1 | /*
|
---|
2 | * Copyright (c) 1990 Regents of the University of California.
|
---|
3 | * All rights reserved.
|
---|
4 | *
|
---|
5 | * %sccs.include.redist.c%
|
---|
6 | */
|
---|
7 |
|
---|
8 |
|
---|
9 | /*
|
---|
10 |
|
---|
11 | @deftypefun int xatexit (void (*@var{fn}) (void))
|
---|
12 |
|
---|
13 | Behaves as the standard @code{atexit} function, but with no limit on
|
---|
14 | the number of registered functions. Returns 0 on success, or @minus{}1 on
|
---|
15 | failure. If you use @code{xatexit} to register functions, you must use
|
---|
16 | @code{xexit} to terminate your program.
|
---|
17 |
|
---|
18 | @end deftypefun
|
---|
19 |
|
---|
20 | */
|
---|
21 |
|
---|
22 | /* Adapted from newlib/libc/stdlib/{,at}exit.[ch].
|
---|
23 | If you use xatexit, you must call xexit instead of exit. */
|
---|
24 |
|
---|
25 | #include "ansidecl.h"
|
---|
26 | #include "libiberty.h"
|
---|
27 |
|
---|
28 | #include <stdio.h>
|
---|
29 |
|
---|
30 | #ifdef ANSI_PROTOTYPES
|
---|
31 | #include <stddef.h>
|
---|
32 | #else
|
---|
33 | #define size_t unsigned long
|
---|
34 | #endif
|
---|
35 |
|
---|
36 | #if VMS
|
---|
37 | #include <stdlib.h>
|
---|
38 | #include <unixlib.h>
|
---|
39 | #else
|
---|
40 | /* For systems with larger pointers than ints, this must be declared. */
|
---|
41 | PTR malloc PARAMS ((size_t));
|
---|
42 | #endif
|
---|
43 |
|
---|
44 | static void xatexit_cleanup PARAMS ((void));
|
---|
45 |
|
---|
46 | /* Pointer to function run by xexit. */
|
---|
47 | extern void (*_xexit_cleanup) PARAMS ((void));
|
---|
48 |
|
---|
49 | #define XATEXIT_SIZE 32
|
---|
50 |
|
---|
51 | struct xatexit {
|
---|
52 | struct xatexit *next; /* next in list */
|
---|
53 | int ind; /* next index in this table */
|
---|
54 | void (*fns[XATEXIT_SIZE]) PARAMS ((void)); /* the table itself */
|
---|
55 | };
|
---|
56 |
|
---|
57 | /* Allocate one struct statically to guarantee that we can register
|
---|
58 | at least a few handlers. */
|
---|
59 | static struct xatexit xatexit_first;
|
---|
60 |
|
---|
61 | /* Points to head of LIFO stack. */
|
---|
62 | static struct xatexit *xatexit_head = &xatexit_first;
|
---|
63 |
|
---|
64 | /* Register function FN to be run by xexit.
|
---|
65 | Return 0 if successful, -1 if not. */
|
---|
66 |
|
---|
67 | int
|
---|
68 | xatexit (fn)
|
---|
69 | void (*fn) PARAMS ((void));
|
---|
70 | {
|
---|
71 | register struct xatexit *p;
|
---|
72 |
|
---|
73 | /* Tell xexit to call xatexit_cleanup. */
|
---|
74 | if (!_xexit_cleanup)
|
---|
75 | _xexit_cleanup = xatexit_cleanup;
|
---|
76 |
|
---|
77 | p = xatexit_head;
|
---|
78 | if (p->ind >= XATEXIT_SIZE)
|
---|
79 | {
|
---|
80 | if ((p = (struct xatexit *) malloc (sizeof *p)) == NULL)
|
---|
81 | return -1;
|
---|
82 | p->ind = 0;
|
---|
83 | p->next = xatexit_head;
|
---|
84 | xatexit_head = p;
|
---|
85 | }
|
---|
86 | p->fns[p->ind++] = fn;
|
---|
87 | return 0;
|
---|
88 | }
|
---|
89 |
|
---|
90 | /* Call any cleanup functions. */
|
---|
91 |
|
---|
92 | static void
|
---|
93 | xatexit_cleanup ()
|
---|
94 | {
|
---|
95 | register struct xatexit *p;
|
---|
96 | register int n;
|
---|
97 |
|
---|
98 | for (p = xatexit_head; p; p = p->next)
|
---|
99 | for (n = p->ind; --n >= 0;)
|
---|
100 | (*p->fns[n]) ();
|
---|
101 | }
|
---|