5.3.5. - 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.2 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(int num, 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(int num)or
func(int num, 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(double **x, int n, 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.