133965Sjdp/* 233965Sjdp * Copyright (c) 1990 Regents of the University of California. 333965Sjdp * All rights reserved. 433965Sjdp * 533965Sjdp * %sccs.include.redist.c% 633965Sjdp */ 733965Sjdp 889857Sobrien 989857Sobrien/* 1089857Sobrien 1189857Sobrien@deftypefun int xatexit (void (*@var{fn}) (void)) 1289857Sobrien 1389857SobrienBehaves as the standard @code{atexit} function, but with no limit on 1489857Sobrienthe number of registered functions. Returns 0 on success, or @minus{}1 on 1589857Sobrienfailure. If you use @code{xatexit} to register functions, you must use 1689857Sobrien@code{xexit} to terminate your program. 1789857Sobrien 1889857Sobrien@end deftypefun 1989857Sobrien 2089857Sobrien*/ 2189857Sobrien 2233965Sjdp/* Adapted from newlib/libc/stdlib/{,at}exit.[ch]. 2333965Sjdp If you use xatexit, you must call xexit instead of exit. */ 2433965Sjdp 25218822Sdim#ifdef HAVE_CONFIG_H 26218822Sdim#include "config.h" 27218822Sdim#endif 2833965Sjdp#include "ansidecl.h" 2933965Sjdp#include "libiberty.h" 3033965Sjdp 3133965Sjdp#include <stdio.h> 3233965Sjdp 3333965Sjdp#include <stddef.h> 3433965Sjdp 35104834Sobrien#if VMS 36104834Sobrien#include <stdlib.h> 37104834Sobrien#include <unixlib.h> 38104834Sobrien#else 3933965Sjdp/* For systems with larger pointers than ints, this must be declared. */ 40218822SdimPTR malloc (size_t); 41104834Sobrien#endif 4233965Sjdp 43218822Sdimstatic void xatexit_cleanup (void); 4433965Sjdp 4533965Sjdp/* Pointer to function run by xexit. */ 46218822Sdimextern void (*_xexit_cleanup) (void); 4733965Sjdp 4833965Sjdp#define XATEXIT_SIZE 32 4933965Sjdp 5033965Sjdpstruct xatexit { 5133965Sjdp struct xatexit *next; /* next in list */ 5233965Sjdp int ind; /* next index in this table */ 53218822Sdim void (*fns[XATEXIT_SIZE]) (void); /* the table itself */ 5433965Sjdp}; 5533965Sjdp 5633965Sjdp/* Allocate one struct statically to guarantee that we can register 5733965Sjdp at least a few handlers. */ 5833965Sjdpstatic struct xatexit xatexit_first; 5933965Sjdp 6033965Sjdp/* Points to head of LIFO stack. */ 6133965Sjdpstatic struct xatexit *xatexit_head = &xatexit_first; 6233965Sjdp 6333965Sjdp/* Register function FN to be run by xexit. 6433965Sjdp Return 0 if successful, -1 if not. */ 6533965Sjdp 6633965Sjdpint 67218822Sdimxatexit (void (*fn) (void)) 6833965Sjdp{ 6933965Sjdp register struct xatexit *p; 7033965Sjdp 7133965Sjdp /* Tell xexit to call xatexit_cleanup. */ 7233965Sjdp if (!_xexit_cleanup) 7333965Sjdp _xexit_cleanup = xatexit_cleanup; 7433965Sjdp 7533965Sjdp p = xatexit_head; 7633965Sjdp if (p->ind >= XATEXIT_SIZE) 7733965Sjdp { 7833965Sjdp if ((p = (struct xatexit *) malloc (sizeof *p)) == NULL) 7933965Sjdp return -1; 8033965Sjdp p->ind = 0; 8133965Sjdp p->next = xatexit_head; 8233965Sjdp xatexit_head = p; 8333965Sjdp } 8433965Sjdp p->fns[p->ind++] = fn; 8533965Sjdp return 0; 8633965Sjdp} 8733965Sjdp 8833965Sjdp/* Call any cleanup functions. */ 8933965Sjdp 9033965Sjdpstatic void 91218822Sdimxatexit_cleanup (void) 9233965Sjdp{ 9333965Sjdp register struct xatexit *p; 9433965Sjdp register int n; 9533965Sjdp 9633965Sjdp for (p = xatexit_head; p; p = p->next) 9733965Sjdp for (n = p->ind; --n >= 0;) 9833965Sjdp (*p->fns[n]) (); 9933965Sjdp} 100