1 /* 2 * Copyright (c) 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 9 /* 10 11 @deftypefun int xatexit (void (*@var{fn}) (void)) 12 13 Behaves as the standard @code{atexit} function, but with no limit on 14 the number of registered functions. Returns 0 on success, or @minus{}1 on 15 failure. If you use @code{xatexit} to register functions, you must use 16 @code{xexit} to terminate your program. 17 18 @end deftypefun 19 20 */ 21 22 /* Adapted from newlib/libc/stdlib/{,at}exit.[ch]. 23 If you use xatexit, you must call xexit instead of exit. */ 24 25 #include "ansidecl.h" 26 #include "libiberty.h" 27 28 #include <stdio.h> 29 30 #ifdef ANSI_PROTOTYPES 31 #include <stddef.h> 32 #else 33 #define size_t unsigned long 34 #endif 35 36 #if VMS 37 #include <stdlib.h> 38 #include <unixlib.h> 39 #else 40 /* For systems with larger pointers than ints, this must be declared. */ 41 PTR malloc PARAMS ((size_t)); 42 #endif 43 44 static void xatexit_cleanup PARAMS ((void)); 45 46 /* Pointer to function run by xexit. */ 47 extern void (*_xexit_cleanup) PARAMS ((void)); 48 49 #define XATEXIT_SIZE 32 50 51 struct xatexit { 52 struct xatexit *next; /* next in list */ 53 int ind; /* next index in this table */ 54 void (*fns[XATEXIT_SIZE]) PARAMS ((void)); /* the table itself */ 55 }; 56 57 /* Allocate one struct statically to guarantee that we can register 58 at least a few handlers. */ 59 static struct xatexit xatexit_first; 60 61 /* Points to head of LIFO stack. */ 62 static struct xatexit *xatexit_head = &xatexit_first; 63 64 /* Register function FN to be run by xexit. 65 Return 0 if successful, -1 if not. */ 66 67 int 68 xatexit (fn) 69 void (*fn) PARAMS ((void)); 70 { 71 register struct xatexit *p; 72 73 /* Tell xexit to call xatexit_cleanup. */ 74 if (!_xexit_cleanup) 75 _xexit_cleanup = xatexit_cleanup; 76 77 p = xatexit_head; 78 if (p->ind >= XATEXIT_SIZE) 79 { 80 if ((p = (struct xatexit *) malloc (sizeof *p)) == NULL) 81 return -1; 82 p->ind = 0; 83 p->next = xatexit_head; 84 xatexit_head = p; 85 } 86 p->fns[p->ind++] = fn; 87 return 0; 88 } 89 90 /* Call any cleanup functions. */ 91 92 static void xatexit_cleanup()93xatexit_cleanup () 94 { 95 register struct xatexit *p; 96 register int n; 97 98 for (p = xatexit_head; p; p = p->next) 99 for (n = p->ind; --n >= 0;) 100 (*p->fns[n]) (); 101 } 102