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