xref: /netbsd-src/external/gpl3/gcc.old/dist/libiberty/xatexit.c (revision 1debfc3d3fad8af6f31804271c18e67f77b4d718)
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*1debfc3dSmrg xatexit (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*1debfc3dSmrg xatexit_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