100bf4279Sespie /* 200bf4279Sespie * Copyright (c) 1990 Regents of the University of California. 300bf4279Sespie * All rights reserved. 400bf4279Sespie * 500bf4279Sespie * %sccs.include.redist.c% 600bf4279Sespie */ 700bf4279Sespie 89588ddcfSespie 99588ddcfSespie /* 109588ddcfSespie 119588ddcfSespie @deftypefun int xatexit (void (*@var{fn}) (void)) 129588ddcfSespie 139588ddcfSespie Behaves as the standard @code{atexit} function, but with no limit on 149588ddcfSespie the number of registered functions. Returns 0 on success, or @minus{}1 on 159588ddcfSespie failure. If you use @code{xatexit} to register functions, you must use 169588ddcfSespie @code{xexit} to terminate your program. 179588ddcfSespie 189588ddcfSespie @end deftypefun 199588ddcfSespie 209588ddcfSespie */ 219588ddcfSespie 2200bf4279Sespie /* Adapted from newlib/libc/stdlib/{,at}exit.[ch]. 2300bf4279Sespie If you use xatexit, you must call xexit instead of exit. */ 2400bf4279Sespie 25*150b7e42Smiod #ifdef HAVE_CONFIG_H 26*150b7e42Smiod #include "config.h" 27*150b7e42Smiod #endif 2800bf4279Sespie #include "ansidecl.h" 2900bf4279Sespie #include "libiberty.h" 3000bf4279Sespie 3100bf4279Sespie #include <stdio.h> 3200bf4279Sespie 3300bf4279Sespie #include <stddef.h> 3400bf4279Sespie 359588ddcfSespie #if VMS 369588ddcfSespie #include <stdlib.h> 379588ddcfSespie #include <unixlib.h> 389588ddcfSespie #else 3900bf4279Sespie /* For systems with larger pointers than ints, this must be declared. */ 40*150b7e42Smiod PTR malloc (size_t); 419588ddcfSespie #endif 4200bf4279Sespie 43*150b7e42Smiod static void xatexit_cleanup (void); 4400bf4279Sespie 4500bf4279Sespie /* Pointer to function run by xexit. */ 46*150b7e42Smiod extern void (*_xexit_cleanup) (void); 4700bf4279Sespie 4800bf4279Sespie #define XATEXIT_SIZE 32 4900bf4279Sespie 5000bf4279Sespie struct xatexit { 5100bf4279Sespie struct xatexit *next; /* next in list */ 5200bf4279Sespie int ind; /* next index in this table */ 53*150b7e42Smiod void (*fns[XATEXIT_SIZE]) (void); /* the table itself */ 5400bf4279Sespie }; 5500bf4279Sespie 5600bf4279Sespie /* Allocate one struct statically to guarantee that we can register 5700bf4279Sespie at least a few handlers. */ 5800bf4279Sespie static struct xatexit xatexit_first; 5900bf4279Sespie 6000bf4279Sespie /* Points to head of LIFO stack. */ 6100bf4279Sespie static struct xatexit *xatexit_head = &xatexit_first; 6200bf4279Sespie 6300bf4279Sespie /* Register function FN to be run by xexit. 6400bf4279Sespie Return 0 if successful, -1 if not. */ 6500bf4279Sespie 6600bf4279Sespie int xatexit(void (* fn)(void))67*150b7e42Smiodxatexit (void (*fn) (void)) 6800bf4279Sespie { 6900bf4279Sespie register struct xatexit *p; 7000bf4279Sespie 7100bf4279Sespie /* Tell xexit to call xatexit_cleanup. */ 7200bf4279Sespie if (!_xexit_cleanup) 7300bf4279Sespie _xexit_cleanup = xatexit_cleanup; 7400bf4279Sespie 7500bf4279Sespie p = xatexit_head; 7600bf4279Sespie if (p->ind >= XATEXIT_SIZE) 7700bf4279Sespie { 7800bf4279Sespie if ((p = (struct xatexit *) malloc (sizeof *p)) == NULL) 7900bf4279Sespie return -1; 8000bf4279Sespie p->ind = 0; 8100bf4279Sespie p->next = xatexit_head; 8200bf4279Sespie xatexit_head = p; 8300bf4279Sespie } 8400bf4279Sespie p->fns[p->ind++] = fn; 8500bf4279Sespie return 0; 8600bf4279Sespie } 8700bf4279Sespie 8800bf4279Sespie /* Call any cleanup functions. */ 8900bf4279Sespie 9000bf4279Sespie static void xatexit_cleanup(void)91*150b7e42Smiodxatexit_cleanup (void) 9200bf4279Sespie { 9300bf4279Sespie register struct xatexit *p; 9400bf4279Sespie register int n; 9500bf4279Sespie 9600bf4279Sespie for (p = xatexit_head; p; p = p->next) 9700bf4279Sespie for (n = p->ind; --n >= 0;) 9800bf4279Sespie (*p->fns[n]) (); 9900bf4279Sespie } 100