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