Mercurial > repo
comparison perl-5.22.2/os2/dl_os2.c @ 8045:a16537d2fe07
<xfix> tar xf perl-5.22.2.tar.gz # Ah, whatever, I\'m doing it anyway
author | HackBot |
---|---|
date | Sat, 14 May 2016 14:54:38 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
8044:711c038a7dce | 8045:a16537d2fe07 |
---|---|
1 #include "dlfcn.h" | |
2 #include "string.h" | |
3 #include "stdio.h" | |
4 | |
5 #define INCL_BASE | |
6 #include <os2.h> | |
7 #include <float.h> | |
8 #include <stdlib.h> | |
9 | |
10 static ULONG retcode; | |
11 static char fail[300]; | |
12 | |
13 static ULONG dllHandle; | |
14 static int handle_found; | |
15 static int handle_loaded; | |
16 #ifdef PERL_CORE | |
17 | |
18 #include "EXTERN.h" | |
19 #include "perl.h" | |
20 | |
21 #else | |
22 | |
23 char *os2error(int rc); | |
24 | |
25 #endif | |
26 | |
27 #ifdef DLOPEN_INITTERM | |
28 unsigned long _DLL_InitTerm(unsigned long modHandle, unsigned long flag) | |
29 { | |
30 switch (flag) { | |
31 case 0: /* INIT */ | |
32 /* Save handle */ | |
33 dllHandle = modHandle; | |
34 handle_found = 1; | |
35 return TRUE; | |
36 | |
37 case 1: /* TERM */ | |
38 handle_found = 0; | |
39 dllHandle = (unsigned long)NULLHANDLE; | |
40 return TRUE; | |
41 } | |
42 | |
43 return FALSE; | |
44 } | |
45 | |
46 #endif | |
47 | |
48 HMODULE | |
49 find_myself(void) | |
50 { | |
51 | |
52 static APIRET APIENTRY (*pDosQueryModFromEIP) (HMODULE * hmod, ULONG * obj, ULONG BufLen, PCHAR Buf, | |
53 ULONG * Offset, ULONG Address); | |
54 HMODULE doscalls_h, mod; | |
55 static int failed; | |
56 ULONG obj, offset, rc; | |
57 char buf[260]; | |
58 | |
59 if (failed) | |
60 return 0; | |
61 failed = 1; | |
62 doscalls_h = (HMODULE)dlopen("DOSCALLS",0); | |
63 if (!doscalls_h) | |
64 return 0; | |
65 /* {&doscalls_handle, NULL, 360}, */ /* DosQueryModFromEIP */ | |
66 rc = DosQueryProcAddr(doscalls_h, 360, 0, (PFN*)&pDosQueryModFromEIP); | |
67 if (rc) | |
68 return 0; | |
69 rc = pDosQueryModFromEIP(&mod, &obj, sizeof(buf), buf, &offset, (ULONG)dlopen); | |
70 if (rc) | |
71 return 0; | |
72 failed = 0; | |
73 handle_found = 1; | |
74 dllHandle = mod; | |
75 return mod; | |
76 } | |
77 | |
78 void * | |
79 dlopen(const char *path, int mode) | |
80 { | |
81 HMODULE handle; | |
82 char tmp[260]; | |
83 const char *beg, *dot; | |
84 ULONG rc; | |
85 unsigned fpflag = _control87(0,0); | |
86 | |
87 fail[0] = 0; | |
88 if (!path) { /* Our own handle. */ | |
89 if (handle_found || find_myself()) { | |
90 char dllname[260]; | |
91 | |
92 if (handle_loaded) | |
93 return (void*)dllHandle; | |
94 rc = DosQueryModuleName(dllHandle, sizeof(dllname), dllname); | |
95 if (rc) { | |
96 strcpy(fail, "can't find my DLL name by the handle"); | |
97 retcode = rc; | |
98 return 0; | |
99 } | |
100 rc = DosLoadModule(fail, sizeof fail, dllname, &handle); | |
101 if (rc) { | |
102 strcpy(fail, "can't load my own DLL"); | |
103 retcode = rc; | |
104 return 0; | |
105 } | |
106 handle_loaded = 1; | |
107 goto ret; | |
108 } | |
109 retcode = ERROR_MOD_NOT_FOUND; | |
110 strcpy(fail, "can't load from myself: compiled without -DDLOPEN_INITTERM"); | |
111 return 0; | |
112 } | |
113 if ((rc = DosLoadModule(fail, sizeof fail, (char*)path, &handle)) == 0) | |
114 goto ret; | |
115 | |
116 retcode = rc; | |
117 | |
118 if (strlen(path) >= sizeof(tmp)) | |
119 return NULL; | |
120 | |
121 /* Not found. Check for non-FAT name and try truncated name. */ | |
122 /* Don't know if this helps though... */ | |
123 for (beg = dot = path + strlen(path); | |
124 beg > path && !strchr(":/\\", *(beg-1)); | |
125 beg--) | |
126 if (*beg == '.') | |
127 dot = beg; | |
128 if (dot - beg > 8) { | |
129 int n = beg+8-path; | |
130 | |
131 memmove(tmp, path, n); | |
132 memmove(tmp+n, dot, strlen(dot)+1); | |
133 if (DosLoadModule(fail, sizeof fail, tmp, &handle) == 0) | |
134 goto ret; | |
135 } | |
136 handle = 0; | |
137 | |
138 ret: | |
139 _control87(fpflag, MCW_EM); /* Some modules reset FP flags on load */ | |
140 return (void *)handle; | |
141 } | |
142 | |
143 #define ERROR_WRONG_PROCTYPE 0xffffffff | |
144 | |
145 void * | |
146 dlsym(void *handle, const char *symbol) | |
147 { | |
148 ULONG rc, type; | |
149 PFN addr; | |
150 | |
151 fail[0] = 0; | |
152 rc = DosQueryProcAddr((HMODULE)handle, 0, symbol, &addr); | |
153 if (rc == 0) { | |
154 rc = DosQueryProcType((HMODULE)handle, 0, symbol, &type); | |
155 if (rc == 0 && type == PT_32BIT) | |
156 return (void *)addr; | |
157 rc = ERROR_WRONG_PROCTYPE; | |
158 } | |
159 retcode = rc; | |
160 return NULL; | |
161 } | |
162 | |
163 char * | |
164 dlerror(void) | |
165 { | |
166 static char buf[700]; | |
167 ULONG len; | |
168 char *err; | |
169 | |
170 if (retcode == 0) | |
171 return NULL; | |
172 if (retcode == ERROR_WRONG_PROCTYPE) | |
173 err = "Wrong procedure type"; | |
174 else | |
175 err = os2error(retcode); | |
176 len = strlen(err); | |
177 if (len > sizeof(buf) - 1) | |
178 len = sizeof(buf) - 1; | |
179 strncpy(buf, err, len+1); | |
180 if (fail[0] && len + strlen(fail) < sizeof(buf) - 100) | |
181 sprintf(buf + len, ", possible problematic module: '%s'", fail); | |
182 retcode = 0; | |
183 return buf; | |
184 } | |
185 | |
186 int | |
187 dlclose(void *handle) | |
188 { | |
189 ULONG rc; | |
190 | |
191 if ((rc = DosFreeModule((HMODULE)handle)) == 0) return 0; | |
192 | |
193 retcode = rc; | |
194 return 2; | |
195 } |