1169695Skan/* 2169695Skan * Copyright (c) 1990 Regents of the University of California. 3169695Skan * All rights reserved. 4169695Skan * 5169695Skan * %sccs.include.redist.c% 6169695Skan */ 7169695Skan 8169695Skan 9169695Skan/* 10169695Skan 11169695Skan@deftypefun int xatexit (void (*@var{fn}) (void)) 12169695Skan 13169695SkanBehaves as the standard @code{atexit} function, but with no limit on 14169695Skanthe number of registered functions. Returns 0 on success, or @minus{}1 on 15169695Skanfailure. If you use @code{xatexit} to register functions, you must use 16169695Skan@code{xexit} to terminate your program. 17169695Skan 18169695Skan@end deftypefun 19169695Skan 20169695Skan*/ 21169695Skan 22169695Skan/* Adapted from newlib/libc/stdlib/{,at}exit.[ch]. 23169695Skan If you use xatexit, you must call xexit instead of exit. */ 24169695Skan 25169695Skan#ifdef HAVE_CONFIG_H 26169695Skan#include "config.h" 27169695Skan#endif 28169695Skan#include "ansidecl.h" 29169695Skan#include "libiberty.h" 30169695Skan 31169695Skan#include <stdio.h> 32169695Skan 33169695Skan#include <stddef.h> 34169695Skan 35169695Skan#if VMS 36169695Skan#include <stdlib.h> 37169695Skan#include <unixlib.h> 38169695Skan#else 39169695Skan/* For systems with larger pointers than ints, this must be declared. */ 40169695SkanPTR malloc (size_t); 41169695Skan#endif 42169695Skan 43169695Skanstatic void xatexit_cleanup (void); 44169695Skan 45169695Skan/* Pointer to function run by xexit. */ 46169695Skanextern void (*_xexit_cleanup) (void); 47169695Skan 48169695Skan#define XATEXIT_SIZE 32 49169695Skan 50169695Skanstruct xatexit { 51169695Skan struct xatexit *next; /* next in list */ 52169695Skan int ind; /* next index in this table */ 53169695Skan void (*fns[XATEXIT_SIZE]) (void); /* the table itself */ 54169695Skan}; 55169695Skan 56169695Skan/* Allocate one struct statically to guarantee that we can register 57169695Skan at least a few handlers. */ 58169695Skanstatic struct xatexit xatexit_first; 59169695Skan 60169695Skan/* Points to head of LIFO stack. */ 61169695Skanstatic struct xatexit *xatexit_head = &xatexit_first; 62169695Skan 63169695Skan/* Register function FN to be run by xexit. 64169695Skan Return 0 if successful, -1 if not. */ 65169695Skan 66169695Skanint 67169695Skanxatexit (void (*fn) (void)) 68169695Skan{ 69169695Skan register struct xatexit *p; 70169695Skan 71169695Skan /* Tell xexit to call xatexit_cleanup. */ 72169695Skan if (!_xexit_cleanup) 73169695Skan _xexit_cleanup = xatexit_cleanup; 74169695Skan 75169695Skan p = xatexit_head; 76169695Skan if (p->ind >= XATEXIT_SIZE) 77169695Skan { 78169695Skan if ((p = (struct xatexit *) malloc (sizeof *p)) == NULL) 79169695Skan return -1; 80169695Skan p->ind = 0; 81169695Skan p->next = xatexit_head; 82169695Skan xatexit_head = p; 83169695Skan } 84169695Skan p->fns[p->ind++] = fn; 85169695Skan return 0; 86169695Skan} 87169695Skan 88169695Skan/* Call any cleanup functions. */ 89169695Skan 90169695Skanstatic void 91169695Skanxatexit_cleanup (void) 92169695Skan{ 93169695Skan register struct xatexit *p; 94169695Skan register int n; 95169695Skan 96169695Skan for (p = xatexit_head; p; p = p->next) 97169695Skan for (n = p->ind; --n >= 0;) 98169695Skan (*p->fns[n]) (); 99169695Skan} 100