leichter (11/01/82)
This newsgroup got started to discuss proposed extensions to C. It seems to have gotten bogged down in detail discussions of bracketing strategies. Herein is an attempt to return the discussion to something a bit meatier. The following is (essentially) a man page describing an extension I added recently to DECUS C. It was very simple to implement and I've found it quite useful. (Note that this isn't yet in any distributed copies of DECUS C; don't go off and try to find it!) BTW: Note the challenge in the BUGS section! -- Jerry decvax!yale-comix!leichter leichter @ yale ------------------------------------------------------------------------------ 1.0 Specify Initializers and Finalizers ------- ------------ --- ---------- *********** * initial * *********** NAME: initial -- 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 Page 2 initial Specify Initializers and Finalizers 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. 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