User Tools

Site Tools


jvs:cigal:manual:chapter1:customize

CIGAL Reference Manual, Chapter 1 (Topics): customize

Customize -- Adding New C-Language Commands to CIGAL

Note: This section assumes that you have access to CIGAL C-language sources. The best way to learn how to add commands is to look at some examples in the source listings. All command names are defined in a table specified in VNAMES.INI and VNAMES.H, and the command keys are defined in CMD.H. There are three dummy commands already declared, which you can use without needing to change the command tables; they are called:

         user1  user2  user3

These commands are represented by dummy routines in DUMM.C. To add a new command therefore you simply need to create a new subroutine and add it to the list of compiled object modules in the linker command file, CIGAL.LNK. If you add a DEFINE statement to your SYSSTART.IMP file, you can give your new command any name you like, without having to recompile any other file; for example you can give your version of USER1() the name ENHANCE with the DEFINE statement:

      define global 'enhance' 'user1'

Of course, you can avoid this step if you change the USER1 entry in VNAMES.INI and recompile CSTART.C.

The parser and runtime routines handle processing of all command line arguments, so generally the following routines need only be used to get arguments passed to your new routine. In all cases, ARGNUM refers to which argument on the command line (or function call), where ARGNUM 1 is the command itself, so the first argument after the command name is argument 2.

To get simple number arguments, three routines are used to get INT, LONG, or FLOAT arguments; in each case a default value is provided to be returned if the command line argument is missing or null:

   int SETDEF(argnum,idefalt)
      int argnum, idefalt;

   long SETIN4(argnum,ldefalt)
      int argnum; long ldefalt;

   float SETFLT(argnum,defalt)
      int argnum; float defalt;

A more general way to get command arguments is GETARG, which returns a flag indicating the type of argument found (flags defined in CIMPL.H), and the value is returned in X or BUF depending on whether it is a number or character string. BUFMAX is the maximum length of string to be returned, and NCH returns with the actual length:

   int GETARG(argnum,x,buf,bufmax,nch)
      int argnum, bufmax,*nch;
      float *x;  char *buf;

The most general way to get an argument is GETPTR, which does not actually get the argument, it simply returns a flag indicating its type, and returns a long value PTR; PTR can be used by POINTR() to get a PSTRUCT data structure, which is how CIGAL handles all types of variables. PSTRUCT is defined in POINTR.H.

   int GETPTR(argnum,ptr)
      int argnum;  long *ptr;

   struct pstruct *pointr(ptr)
      long ptr;

To actually get at the data pointed to by a PSTRUCT pointer, you first need to call GTVARB, which handles finding the variable, creating buffers if necessary, and checking subscripts. GTVARB returns the variable type flag and fills: NVALS with the number of elements in the specified part of the variable, BUFSIZ with the number of elements available in the current buffer, TOTSIZ with the total number of elements in the variable, and WDSIZ with a flag indicating the size of each individual data element (flags are defined in CIMPL.H). WRITEFLG should be non-zero if the variable is being accessed for writing.

   int GTVARB(p,nvals,bufsiz,totsiz,wdsiz,writeflg)
      struct pstruct *p;
      long *nvals,*bufsiz,*totsiz;
      int *wdsiz,writeflg;

To read data from the variable you call LDVARB whenever the BUFSIZ count gets down to 0. OFFSET is added to BUFSIZ before returning. You should decrement BUFSIZ each time you get a data element, and use either GSTACK or IGSTAK to get individual values.

   LDVARB(p,bufsiz,offset)
      struct pstruct *p;
      long *bufsiz,offset;

   float GSTACK(p)
      struct pstruct *p;

   long IGSTAK(p)
      struct pstruct *p;

Writing values to a variable is done with PSTACK or IPSTAK, again decrementing BUFSIZ with each write. When BUFSIZ gets to 0, or you run out of data, you should call DMPVRB, which does the actual write and then prepares the buffer for the next batch. BUFSIZ returns containing the number of elements you can write to the next buffer. OFFSET is added to BUFSIZ before returning. MOREFLAG should be nonzero if you have more data to write, and 0 when you are done. DMPVRB will look after flushing the data buffers when it finishes; or you can call FLSHIO explicitly.

   PSTACK(x,p)
      float x;
      struct pstruct *p;

   IPSTAK(x,p)
      long x;
      struct pstruct *p;

   DMPVRB(p,bufsiz,moreflag,offset)
      struct pstruct *p;
      long *bufsiz,offset;
      int moreflag;

   FLSHIO(p)
      struct pstruct *p;

These routines can be used for manipulating any CIGAL variable, regardless of whether it is on the internal stack, anywhere in core memory, in an image processor, or a disk file. They also automatically adjust for different size data elements, although if you know you will not be dealing with floating point numbers you will find that the IGSTAK and IPSTAK routines run much faster than the more general floating point versions GSTACK and PSTACK.

For examples of writing data manipulation commands you should look at the commands contained in the files IFUNCS and VFUNCS. These commands also demonstrate how to deal with vector variables, and the cursor.

See Also:
CIGAL Home, CIGAL Manual, Topics List, Manual Help

jvs/cigal/manual/chapter1/customize.txt · Last modified: 2023/02/23 18:43 (external edit)