spec

Software for Diffraction

5.3.7. - Adding Site-Dependent C Code



This step applies only to sophisticated end users of spec who understand the C language and need to customize spec for specific, site-dependent uses. Most readers can skip to the next section. Note also, local code can be accessed using the data-pipe facility explained 2.4.6.1 in the Reference Manual.

spec has provisions for end users to add their own C code to the program. User-added code is accessed using the built-in calc() function. If you wish to incorporate non-standard calculations within the spec program, you can do so by adding hooks for the code in the u_hook.c source file. C code that you add should, in general, be limited to calculations. You should avoid I/O, signal catching, etc. Consult CSS for specific information about what is appropriate for including in user-added C code. The geo_*.c files in the standard spec distribution that contain the X-ray diffractometer geometry code are examples of site-dependent code.


Within u_hook.c there is a routine called init_calc(). This routine is called once when spec starts up. Within init_calc(), calls to the routine
ins_calc(num, func)
int     (*func)();
insert the C routine func in a table of functions. These functions are called when calc(num) or calc(num, arg) is typed as a command to spec. The routine func() should be specified as either
func(num)
or
func(num, arg)
double  arg;
depending on whether calc() is to be invoked with one or two arguments.

Any return value from func() is ignored. However, you can have the calc() routine return a value by assigning a number to the variable
extern  double  calc_return;
in func(). If no explicit assignment is made to calc_return, calc() returns zero.

The argument num can be from 0 to 63, but must be chosen not to conflict with any of the other ins_calc() entries already existing in u_hook.c.

You can also create built-in arrays of double precision, floating point numbers that can be used to communicate values between your C code and the user of the program. The routine
ins_asym(x, n, s)
double  **x;
char    *s;
inserts the array x consisting of n elements into the table of built-in symbols. The character pointer s points to a string containing the name used to refer to the array from spec command level. For example,
#define N_PARAM 28
double  *gparam[N_PARAM];
init_calc() {
      ...
      ins_asym(gparam, N_PARAM, "G");
      ...
}
inserts the 28-element array referred to as G[] into the program. Since the array gparam[] is an array of pointers, you must use the indirection operator (*) when referring to the values of the floating point numbers in your C code, as in
      ...
      *gparam[3] = 1.54;
      ...
      if (*gparam[2] == 0)
              ...


If you make any changes to u_hook.c, you must relink and reinstall the spec binary.