sl@0: /* ATEXIT.C sl@0: * sl@0: * Portions Copyright (c) 1990-2006 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: */ sl@0: sl@0: /* sl@0: * Copyright (c) 1990 Regents of the University of California. sl@0: * All rights reserved. sl@0: * sl@0: * %sccs.include.redist.c% sl@0: */ sl@0: sl@0: /* sl@0: FUNCTION sl@0: <>---request execution of functions at program exit sl@0: sl@0: INDEX sl@0: atexit sl@0: sl@0: ANSI_SYNOPSIS sl@0: #include sl@0: int atexit(void (*<[function]>)(void); sl@0: sl@0: TRAD_SYNOPSIS sl@0: #include sl@0: int atexit((<[function]>) sl@0: void (*<[function]>)(); sl@0: sl@0: DESCRIPTION sl@0: You can use <> to enroll functions in a list of functions that sl@0: will be called when your program terminates normally. The argument is sl@0: a pointer to a user-defined function (which must not require arguments and sl@0: must not return a result). sl@0: sl@0: The functions are kept in a LIFO stack; that is, the last function sl@0: enrolled by <> will be the first to execute when your program sl@0: exits. sl@0: sl@0: There is no built-in limit to the number of functions you can enroll sl@0: in this list; however, after every group of 32 functions is enrolled, sl@0: <> will call <> to get space for the next part of the sl@0: list. The initial list of 32 functions is statically allocated, so sl@0: you can always count on at least that many slots available. sl@0: sl@0: RETURNS sl@0: <> returns <<0>> if it succeeds in enrolling your function, sl@0: <<-1>> if it fails (possible only if no space was available for sl@0: <> to extend the list of functions or the library globals could not sl@0: be allocated). sl@0: sl@0: PORTABILITY sl@0: <> is required by the ANSI standard, which also specifies that sl@0: implementations must support enrolling at least 32 functions. sl@0: sl@0: Supporting OS subroutines required: <>, <>, <>, sl@0: <>, <>, <>, <>. sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: /* sl@0: * Register a function to be performed at exit. sl@0: * NB. MSVC 5.0 has a built-in prototype for atexit, so we have to use a #define sl@0: * to map the name atexit to _epoc32_atexit sl@0: */ sl@0: sl@0: /* sl@0: @return On Success, returns 0. sl@0: On Failure, returns -1. sl@0: */ sl@0: sl@0: EXPORT_C int sl@0: _epoc32_atexit (void (*fn)(void)) sl@0: { sl@0: register struct _atexit *p; sl@0: struct _reent *rp = _REENT2; sl@0: if (!rp) sl@0: return -1; // Memory for library globals is not allocated (errno not set). sl@0: sl@0: if ((p = rp->_atexit) == NULL) sl@0: rp->_atexit = p = &rp->_atexit0; sl@0: if (p->_ind >= _ATEXIT_SIZE) sl@0: { sl@0: if ((p = (struct _atexit *) malloc (sizeof *p)) == NULL) sl@0: return -1; sl@0: p->_ind = 0; sl@0: p->_next = rp->_atexit; sl@0: rp->_atexit = p; sl@0: } sl@0: p->_fns[p->_ind++] = fn; sl@0: return 0; sl@0: } sl@0: sl@0: EXPORT_C void sl@0: _atexit_processing_r (struct _reent *rp) sl@0: { sl@0: register struct _atexit *p; sl@0: register int n; sl@0: sl@0: for (p = rp->_atexit; p; p = p->_next) sl@0: for (n = p->_ind; --n >= 0;) sl@0: (*p->_fns[n]) (); sl@0: if (rp->__cleanup) sl@0: (*rp->__cleanup) (rp); sl@0: }