Initial Commit
[libctiny.git] / initterm.cc
blob9cb22507efce1ae5bbc5a4a5311125feba6b1946
1 //==========================================
2 // LIBCTINY - Matt Pietrek 2001
3 // MSDN Magazine, January 2001
4 // ==========================================
6 #include "libctiny.h"
7 #include <windows.h>
8 #include <malloc.h>
9 #include "initterm.h"
11 #pragma data_seg(".CRT$XCA")
12 _PVFV __xc_a[] = { NULL };
13 #pragma data_seg(".CRT$XCZ")
14 _PVFV __xc_z[] = { NULL };
17 #pragma data_seg(".CRT$XIA")
18 _PVFV __xi_a[] = { NULL };
19 #pragma data_seg(".CRT$XIZ")
20 _PVFV __xi_z[] = { NULL };
22 #pragma data_seg(".CRT$XTA")
23 _PVFV __xt_a[] = { NULL };
24 #pragma data_seg(".CRT$XTZ")
25 _PVFV __xt_z[] = { NULL };
27 #pragma data_seg(".CRT$XPA")
28 _PVFV __xp_a[] = { NULL };
29 #pragma data_seg(".CRT$XPZ")
30 _PVFV __xp_z[] = { NULL };
33 #pragma data_seg() /* reset */
35 #pragma comment(linker, "/merge:.CRT=.data")
37 typedef void (__cdecl *_PVFV)();
39 void __cdecl _initterm(
40 _PVFV * pfbegin,
41 _PVFV * pfend
42 ) {
43 // walk the table of function pointers from the bottom up, until
44 // the end is encountered. Do not skip the first entry. The initial
45 // value of pfbegin points to the first valid entry. Do not try to
46 // execute what pfend points to. Only entries before pfend are valid.
47 while (pfbegin < pfend)
49 // if current table entry is non-NULL, call thru it.
50 if (*pfbegin != NULL)
51 (**pfbegin)();
52 ++pfbegin;
56 static _PVFV * pf_atexitlist = 0;
57 static unsigned max_atexitlist_entries = 0;
58 static unsigned cur_atexitlist_entries = 0;
60 void __cdecl _atexit_init() {
61 max_atexitlist_entries = 32;
62 pf_atexitlist = (_PVFV *)calloc( max_atexitlist_entries,
63 sizeof(_PVFV*) );
66 int __cdecl atexit(_PVFV func ) {
67 if (cur_atexitlist_entries < max_atexitlist_entries)
69 pf_atexitlist[cur_atexitlist_entries++] = func;
70 return 0;
73 return -1;
76 void __cdecl _DoExit() {
77 if (cur_atexitlist_entries)
79 _initterm( pf_atexitlist,
80 // Use ptr math to find the end of the array
81 pf_atexitlist + cur_atexitlist_entries );
85 // -----------------------------------------------------
88 static HANDLE g_hProcessHeap = NULL;
90 extern "C" _PVFV* __onexitbegin = NULL;
91 extern "C" _PVFV* __onexitend = NULL;
93 extern "C" _PVFV __xi_a[], __xi_z[]; // C initializers
94 extern "C" _PVFV __xc_a[], __xc_z[]; // C++ initializers
95 extern "C" _PVFV __xp_a[], __xp_z[]; // C pre-terminators
96 extern "C" _PVFV __xt_a[], __xt_z[]; // C terminators
98 // Critical section to protect initialization/exit code
99 static CRITICAL_SECTION g_csInit;
101 extern "C" void DoInitialization() {
102 _PVFV* pf;
104 // memset(&osi, 0, sizeof(OSVERSIONINFO));
105 // osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
106 // GetVersionEx(&osi);
107 // _osplatform = osi.dwPlatformId;
109 InitializeCriticalSection( &g_csInit );
111 EnterCriticalSection( &g_csInit );
113 __try
115 g_hProcessHeap = GetProcessHeap();
117 // Call initialization routines (contructors for globals, etc.)
118 for (pf = __xi_a; pf < __xi_z; pf++)
120 if (*pf != NULL)
122 (**pf)();
126 for (pf = __xc_a; pf < __xc_z; pf++)
128 if (*pf != NULL)
130 (**pf)();
134 __finally
136 LeaveCriticalSection(&g_csInit);
140 extern "C" void DoCleanup() {
141 _PVFV* pf;
143 EnterCriticalSection(&g_csInit); // Protect access to the atexit table
145 __try
147 // Call routines registered with atexit() from most recently registered
148 // to least recently registered
149 if (__onexitbegin != NULL)
151 for (pf = __onexitend-1; pf >= __onexitbegin; pf--)
153 if (*pf != NULL)
154 (**pf)();
158 free(__onexitbegin);
159 __onexitbegin = NULL;
160 __onexitend = NULL;
162 for (pf = __xp_a; pf < __xp_z; pf++)
164 if (*pf != NULL)
166 (**pf)();
170 for (pf = __xt_a; pf < __xt_z; pf++)
172 if (*pf != NULL)
174 (**pf)();
178 __finally
180 LeaveCriticalSection(&g_csInit);
181 DeleteCriticalSection(&g_csInit);
185 int __cdecl atexit(_PVFV pf) {
186 size_t nCurrentSize;
187 int nRet = 0;
189 EnterCriticalSection(&g_csInit);
191 __try
193 if (__onexitbegin == NULL)
195 __onexitbegin = (_PVFV*)malloc(16*sizeof(_PVFV));
196 if (__onexitbegin == NULL)
198 LeaveCriticalSection(&g_csInit);
199 return(-1);
201 __onexitend = __onexitbegin;
204 nCurrentSize = _msize(__onexitbegin);
205 if ((nCurrentSize+sizeof(_PVFV)) < ULONG(((const byte*)__onexitend-
206 (const byte*)__onexitbegin)))
208 _PVFV* pNew;
210 pNew = (_PVFV*)realloc(__onexitbegin, 2*nCurrentSize);
211 if (pNew == NULL)
213 LeaveCriticalSection(&g_csInit);
214 return(-1);
218 *__onexitend = pf;
219 __onexitend++;
221 __except (1)
223 nRet = -1;
226 LeaveCriticalSection(&g_csInit);
228 return(nRet);