xatexit.c 2.1 KB

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