/*
 *				i n i t i a . h
 */

/*)LIBRARY
*/

#ifdef	DOCUMENTATION

title	initial	Specify Initializers and Finalizers
index		Specify initializers and finalizers

synopsis

	 #include <initia.h>

	 INITIAL
	 { initial-code-block };

	 FINAL
	 { final-code-block };

description

	The macros defined in this module provide a facility for
	module-specific initialization and finalization code.  The code
	in the initial-code-block is called as a normal C function before
	main() is called; the final-code-block is called on exit, just after
	wrapup().

	Neither call passes any arguments.

	Any number of modules in an image may independently declare
	initializers or finalizers; all of them will be called at startup or
	exit.  However, it is impossible to predict what order the calls will
	be made in, and programs should not rely on any particular ordering.

	A typical use of initializers and finalizers is the following:
	Suppose you have a package that supports access to some on-disk data
	base; a user of the package will call a lookup and an update function.
	The file containing the data base must be opened before any operations
	on it can take place, and it should be closed when the program is
	finished.  (Assume that the package maintains some sort of resident
	buffer which it must flush.)  There are two conventional approaches
	to solving this problem:  Have the lookup and update functions check
	the file on each call, and open it if necessary - which could be quite
	expensive if they are very small functions, and in any case does not
	solve the problem of properly closing the file - or have the main
	program call an initialization and finalization function at the proper
	time.  The problem with this latter approach is lack of modularity -
	the main program ought not to have to know that the module needs
	initialization or finalization.

	The solution using these macros is straightforward.  The defining
	module includes the calls:

		INITIAL
		{ open-the-data-base };

		FINAL
		{ flush-buffers-and-close-the-data-base };

	The wrapup() function is treated like a built-in finalizer; however,
	it is guaranteed to execute before any other finalizers.  (The module
	defining wrapup() may declare an initializer or finalizer if it
	wishes; it will be treated just like all other initializers and
	finalizers.)

	If any finalizer (or wrapup()) calls exit(), the program exits
	immediately.

	Notes:  Using INITIAL will declare a static function named $init$(),
	and a (char *) named $init_; similarly, FINAL will declare $finl$()
	and $finl_.  Also, both INITIAL and FINAL generate dsect commands.
	Since C provides no way to "remember" the current dsect, both macros
	issue a dsect "" command when they are done, restoring the C default
	dsect.

	While it is a poor idea to write code that depends on the order in
	which initializers and finalizers are executed, this can be useful
	information to have for debugging.  Execution is always in the order
	that the modules involved were examined by the task builder or linker.
	When the modules are named explicitly, this will just be the order in
	which they were named.  When the modules come from a library, it
	will be extremely difficult to predict the order in which they will
	be extracted and linked in.

	Warning:  While initializers and finalizers provide some modularity
	to package initialization and finalization, they are not a panacea.
	For example, if package A calls routines in package B from within
	its initializers, and package B also declares initializers, the
	correct functioning of a program that includes both - hence, of any
	program using package A - will be problematical.

internal

	The macros operate by leaving a list of (pointers to) functions to be
	called in psects $INIT$ and $FINL$.  In order to be able to determine
	the beginning and end of these psects, the psects $INIT, $FINL,
	$INIT., and $FINL., are also reserved.  These psects must not actually
	contain any data; they exist solely to provide well-defined endpoints
	to the initialization and finalization list.  The names are
	consecutive in alphabetical sequence, so the Task Builder will place
	them in order. The RT11 Linker, however - and the Task Builder with
	the /SQ switch - place psects in the order they are encountered.
	Since it impossible to predict what order the various modules will be
	seen by the linking program, it is essential that EVERY module that
	refers to any of these psects refer to the two related ones as well,
	and in the correct order.

bugs

	Requires the DECUS C dsect commands; hence, very non-portable.  It
	may be possible to provide the same functionality using different
	techniques; if not, what's wrong with your implementation?

author

	Jerry Leichter

#endif

/*
)EDITLEVEL=05
 * Edit history
 * 0.0 19-Jul-82 JSL	Invention
 * 0.1 22-Nov-82 JSL	Documentation cleanups only; much of the documentation
 *			gets duplicated in initia.mac.
 */

#define INITIAL dsect"$init ";dsect"$init$";static char *$init_ = &$init$;dsect"$init.";dsect"";static $init$()
	
#define FINAL dsect"$finl ";dsect"$finl$";static char *$finl_ = &$finl$;dsect"$finl.";dsect"";static $finl$()
	
/*
 * Sorry about the scrunched code; DECUS C has some size limits on #define
 * lines that are a pain.  Here's the code "in the clear":
 *
 * #define INITIAL dsect "$init ";	\	-- Declare the dsects in the
 *	dsect"$init$";			\		right order
 *	static char *$init_ = &$init$;	\	-- Pointer to the function
 *	dsect"$init.";			\	-- Another dsect in order
 *	dsect"";			\	-- Back to the default
 *	static $init$()				-- Declare the function
 *
 * The code for FINAL is essentially the same.
 */
