Important System Components

This section contains short instructions for the use of the most important library functions. I do not specify the parameters of the functions in the following examples. The declarations of the functions, structures, and constants necessary for their use can be found in the Appendices.

Opening and closing files

To open files, use function SIA_file_open (). This function opens a file using fopen (), and issues error or warning message if failed. Using this function to open text files, you automatically allow modifications of the file open regimes, namely: If the file name is an asterisk '*', the output is directed to the current log file. Write/Append modes can be modified by calling module setup before current module. The function SIA_fclose ( FILE** f ) closes the file *f using fclose ( *f ), but it also assigns *f = NULL afterwards, and does not attempt closing file which has been already closed. Thus this function is a litle safer during careless coding of I/O operations.

Error handling and messages to the user

Two text files are generally opened for the messages output by the module: log and error files. These files can be individual for each module; at startup, both of these files are associated with the standard output . The Log files receive all information messages printed by the module, and the error file contains all error and warning messages.

Two functions are available for printing of the texts of the message and informing the monitor of an error situation. SIA_message () simply prints the message into the log file, and it can be used at any moment during Edit or Process phases. If an error is detected, use SIA_err () to report it. The first parameter of this function is the error-handling routine, which may be SIA_abort_now, SIA_abort, or SIA_ignore, in the order of decreasing severity of the error. Also, you can provide your own routine, i.g., for interactive error correction. 

SIA_err () does not print the error message, but passes it to the error-handling routine. The error-handling functions currently defined act as follows: 

Although it is possible to use SIA_err () during Process phase, it hardly makes any sense to do so, except if you need to terminate the entire processing immediately, using SIA_abort_now. The latter, however, is very rough to the rest of the modules

Memory allocation

When coding the C++ libraries, there is typically no need to allocate additional memory.  However, four memory allocation functions are available: SIA_malloc(), SIA_realloc() , SIA_allocate(), and SIA_free(). The first two work as the corresponding C library routines, but they maintain their own memory allocation tables, which provides some additional means for dubugging when a memory corruption occurs. The third function behaves as SIA_malloc() when the pointer provided in the argument is NULL, or as SIA_realloc() otherwise. 

SIA_free() deallocates the memory block, assigns NULL to the corresponding pointer, and performs garbage collection (merging of adjacent free memory blocks). If an error occurs during memory allocation, these functions issue error messages. To copy a memory block to an (possibly) overlapping location, use SIA_memmove(). Note that SIA_free() is declared as follows: void SIA_free( void ** ). Thus you need to supply the address of the pointer in its parameter. Never use free () to deallocate the memory allocated by SIA_malloc() or other memory allocating routines described above.

To allocate temporary memory for use within a subroutine, there is a useful macro 

ALLOC_TEMP ( number_of_fields, field_type )  

This macro uses function alloca();  note that this memory is released automatically when the current subroutine exits.

Communications between the modules

Occasionally, modules need to communicate between each other, e.g., in order to share a common data structure. The typical examples are modules *endif, *endrep, and *back, which first locate corresponding *if and *elseif modules during Edit phase, and manipulate their input and output trace sequences during the Process phase. 

The communication between the modules is implemented via a mechanism of messages. Using SIA_define_message (), each module can issue an arbitrary number of messages which are put into a message stack maintained by the monitor. Each message contains a pointer to the issuing module and a pointer to the message data. Each module can access the last message using, e.g., 

SIA_MESAGE *m = SIA_get_message() , 

and to get all previous messages repeatedly using m = m->pred. The identity of the module that had stored this message can be established using the field m->module. Any message m can be erased using 

delete m.