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