more complete pseudo-fork() support for Windows
[p5sagit/p5-mst-13.2.git] / win32 / perllib.c
1 /*
2  * "The Road goes ever on and on, down from the door where it began."
3  */
4
5
6 #include "EXTERN.h"
7 #include "perl.h"
8
9 #ifdef PERL_OBJECT
10 #define NO_XSLOCKS
11 #endif
12
13 #include "XSUB.h"
14
15 #ifdef PERL_IMPLICIT_SYS
16 #include "win32iop.h"
17 #include <fcntl.h>
18 #endif /* PERL_IMPLICIT_SYS */
19
20
21 /* Register any extra external extensions */
22 char *staticlinkmodules[] = {
23     "DynaLoader",
24     NULL,
25 };
26
27 EXTERN_C void boot_DynaLoader (pTHXo_ CV* cv);
28
29 static void
30 xs_init(pTHXo)
31 {
32     char *file = __FILE__;
33     dXSUB_SYS;
34     newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
35 }
36
37 #ifdef PERL_IMPLICIT_SYS
38
39 #include "perlhost.h"
40
41 EXTERN_C void
42 perl_get_host_info(struct IPerlMemInfo* perlMemInfo,
43                    struct IPerlMemInfo* perlMemSharedInfo,
44                    struct IPerlMemInfo* perlMemParseInfo,
45                    struct IPerlEnvInfo* perlEnvInfo,
46                    struct IPerlStdIOInfo* perlStdIOInfo,
47                    struct IPerlLIOInfo* perlLIOInfo,
48                    struct IPerlDirInfo* perlDirInfo,
49                    struct IPerlSockInfo* perlSockInfo,
50                    struct IPerlProcInfo* perlProcInfo)
51 {
52     if (perlMemInfo) {
53         Copy(&perlMem, &perlMemInfo->perlMemList, perlMemInfo->nCount, void*);
54         perlMemInfo->nCount = (sizeof(struct IPerlMem)/sizeof(void*));
55     }
56     if (perlMemSharedInfo) {
57         Copy(&perlMem, &perlMemSharedInfo->perlMemList, perlMemSharedInfo->nCount, void*);
58         perlMemSharedInfo->nCount = (sizeof(struct IPerlMem)/sizeof(void*));
59     }
60     if (perlMemParseInfo) {
61         Copy(&perlMem, &perlMemParseInfo->perlMemList, perlMemParseInfo->nCount, void*);
62         perlMemParseInfo->nCount = (sizeof(struct IPerlMem)/sizeof(void*));
63     }
64     if (perlEnvInfo) {
65         Copy(&perlEnv, &perlEnvInfo->perlEnvList, perlEnvInfo->nCount, void*);
66         perlEnvInfo->nCount = (sizeof(struct IPerlEnv)/sizeof(void*));
67     }
68     if (perlStdIOInfo) {
69         Copy(&perlStdIO, &perlStdIOInfo->perlStdIOList, perlStdIOInfo->nCount, void*);
70         perlStdIOInfo->nCount = (sizeof(struct IPerlStdIO)/sizeof(void*));
71     }
72     if (perlLIOInfo) {
73         Copy(&perlLIO, &perlLIOInfo->perlLIOList, perlLIOInfo->nCount, void*);
74         perlLIOInfo->nCount = (sizeof(struct IPerlLIO)/sizeof(void*));
75     }
76     if (perlDirInfo) {
77         Copy(&perlDir, &perlDirInfo->perlDirList, perlDirInfo->nCount, void*);
78         perlDirInfo->nCount = (sizeof(struct IPerlDir)/sizeof(void*));
79     }
80     if (perlSockInfo) {
81         Copy(&perlSock, &perlSockInfo->perlSockList, perlSockInfo->nCount, void*);
82         perlSockInfo->nCount = (sizeof(struct IPerlSock)/sizeof(void*));
83     }
84     if (perlProcInfo) {
85         Copy(&perlProc, &perlProcInfo->perlProcList, perlProcInfo->nCount, void*);
86         perlProcInfo->nCount = (sizeof(struct IPerlProc)/sizeof(void*));
87     }
88 }
89
90 #ifdef PERL_OBJECT
91
92 EXTERN_C PerlInterpreter*
93 perl_alloc_override(struct IPerlMem** ppMem, struct IPerlMem** ppMemShared,
94                  struct IPerlMem** ppMemParse, struct IPerlEnv** ppEnv,
95                  struct IPerlStdIO** ppStdIO, struct IPerlLIO** ppLIO,
96                  struct IPerlDir** ppDir, struct IPerlSock** ppSock,
97                  struct IPerlProc** ppProc)
98 {
99     PerlInterpreter *my_perl = NULL;
100     try
101     {
102         CPerlHost* pHost = new CPerlHost(ppMem, ppMemShared, ppMemParse, ppEnv,
103                                          ppStdIO, ppLIO, ppDir, ppSock, ppProc);
104
105         if (pHost) {
106             my_perl = perl_alloc_using(pHost->m_pHostperlMem,
107                                        pHost->m_pHostperlMemShared,
108                                        pHost->m_pHostperlMemParse,
109                                        pHost->m_pHostperlEnv,
110                                        pHost->m_pHostperlStdIO,
111                                        pHost->m_pHostperlLIO,
112                                        pHost->m_pHostperlDir,
113                                        pHost->m_pHostperlSock,
114                                        pHost->m_pHostperlProc);
115             if (my_perl) {
116                 CPerlObj* pPerl = (CPerlObj*)my_perl;
117                 w32_internal_host = pHost;
118             }
119         }
120     }
121     catch(...)
122     {
123         win32_fprintf(stderr, "%s\n", "Error: Unable to allocate memory");
124         my_perl = NULL;
125     }
126
127     return my_perl;
128 }
129
130 EXTERN_C PerlInterpreter*
131 perl_alloc(void)
132 {
133     PerlInterpreter* my_perl = NULL;
134     try
135     {
136         CPerlHost* pHost = new CPerlHost();
137         if (pHost) {
138             my_perl = perl_alloc_using(pHost->m_pHostperlMem,
139                                        pHost->m_pHostperlMemShared,
140                                        pHost->m_pHostperlMemParse,
141                                        pHost->m_pHostperlEnv,
142                                        pHost->m_pHostperlStdIO,
143                                        pHost->m_pHostperlLIO,
144                                        pHost->m_pHostperlDir,
145                                        pHost->m_pHostperlSock,
146                                        pHost->m_pHostperlProc);
147             if (my_perl) {
148                 CPerlObj* pPerl = (CPerlObj*)my_perl;
149                 w32_internal_host = pHost;
150             }
151         }
152     }
153     catch(...)
154     {
155         win32_fprintf(stderr, "%s\n", "Error: Unable to allocate memory");
156         my_perl = NULL;
157     }
158
159     return my_perl;
160 }
161
162 EXTERN_C void
163 perl_construct(PerlInterpreter* my_perl)
164 {
165     CPerlObj* pPerl = (CPerlObj*)my_perl;
166     try
167     {
168         Perl_construct();
169     }
170     catch(...)
171     {
172         win32_fprintf(stderr, "%s\n",
173                       "Error: Unable to construct data structures");
174         CPerlHost* pHost = (CPerlHost*)w32_internal_host;
175         Perl_free();
176         delete pHost;
177         SetPerlInterpreter(NULL);
178     }
179 }
180
181 EXTERN_C void
182 perl_destruct(PerlInterpreter* my_perl)
183 {
184     CPerlObj* pPerl = (CPerlObj*)my_perl;
185 #ifdef DEBUGGING
186     Perl_destruct();
187 #else
188     try
189     {
190         Perl_destruct();
191     }
192     catch(...)
193     {
194     }
195 #endif
196 }
197
198 EXTERN_C void
199 perl_free(PerlInterpreter* my_perl)
200 {
201     CPerlObj* pPerl = (CPerlObj*)my_perl;
202 #ifdef DEBUGGING
203     CPerlHost* pHost = (CPerlHost*)w32_internal_host;
204     Perl_free();
205     delete pHost;
206 #else
207     try
208     {
209         CPerlHost* pHost = (CPerlHost*)w32_internal_host;
210         Perl_free();
211         delete pHost;
212     }
213     catch(...)
214     {
215     }
216 #endif
217     SetPerlInterpreter(NULL);
218 }
219
220 EXTERN_C int
221 perl_run(PerlInterpreter* my_perl)
222 {
223     CPerlObj* pPerl = (CPerlObj*)my_perl;
224 #ifdef DEBUGGING
225     return Perl_run();
226 #else
227     int retVal;
228     try
229     {
230         retVal = Perl_run();
231     }
232     catch(...)
233     {
234         win32_fprintf(stderr, "Error: Runtime exception\n");
235         retVal = -1;
236     }
237     return retVal;
238 #endif
239 }
240
241 EXTERN_C int
242 perl_parse(PerlInterpreter* my_perl, void (*xsinit)(CPerlObj*), int argc, char** argv, char** env)
243 {
244     int retVal;
245     CPerlObj* pPerl = (CPerlObj*)my_perl;
246 #ifdef DEBUGGING
247     retVal = Perl_parse(xsinit, argc, argv, env);
248 #else
249     try
250     {
251         retVal = Perl_parse(xsinit, argc, argv, env);
252     }
253     catch(...)
254     {
255         win32_fprintf(stderr, "Error: Parse exception\n");
256         retVal = -1;
257     }
258 #endif
259     *win32_errno() = 0;
260     return retVal;
261 }
262
263 #undef PL_perl_destruct_level
264 #define PL_perl_destruct_level int dummy
265
266 #else /* !PERL_OBJECT */
267
268 EXTERN_C PerlInterpreter*
269 perl_alloc(void)
270 {
271     PerlInterpreter *my_perl = NULL;
272     CPerlHost* pHost = new CPerlHost();
273     if (pHost) {
274         my_perl = perl_alloc_using(pHost->m_pHostperlMem,
275                                    pHost->m_pHostperlMemShared,
276                                    pHost->m_pHostperlMemParse,
277                                    pHost->m_pHostperlEnv,
278                                    pHost->m_pHostperlStdIO,
279                                    pHost->m_pHostperlLIO,
280                                    pHost->m_pHostperlDir,
281                                    pHost->m_pHostperlSock,
282                                    pHost->m_pHostperlProc);
283         if (my_perl) {
284             CPerlObj* pPerl = (CPerlObj*)my_perl;
285             w32_internal_host = pHost;
286         }
287     }
288     return my_perl;
289 }
290
291 #endif /* PERL_OBJECT */
292 #endif /* PERL_IMPLICIT_SYS */
293
294 EXTERN_C HANDLE w32_perldll_handle;
295
296 static DWORD g_TlsAllocIndex;
297
298 EXTERN_C DllExport bool
299 SetPerlInterpreter(void *interp)
300 {
301     return TlsSetValue(g_TlsAllocIndex, interp);
302 }
303
304 EXTERN_C DllExport void*
305 GetPerlInterpreter(void)
306 {
307     return TlsGetValue(g_TlsAllocIndex);
308 }
309
310 EXTERN_C DllExport int
311 RunPerl(int argc, char **argv, char **env)
312 {
313     int exitstatus;
314     PerlInterpreter *my_perl, *new_perl = NULL;
315     struct perl_thread *thr;
316
317 #ifndef __BORLANDC__
318     /* XXX this _may_ be a problem on some compilers (e.g. Borland) that
319      * want to free() argv after main() returns.  As luck would have it,
320      * Borland's CRT does the right thing to argv[0] already. */
321     char szModuleName[MAX_PATH];
322     char *ptr;
323
324     GetModuleFileName(NULL, szModuleName, sizeof(szModuleName));
325     (void)win32_longpath(szModuleName);
326     argv[0] = szModuleName;
327 #endif
328
329 #ifdef PERL_GLOBAL_STRUCT
330 #define PERLVAR(var,type) /**/
331 #define PERLVARA(var,type) /**/
332 #define PERLVARI(var,type,init) PL_Vars.var = init;
333 #define PERLVARIC(var,type,init) PL_Vars.var = init;
334 #include "perlvars.h"
335 #undef PERLVAR
336 #undef PERLVARA
337 #undef PERLVARI
338 #undef PERLVARIC
339 #endif
340
341     PERL_SYS_INIT(&argc,&argv);
342
343     if (!(my_perl = perl_alloc()))
344         return (1);
345     perl_construct( my_perl );
346     PL_perl_destruct_level = 0;
347
348     exitstatus = perl_parse(my_perl, xs_init, argc, argv, env);
349     if (!exitstatus) {
350 #if defined(TOP_CLONE) && defined(USE_ITHREADS)         /* XXXXXX testing */
351 #  ifdef PERL_OBJECT
352         CPerlHost *h = new CPerlHost();
353         new_perl = perl_clone_using(my_perl, 1,
354                                     h->m_pHostperlMem,
355                                     h->m_pHostperlMemShared,
356                                     h->m_pHostperlMemParse,
357                                     h->m_pHostperlEnv,
358                                     h->m_pHostperlStdIO,
359                                     h->m_pHostperlLIO,
360                                     h->m_pHostperlDir,
361                                     h->m_pHostperlSock,
362                                     h->m_pHostperlProc
363                                     );
364         CPerlObj *pPerl = (CPerlObj*)new_perl;
365 #  else
366         new_perl = perl_clone(my_perl, 1);
367 #  endif
368         exitstatus = perl_run( new_perl );
369         SetPerlInterpreter(my_perl);
370 #else
371         exitstatus = perl_run( my_perl );
372 #endif
373     }
374
375     perl_destruct( my_perl );
376     perl_free( my_perl );
377 #ifdef USE_ITHREADS
378     if (new_perl) {
379         SetPerlInterpreter(new_perl);
380         perl_destruct(new_perl);
381         perl_free(new_perl);
382     }
383 #endif
384
385     PERL_SYS_TERM();
386
387     return (exitstatus);
388 }
389
390 BOOL APIENTRY
391 DllMain(HANDLE hModule,         /* DLL module handle */
392         DWORD fdwReason,        /* reason called */
393         LPVOID lpvReserved)     /* reserved */
394
395     switch (fdwReason) {
396         /* The DLL is attaching to a process due to process
397          * initialization or a call to LoadLibrary.
398          */
399     case DLL_PROCESS_ATTACH:
400 /* #define DEFAULT_BINMODE */
401 #ifdef DEFAULT_BINMODE
402         setmode( fileno( stdin  ), O_BINARY );
403         setmode( fileno( stdout ), O_BINARY );
404         setmode( fileno( stderr ), O_BINARY );
405         _fmode = O_BINARY;
406 #endif
407         g_TlsAllocIndex = TlsAlloc();
408         DisableThreadLibraryCalls(hModule);
409         w32_perldll_handle = hModule;
410         break;
411
412         /* The DLL is detaching from a process due to
413          * process termination or call to FreeLibrary.
414          */
415     case DLL_PROCESS_DETACH:
416         TlsFree(g_TlsAllocIndex);
417         break;
418
419         /* The attached process creates a new thread. */
420     case DLL_THREAD_ATTACH:
421         break;
422
423         /* The thread of the attached process terminates. */
424     case DLL_THREAD_DETACH:
425         break;
426
427     default:
428         break;
429     }
430     return TRUE;
431 }