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.