xref: /dflybsd-src/contrib/binutils-2.27/libiberty/xatexit.c (revision e656dc90e3d65d744d534af2f5ea88cf8101ebcf)
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*a9fa9459Szrj xatexit (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*a9fa9459Szrj xatexit_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