sdk;ecere: Tweaks for Debian Multi-Arch support
[sdk] / ecere / src / com / instance.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <ctype.h>
5 #include <string.h>
6
7 #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__)
8 #include <time.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #endif
13
14 #if defined(__unix__) || defined(__APPLE__)
15 #define bool _bool
16 #include <utime.h>
17 #include <dlfcn.h>
18 #undef bool
19 #endif
20
21 #if defined(__WIN32__)
22 #define WIN32_LEAN_AND_MEAN
23 #define UNICODE
24 #include <windows.h>
25 #include <io.h>
26
27 #else
28 #include <unistd.h>
29 #endif
30
31 typedef int bool;
32 typedef unsigned char byte;
33 typedef unsigned short uint16;
34 typedef unsigned int uint;
35 typedef unsigned int FileSize;
36 typedef unsigned long long uint64;
37
38 #define false 0
39 #define true 1
40
41 #define null ((void *)0)
42
43 #define MAX_LOCATION 797
44 #define MAX_FILENAME 274
45 #define MAX_EXTENSION 17
46
47 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
48 void * __ecereNameSpace__ecere__com__eSystem_New0(unsigned int size);
49 void * __ecereNameSpace__ecere__com__eSystem_Renew(void * memory, unsigned int size);
50 void * __ecereNameSpace__ecere__com__eSystem_Renew0(void * memory, unsigned int size);
51 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(char * source, int * wordCount);
52 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(char * source, uint16 * dest, int max);
53 char * __ecereNameSpace__ecere__sys__UTF16toUTF8(uint16 * source);
54 char * __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer(uint16 * source, byte * dest, int max);
55
56 #define eSystem_Delete     __ecereNameSpace__ecere__com__eSystem_Delete
57 #define eSystem_New0       __ecereNameSpace__ecere__com__eSystem_New0
58 #define eSystem_Renew      __ecereNameSpace__ecere__com__eSystem_Renew
59 #define eSystem_Renew0     __ecereNameSpace__ecere__com__eSystem_Renew0
60 #define UTF8toUTF16        __ecereNameSpace__ecere__sys__UTF8toUTF16
61 #define UTF8toUTF16Buffer  __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer
62 #define UTF16toUTF8        __ecereNameSpace__ecere__sys__UTF16toUTF8
63 #define UTF16toUTF8Buffer  __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer
64
65 #if defined(__unix__)
66 static char exeLocation[MAX_LOCATION];
67 #endif
68
69 int __ecereNameSpace__ecere__sys__Tokenize(char * string, int maxTokens, char* tokens[], bool escapeBackSlashes);
70 char * __ecereNameSpace__ecere__sys__RSearchString(char * buffer, char * subStr, int maxLen, bool matchCase, bool matchWord);
71 char * __ecereNameSpace__ecere__sys__GetLastDirectory(char * string, char * output);
72 char * __ecereNameSpace__ecere__sys__PathCat(char * string, char * addedPath);
73 char * __ecereNameSpace__ecere__sys__GetExtension(char * string, char * output);
74
75 #define Tokenize           __ecereNameSpace__ecere__sys__Tokenize
76 #define RSearchString      __ecereNameSpace__ecere__sys__RSearchString
77 #define GetLastDirectory   __ecereNameSpace__ecere__sys__GetLastDirectory
78 #define PathCat            __ecereNameSpace__ecere__sys__PathCat
79 #define GetExtension       __ecereNameSpace__ecere__sys__GetExtension
80
81 extern struct __ecereNameSpace__ecere__com__Instance * __thisModule;
82
83 typedef enum { unknown, win32, tux, apple } Platform;
84
85 #if defined(__WIN32__)
86 Platform runtimePlatform = win32;
87 #elif defined(__APPLE__)
88 Platform runtimePlatform = apple;
89 #elif defined(__linux__)
90 Platform runtimePlatform = tux;
91 #else
92 Platform runtimePlatform = unknown;
93 #endif
94
95 bool Instance_LocateModule(char * name, char * fileName)
96 {
97 #if defined(__WIN32__)
98    HMODULE hModule = null;
99    if(name && name[0])
100    {
101       uint16 _wmoduleName[MAX_LOCATION];
102       UTF8toUTF16Buffer(name, _wmoduleName, MAX_LOCATION);
103       hModule = GetModuleHandle(_wmoduleName);
104       if(!hModule)
105       {
106          wcscat(_wmoduleName, L".exe");
107          hModule = GetModuleHandle(_wmoduleName);
108       }
109       if(hModule)
110       {
111          uint16 _wfileName[MAX_LOCATION];
112          GetModuleFileNameW(hModule, _wfileName, MAX_LOCATION);
113          UTF16toUTF8Buffer(_wfileName, (byte *)fileName, MAX_LOCATION);
114          return true;
115       }
116    }
117    else
118    {
119       uint16 _wfileName[MAX_LOCATION];
120       GetModuleFileNameW(null, _wfileName, MAX_LOCATION);
121       UTF16toUTF8Buffer(_wfileName, (byte *)fileName, MAX_LOCATION);
122       return true;
123    }
124 #elif defined(__APPLE__)
125    if(name && name[0])
126    {
127       int imageCount = _dyld_image_count();
128       int c;
129       int nameLen = strlen(name);
130       for(c = 0; c<imageCount; c++)
131       {
132          struct mach_header * header = _dyld_get_image_header(c);
133          char * path = _dyld_get_image_name(c);
134          int pathLen = strlen(path);
135          char * subStr = RSearchString(path, name, pathLen, false, false);
136          if(subStr)
137          {
138             if(( *(subStr-1) == '/' || !strncmp(subStr - 4, "/lib", 4)) &&
139                (!subStr[nameLen] || !strncmp(subStr + nameLen, ".dylib", 6)))
140             {
141                strcpy(fileName, path);
142                return true;
143             }
144          }
145       }
146    }
147    else
148    {
149       int size = MAX_LOCATION;
150       _NSGetExecutablePath(fileName, &size);
151       return true;
152    }
153 #elif defined(__unix__)
154    //File f = FileOpen("/proc/self/maps", read);
155    FILE * f;
156    char exeName[MAX_FILENAME];
157    exeName[0] = 0;
158 #if defined(__linux__)
159    f = fopen("/proc/self/status", "r");
160 #else
161    f = fopen("/proc/curproc/status", "r");
162 #endif
163    if(f)
164    {
165       char line[1025];
166       while(fgets(line, sizeof(line), f))
167       {
168          char * name = strstr(line, "Name:\t");
169          if(name)
170          {
171             int nameLen;
172             name += 6;
173             nameLen = strlen(name);
174             name[--nameLen] = 0;
175             strcpy(exeName, name);
176             break;
177          }
178       }
179       fclose(f);
180   }
181 #if defined(__linux__)
182    f = fopen("/proc/self/maps", "r");
183 #else
184    f = fopen("/proc/curproc/map", "r");
185 #endif
186    if(f)
187    {
188       char line[1025];
189       //while(f.GetLine(line, sizeof(line)))
190       while(fgets(line, sizeof(line), f))
191       {
192          char * path = strstr(line, "/");
193          if(path)
194          {
195             int pathLen = strlen(path);
196             path[--pathLen] = 0;
197             if(name && name[0])
198             {
199                int nameLen = strlen(name);
200                char * subStr;
201                subStr = RSearchString(path, name, pathLen, false, false);
202                if(subStr)
203                {
204                   if(( *(subStr-1) == '/' || !strncmp(subStr - 4, "/lib", 4)) &&
205                      (!subStr[nameLen] || !strncmp(subStr + nameLen, ".so", 3)))
206                   {
207                      char * space = strchr(path, ' ');
208                      if(space) *space = 0;
209                      strcpy(fileName, path);
210                      fclose(f);
211                      return true;
212                   }
213                }
214             }
215             else
216             {
217                char name[MAX_FILENAME];
218                GetLastDirectory(path, name);
219                if(!exeName[0] || !strcmp(name, exeName))
220                {
221                   char * space = strchr(path, ' ');
222                   if(space) *space = 0;
223                   strcpy(fileName, path);
224                   fclose(f);
225                   return true;
226                }
227             }
228          }
229       }
230       fclose(f);
231    }
232    if(!name || !name[0])
233    {
234       strcpy(fileName, exeLocation);
235       return true;
236    }
237 #endif
238    return false;
239 }
240
241 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, char *** argvPtr)
242 {
243 #if !defined(__WIN32__)
244    // Disable stdout buffering on Unix
245    setvbuf(stdout, null, _IONBF, 0);
246 #endif
247 #if defined(__WIN32__)
248    *parsedCommand = UTF16toUTF8(GetCommandLineW());
249    *argvPtr = eSystem_New0(sizeof(char *) * 512);
250    *argcPtr = Tokenize(*parsedCommand, 512,(void*)(char **)(*argvPtr), false);
251 #else
252    *argcPtr = argc;
253    *argvPtr = argv;
254 #endif
255 #if defined(__unix__)
256    if(!__thisModule && argv)
257    {
258       getcwd(exeLocation, MAX_LOCATION);
259       PathCat(exeLocation, argv[0]);
260    }
261 #endif
262 }
263
264 void * Instance_Module_Load(char * name, void ** Load, void ** Unload)
265 {
266    char fileName[MAX_LOCATION];
267    char extension[MAX_EXTENSION];
268    void * library = null;
269
270    *Load = null;
271    *Unload = null;
272
273 #if defined(__WIN32__)
274    strcpy(fileName, name);
275    GetExtension(fileName, extension);
276    if(!extension[0])
277       strcat(fileName, ".dll");
278
279    {
280       uint16 _wfileName[MAX_LOCATION];
281       UTF8toUTF16Buffer(fileName, _wfileName, MAX_LOCATION);
282       library = LoadLibraryW(_wfileName);
283    }
284    if(library)
285    {
286       *Load = (void *)GetProcAddress(library, "__ecereDll_Load@4");
287       *Unload = (void *)GetProcAddress(library, "__ecereDll_Unload@4");
288       if(!*Load)
289          FreeLibrary(library);
290    }
291 #elif defined(__unix__) || defined(__APPLE__)
292 #if defined(__ANDROID__)
293    sprintf(fileName, "/data/data/com.ecere.%s/lib/lib", name);
294 #else
295    strcpy(fileName, "lib");
296 #endif
297    strcat(fileName, name);
298    GetExtension(fileName, extension);
299    if(!extension[0])
300 #if defined(__APPLE__)
301       strcat(fileName, ".dylib");
302 #else
303       strcat(fileName, ".so");
304 #endif
305
306    library = dlopen(fileName, RTLD_LAZY);
307    if(!library)
308    {
309 #ifdef DEB_HOST_MULTIARCH
310       strcpy(fileName, DEB_HOST_MULTIARCH);
311       strcat(fileName, "/ec/lib");
312 #else
313       strcpy(fileName, "/usr/lib/ec/lib");
314 #endif
315       strcat(fileName, name);
316       GetExtension(fileName, extension);
317       if(!extension[0])
318 #if defined(__APPLE__)
319          strcat(fileName, ".dylib");
320 #else
321          strcat(fileName, ".so");
322 #endif
323       library = dlopen(fileName, RTLD_LAZY);
324    }
325
326    if(library)
327    {
328       *Load = dlsym(library, "__ecereDll_Load");
329       *Unload = dlsym(library, "__ecereDll_Unload");
330       if(!*Load)
331          dlclose(library);
332    }
333 #elif defined(__APPLE__)
334    strcpy(fileName, "lib");
335    strcat(fileName, name);
336    GetExtension(fileName, extension);
337    if(!extension[0])
338       strcat(fileName, ".dylib");
339    {
340       NSObjectFileImage *fileImage;
341       NSObjectFileImageReturnCode returnCode = NSCreateObjectFileImageFromFile(fileName, &fileImage);
342
343       if(returnCode == NSObjectFileImageSuccess)
344       {
345          printf("NSObjectFileImageSuccess!\n");
346          library = NSLinkModule(fileImage,fileName, 
347               NSLINKMODULE_OPTION_RETURN_ON_ERROR
348             | NSLINKMODULE_OPTION_PRIVATE);
349          // NSDestroyObjectFileImage(fileImage);
350          if(library)
351          {
352             *Load = NSAddressOfSymbol(NSLookupSymbolInModule(library, "__ecereDll_Load")); 
353             *Unload = NSAddressOfSymbol(NSLookupSymbolInModule(library, "__ecereDll_Unload"));
354             if(!*Load)
355             {
356                NSUnLinkModule(library, 0);
357             }
358             else
359                printf("Found Load!\n");
360          }
361       }
362       else
363          printf("No Success :(\n");
364    }
365 #endif
366    return library;
367 }
368
369 void Instance_Module_Free(void * library)
370 {
371 #if defined(__WIN32__)
372    if(library)
373       FreeLibrary(library);
374 #elif defined(__unix__) || defined(__APPLE__)
375    if(library)
376       dlclose(library);
377 #endif
378 }