Philip L. Budne
Consultant
As the title suggests, the target machine is anything that has a C compiler and provides provides a Un*x-like (ie; POSIX) environment. The target machine should have;
System dependencies are all isolated in library routines and a few C preprocessor macros (for inline implementation of SIL operations). The supplied code should be machine independent, and a binary of snobol4 should not be needed to bootstrap the system.
The "autoconf" script determines which file from the config directory to use, and includes it in config.m4. The config.m4 file is included into Makefile2.m4 using the m4 macro processor, and contains make variable assignments (ie; VAR=VALUE) and m4 macro invocations.
Autoconf checks for the file "local-config" and if it exists includes it at the end of config.m4.
The following are variables which may need to be set in some environments;
The path for the C compiler to use.
The command to use to create "make depend" output. The default value is "./cc-M" If your C compiler (see CC, above) supports this function directly, CCM can be reset in system.m4.
The flags/path to use to link a C program with math routines (may be needed for the pow() function, or other implementation of exp.c. The default value is '-lm'.
Optimization, debug, and profiling flags to pass to the C compiler. The default is "-O".
Name of the main source file to make and use. Should be either isnobol4 (the default), which has functions reordered so that gcc can inline functions more effectively. If you are not using gcc, or not using the inline-functions option, you can use the value "snobol4" and avoid the function reordering steps in the Makefile.
Object files not in snolib.a for functions referenced from pml.h (see load.doc).
All library source file paths are defined in variables, so that alternate versions may be substituted. Typical variables of this type are CONVERT_C, LOAD_C, EXP_C, MSTIME_C. See the section on library functions for descriptions of the files, and the alternate versions included in the distribution.
Each of the following macros can be used to add files or flags to a make variable (in place of the += syntax available in some make programs). The m4 quote start and end characters have been changed from accent grave and apostrophe to open and close brackets. Values passed to the m4 macros should be quoted for safety.
Add argument to CPPFLAGS (used in make depend, .c file compilation).
Add argument to flags used to compile .c files.
Add argument to list of source files processed in "make depend".
Add argument to list of object files used to construct snolib.a
Add argument to flags passed to "cc" command used to link snobol4 executable.
The following are cpp macro names which can be by adding ADD_CPPFLAGS([-D<symbol>]) or ADD_CPPFLAGS([-D<symbol>=<value>]) to system.m4 or local-config.
DCMP_BYTES should be defined if sizeof(int_t) != sizeof(real_t). If DCMP_BYTES is defined, descriptor equality will be determined using bcmp().
Example: ADD_CPPFLAGS([-DDMP_BYTES]). See also INT_T and REAL_T.
If INT_T is defined, it should be the C type to use for integer values and addresses. INT_T must be large enough to hold a pointer. The default type used for int_t is "long".
Example: ADD_CPPFLAGS([-DINT_T="long long"]). See also REAL_T.
Disable use of bitfields to store descriptor "v" (size) field. Some compilers have problems with bitfields, yields no storage benefits, or causes performance penalties. Bitfields are used to try and fit the 8-bit flags and 24-bit size fields into one 32-bit word. On Alpha systems the "a" field is 64-bits long (due to pointer size). Since the combined "f" and "v" fields will be padded to 64-bits for alignment there is no benefit to using bitfields in this situation. See also VFLD_T.
If REAL_T is defined, it should be the C type to use for real values. The default type used for real_t is "float". On Alpha OSF/1 systems the "a" field will be 64-bits (to hold pointers), so REAL_T is declared as double to take advantage of the available space.
Example: ADD_CPPFLAGS([-DREAL_T=double]). See also INT_T.
The descriptor "v" field is used to hold the size of objects in bytes. When NO_BITFIELDS is not defined, the "v" field is a 24-bit unsigned bitfield. When NO_BITFIELDS is defined VFLD_T is used (and defaults to "int"). VFLD_T should be able to hold 31-bit unsigned quantities.
Directory to use for temporary files (default "/tmp").
Used with lib/generic/mstime.c; Number of ticks per second, as returned by times() system call (default: 60).
Return type for signal handler functions (default: void).
Prevents "poor-mans loading" of SPITBOL EXIT() function emulation. There is a dummy function available for addition to snolib for the execute() function (ie; ADD_OBJS([execute.o])) in case execl() is not available. This may be preferable to eliminating EXIT() altogether for compatibility reasons.
Prevents "poor-mans loading" of SPITBOL HOST() function emulation. There are dummy functions available for addition to snolib for the system() and getenv() functions (ie; ADD_OBJS([system.o])) in case either or both functions are not available.
Prevents "poor-mans loading" of the following functions; SQRT(), EXP(), LOG(), CHOP(), The functions can also be eliminated individually by setting one of NO_PML_SQRT, NO_PML_EXP, NO_PML_LOG, or NO_PML_CHOP. Setting NO_PML_TRIG eliminates SIN(), COS() and TAN().
Prevents "poor-mans loading" of the SITBOL compatible FILE() predicate.
Prevents "poor-mans loading" of the SITBOL compatible DELETE() function.
Prevents "poor-mans loading" of the SITBOL compatible RENAME() function.
Should be set on systems where there is no system supplied "off_t" typedef available in either <sys/types.h> or <unistd.h>. The "long" datatype will be used for file offsets in this case.
The are macros defined in macros.h which call may call library functions.
DCMP compares two descriptors. By default it compares the members one at a time. On systems where int_t (see INT_T) does not access the entire "a" field, DCMP_BYTES may need to be defined, in which case DCMP calls the "bcmp()" library function.
Uses bcopy() to move blocks of descriptors. The source and destination may overlap, a situation which many versions of memcpy() will not deal with correctly!!
ANSI C memmove() handles overlap, but may be inefficient.
A portable, efficient C bcopy routine is provided in lib/auxil/bcopy.c
Uses bcopy() to append strings. See MOVBLK macro.
Uses bzero() to clear blocks of descriptors.
A generic C bzero routine is provided lib/auxil/bzero.c
The remainder of this file describes the various system-dependent library files, the functions they provide, and the C library functions they require.
Convert from strings to numbers. Two versions of convert.c are provided: lib/ansi/convert.c which uses strtol() and strtod(), and lib/generic/convert.c which uses sscanf().
Contains date() for formatting the current data and time for the SNOBOL4 DATE() function. Calls time(), localtime() and sprintf().
Allocate dynamic storage region, and forewarn the operating system that access behavior may be non-sequential (particularly during storage regeneration). Two versions are provided: generic/dynamic.c, which uses malloc(), and bsd/dynamic.c which calls malloc() and then vadvise().
Contains endex() which is called to end execution. Calls exit() for normal termination and abort() for abnormal termination!
Provides execute() function for SPITBOL HOST() simulation.
Perform integer and real exponentiation for SNOBOL4 exponentiation operator. Two versions are provided: generic/exp.c which uses the pow() library function, and dummy/exp.c which causes fatal errors (as specified by the SIL language manual) to be used if suitable library functions are not available (or if the size of the library functions is objectionable).
pow(x,y) is a venerable function and should be widely available. If it is not, it could be simulated (ie; in pow.c) using exp() and log(), or similar functions (such as expm1() and log1p()).
pow() is used for integer exponentiation. It might be more efficient to decompose y (bitwise) into powers of two and use repeated multiplies from the series x, x^2, x^4 ...
Provides tcp_open() function to establish a connection to a TCP server.
Initialization functions init_args() and init(). init_args() is called from main() to parse command line arguments, using getopt() and sscanf(). A version of getopt is available in lib/getopt.c.
init() is called from by the SIL INIT macro (first line of v311.sil) to initialize storage and signal handling. init() calls bzero() and signal().
Convert integers from binary to strings using sprintf.
Provide I/O support (io_xxx) using the C standard I/O package. Calls: fopen, fclose, fgets, fprintf, rewind, bzero (see above), malloc, free, exit, strcpy, strncpy, strlen.
Provides functions load(), link() and unload() (SIL macros LOAD, LINK, UNLOAD) for the SNOBOL4 LOAD() and UNLOAD() functions. Two versions of load.c are provided: dummy/load.c which causes fatal errors as specified in the SIL language reference, and bsd/load.c which uses the loader (ld) to provide a portable implementation for systems using a.out object format.
Provides user runtime in milliseconds. Six (!!) versions of mstime.c are provided:
Convert from binary floating point to string. Should NOT resort to use of scientific notation. Uses sprintf() %f format which is usually suboptimal (may have trailing zeroes). Does not use %g format, since it is less widely available, may resort to scientific notation, and may omit period and ALL trailing zeroes on whole numbers.
Better results may be possible by using fconvert(), and gconvert() (or fcvt() and gcvt()) when available, along with a modicum of intelligence and/or post-processing.
Provides term_input() function which returns a stdio stream (FILE *) connected to the terminal (typically via the stderr file descriptor) for read. Three versions are provided;
Provides fisatty(), tty_save(), tty_restore(), tty_close(), and tty_mode() functions for saving and manipulating terminal mode and echo.
provides hwname() and osname() functions for use by SPITBOL HOST() function emulation. Two versions are provided. Both check for HWNAME and OSNAME defines, and use them if they exist. HWNAME and/or OSNAME can be set using the SYSDEFS make variable, ie;
[SYSDEFS=-DHWNAME="yoyodyne-2000" -DOSNAME="yoyo-os 4.0"]