/*
 *				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 };

	Note:  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.

	If a user-written wrapup() function calls exit() recursively, any
	finalizers declared will still be called; however, if any finalizer
	calls exit(), the program exits immediately.

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
 */

#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.
 */
