documentor; compiler/libec; ecere/com/instance: Fixes for consistent module names...
[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 #if defined(__APPLE__)
19 #include <mach-o/dyld.h>
20 #endif
21 #if defined(__FreeBSD__)
22 #include <sys/sysctl.h>
23 #endif
24 #undef bool
25 #endif
26
27 #if defined(__WIN32__)
28 #define WIN32_LEAN_AND_MEAN
29 #define UNICODE
30 #include <windows.h>
31 #include <io.h>
32
33 #else
34 #include <unistd.h>
35 #endif
36
37 typedef int bool;
38 typedef unsigned char byte;
39 typedef unsigned short uint16;
40 typedef unsigned int uint;
41 typedef unsigned int FileSize;
42 typedef unsigned long long uint64;
43
44 #define false 0
45 #define true 1
46
47 #define null ((void *)0)
48
49 #define MAX_LOCATION 797
50 #define MAX_FILENAME 274
51 #define MAX_EXTENSION 17
52
53 #if defined(__WIN32__)
54 intptr_t stdinHandle, stdoutHandle;
55 int osfStdin, osfStdout;
56 FILE * fStdIn, * fStdOut;
57 #endif
58
59 FILE *eC_stdin(void)  {
60 #if defined(__WIN32__)
61    if(!fStdIn)
62    {
63       stdinHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
64       osfStdin = _open_osfhandle(stdinHandle, _O_TEXT);
65       if(osfStdin != -1)
66          fStdIn = _fdopen( osfStdin, "rb");
67       else
68          fStdIn = stdin;
69       setvbuf( fStdIn, NULL, _IONBF, 0 );
70    }
71    return fStdIn;
72 #else
73 return stdin;
74 #endif
75 }
76
77 FILE *eC_stdout(void)
78 {
79 #if 0 //defined(__WIN32__)
80    if(!fStdOut)
81    {
82       stdoutHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
83       osfStdout = _open_osfhandle(stdoutHandle, _O_TEXT);
84       if(osfStdout != -1)
85          fStdOut = _fdopen( osfStdout, "wb");
86       else
87          fStdOut = stdout;
88       setvbuf( fStdOut, NULL, _IONBF, 0 );
89    }
90    return fStdOut;
91 #else
92    return stdout;
93 #endif
94 }
95 FILE *eC_stderr(void) { return stderr; }
96
97 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
98 void * __ecereNameSpace__ecere__com__eSystem_New0(unsigned int size);
99 void * __ecereNameSpace__ecere__com__eSystem_Renew(void * memory, unsigned int size);
100 void * __ecereNameSpace__ecere__com__eSystem_Renew0(void * memory, unsigned int size);
101 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(char * source, int * wordCount);
102 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(char * source, uint16 * dest, int max);
103 char * __ecereNameSpace__ecere__sys__UTF16toUTF8(uint16 * source);
104 char * __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer(uint16 * source, byte * dest, int max);
105
106 #define eSystem_Delete     __ecereNameSpace__ecere__com__eSystem_Delete
107 #define eSystem_New0       __ecereNameSpace__ecere__com__eSystem_New0
108 #define eSystem_Renew      __ecereNameSpace__ecere__com__eSystem_Renew
109 #define eSystem_Renew0     __ecereNameSpace__ecere__com__eSystem_Renew0
110 #define UTF8toUTF16        __ecereNameSpace__ecere__sys__UTF8toUTF16
111 #define UTF8toUTF16Buffer  __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer
112 #define UTF16toUTF8        __ecereNameSpace__ecere__sys__UTF16toUTF8
113 #define UTF16toUTF8Buffer  __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer
114
115 #if defined(__unix__)
116 static char exeLocation[MAX_LOCATION];
117 #endif
118
119 #define forArgsPassing 2
120 int __ecereNameSpace__ecere__sys__Tokenize(char * string, int maxTokens, char* tokens[], int esc);
121 char * __ecereNameSpace__ecere__sys__RSearchString(char * buffer, char * subStr, int maxLen, bool matchCase, bool matchWord);
122 char * __ecereNameSpace__ecere__sys__GetLastDirectory(char * string, char * output);
123 char * __ecereNameSpace__ecere__sys__PathCat(char * string, char * addedPath);
124 char * __ecereNameSpace__ecere__sys__GetExtension(char * string, char * output);
125
126 #define Tokenize           __ecereNameSpace__ecere__sys__Tokenize
127 #define RSearchString      __ecereNameSpace__ecere__sys__RSearchString
128 #define GetLastDirectory   __ecereNameSpace__ecere__sys__GetLastDirectory
129 #define PathCat            __ecereNameSpace__ecere__sys__PathCat
130 #define GetExtension       __ecereNameSpace__ecere__sys__GetExtension
131
132 extern struct __ecereNameSpace__ecere__com__Instance * __thisModule;
133
134 typedef enum { unknown, win32, tux, apple } Platform;
135
136 #if defined(__WIN32__)
137 Platform runtimePlatform = win32;
138 #elif defined(__APPLE__)
139 Platform runtimePlatform = apple;
140 #else //if defined(__linux__)
141 Platform runtimePlatform = tux;
142 /*#else
143 Platform runtimePlatform = unknown;    // 'linux' is used as a catch all UNIX platform for now
144 */
145 #endif
146
147 #if !defined(ECERE_NOFILE) && defined(__unix__) && !defined(__linux__)
148
149 typedef struct _DualPipe _DualPipe;
150
151 void DualPipe_Destructor(_DualPipe * dp);
152 bool DualPipe_Getc(_DualPipe * dp, char * ch);
153 bool DualPipe_Eof(_DualPipe * dp);
154 void DualPipe_Wait(_DualPipe * dp);
155
156 _DualPipe * _DualPipeOpen(int mode, char * commandLine, char * env, void ** inputPtr, void ** outputPtr);
157
158 static bool DualPipe_GetLine(FILE * p, char *s, int max)
159 {
160    int c = 0;
161    bool result = true;
162    s[c]=0;
163    if(feof(p))
164       result = false;
165    else
166    {
167       while(c<max-1)
168       {
169          int ch = 0;
170          if((ch = fgetc(p)) == EOF)
171          {
172             result = false;
173             break;
174          }
175          if(ch =='\n')
176             break;
177          if(ch !='\r')
178             s[c++]=(char)ch;
179       }
180    }
181    s[c]=0;
182    return result || c > 1;
183 }
184
185 #endif
186
187 bool Instance_LocateModule(char * name, char * fileName)
188 {
189 #if defined(__WIN32__)
190    HMODULE hModule = null;
191    if(name && name[0])
192    {
193       uint16 _wmoduleName[MAX_LOCATION];
194       UTF8toUTF16Buffer(name, _wmoduleName, MAX_LOCATION);
195       hModule = GetModuleHandle(_wmoduleName);
196       if(!hModule)
197       {
198          wcscat(_wmoduleName, L".exe");
199          hModule = GetModuleHandle(_wmoduleName);
200       }
201       if(hModule)
202       {
203          uint16 _wfileName[MAX_LOCATION];
204          GetModuleFileNameW(hModule, _wfileName, MAX_LOCATION);
205          UTF16toUTF8Buffer(_wfileName, (byte *)fileName, MAX_LOCATION);
206          return true;
207       }
208    }
209    else
210    {
211       uint16 _wfileName[MAX_LOCATION];
212       GetModuleFileNameW(null, _wfileName, MAX_LOCATION);
213       UTF16toUTF8Buffer(_wfileName, (byte *)fileName, MAX_LOCATION);
214       return true;
215    }
216 #elif defined(__APPLE__)
217    if(name && name[0])
218    {
219       int imageCount = _dyld_image_count();
220       int c;
221       int nameLen = strlen(name);
222       for(c = 0; c<imageCount; c++)
223       {
224          struct mach_header * header = _dyld_get_image_header(c);
225          char * path = _dyld_get_image_name(c);
226          int pathLen = strlen(path);
227          char * subStr = RSearchString(path, name, pathLen, false, false);
228          if(subStr)
229          {
230             if(( *(subStr-1) == '/' || !strncmp(subStr - 4, "/lib", 4)) &&
231                (!subStr[nameLen] || !strncmp(subStr + nameLen, ".dylib", 6)))
232             {
233                strcpy(fileName, path);
234                return true;
235             }
236          }
237       }
238    }
239    else
240    {
241       int size = MAX_LOCATION;
242       _NSGetExecutablePath(fileName, &size);
243       return true;
244    }
245 #elif defined(__unix__)
246    //File f = FileOpen("/proc/self/maps", read);
247    FILE * f;
248    char exeName[MAX_FILENAME];
249    exeName[0] = 0;
250 #if defined(__linux__)
251    f = fopen("/proc/self/status", "r");
252 #else
253    f = fopen("/proc/curproc/status", "r");
254 #endif
255    if(f)
256    {
257       char line[1025];
258       while(fgets(line, sizeof(line), f))
259       {
260          char * name = strstr(line, "Name:\t");
261          if(name)
262          {
263             int nameLen;
264             name += 6;
265             nameLen = strlen(name);
266             name[--nameLen] = 0;
267             strcpy(exeName, name);
268             break;
269          }
270       }
271       fclose(f);
272   }
273 #if defined(__linux__)
274    f = fopen("/proc/self/maps", "r");
275 #else
276    f = fopen("/proc/curproc/map", "r");
277 #endif
278    if(f)
279    {
280       char line[1025];
281       //while(f.GetLine(line, sizeof(line)))
282       while(fgets(line, sizeof(line), f))
283       {
284          char * path = strstr(line, "/");
285          if(path)
286          {
287             int pathLen = strlen(path);
288             path[--pathLen] = 0;
289             if(name && name[0])
290             {
291                int nameLen = strlen(name);
292                char * subStr;
293                subStr = RSearchString(path, name, pathLen, false, false);
294                if(subStr)
295                {
296                   if(( *(subStr-1) == '/' || !strncmp(subStr - 4, "/lib", 4)) &&
297                      (!subStr[nameLen] || !strncmp(subStr + nameLen, ".so", 3)))
298                   {
299                      char * space = strchr(path, ' ');
300                      if(space) *space = 0;
301                      strcpy(fileName, path);
302                      fclose(f);
303                      return true;
304                   }
305                }
306             }
307             else
308             {
309                char name[MAX_FILENAME];
310                GetLastDirectory(path, name);
311                if(!exeName[0] || !strcmp(name, exeName))
312                {
313                   char * space = strchr(path, ' ');
314                   if(space) *space = 0;
315                   strcpy(fileName, path);
316                   fclose(f);
317                   return true;
318                }
319             }
320          }
321       }
322       fclose(f);
323    }
324 #if !defined(ECERE_NOFILE) && !defined(__linux__)
325    if(name && name[0])
326    {
327       // Couldn't locate libraries with /proc/curmap/map, attempt with ldd
328       FILE * in = null, * out = null;
329       _DualPipe * p;
330       char command[MAX_LOCATION];
331       snprintf(command, sizeof(command), "ldd /proc/%d/file", (int)getpid());
332       p  = _DualPipeOpen(1, command, null, &in, &out);
333       if(p)
334       {
335          bool result = false;
336          char line[1025];
337          int nameLen = strlen(name);
338          while(DualPipe_GetLine(in, line, sizeof(line)))
339          {
340             char * path = strstr(line, "/");
341             if(path)
342             {
343                int pathLen = strlen(path);
344                char * subStr;
345                path[--pathLen] = 0;
346                subStr = RSearchString(path, name, pathLen, false, false);
347                if(subStr)
348                {
349                   if(( *(subStr-1) == '/' || !strncmp(subStr - 4, "/lib", 4)) &&
350                      (!subStr[nameLen] || !strncmp(subStr + nameLen, ".so", 3)))
351                   {
352                      char * space = strchr(path, ' ');
353                      if(space) *space = 0;
354                      strcpy(fileName, path);
355                      result = true;
356                   }
357                }
358             }
359          }
360          DualPipe_Wait(p);
361          fclose(in);
362          DualPipe_Destructor(p);
363          return result;
364       }
365    }
366 #endif
367    if(!name || !name[0])
368    {
369 #if defined(__FreeBSD__)
370       {
371          int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
372          size_t cb = MAX_LOCATION;
373          fileName[0] = 0;
374          sysctl(mib, 4, fileName, &cb, null, 0);
375          if(fileName[0])
376             return true;
377       }
378 #endif
379 #if !defined(__linux__)
380       {
381          char * env;
382          if(!access("/proc/curproc/file", F_OK))
383          {
384             strcpy(fileName, "/proc/curproc/file");
385             return true;
386          }
387          if((env = getenv("_")))
388          {
389             strcpy(fileName, env);
390             return true;
391          }
392       }
393 #endif
394       strcpy(fileName, exeLocation);
395       return true;
396    }
397 #endif
398    return false;
399 }
400
401 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, char *** argvPtr)
402 {
403 #if !defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
404    // Disable stdout buffering on Unix
405    setvbuf(stdout, null, _IONBF, 0);
406 #endif
407 #if defined(__WIN32__)
408    *parsedCommand = UTF16toUTF8(GetCommandLineW());
409    *argvPtr = eSystem_New0(sizeof(char *) * 512);
410    *argcPtr = Tokenize(*parsedCommand, 512,(void*)(char **)(*argvPtr), forArgsPassing);
411 #else
412    *argcPtr = argc;
413    *argvPtr = argv;
414 #endif
415 #if defined(__unix__)
416    if(!__thisModule && argv)
417    {
418       getcwd(exeLocation, MAX_LOCATION);
419       PathCat(exeLocation, argv[0]);
420    }
421 #endif
422 }
423
424 void * Instance_Module_Load(const char * libLocation, const char * name, void ** Load, void ** Unload)
425 {
426    char fileName[MAX_LOCATION];
427    char extension[MAX_EXTENSION];
428    void * library = null;
429 #if defined(__unix__) || defined(__APPLE__)
430    int attempts = 0;
431    char * paths[] = { null, "/usr/lib/ec/lib", "/usr/lib32/ec/lib" };
432 #endif
433
434    *Load = null;
435    *Unload = null;
436
437 #if defined(__WIN32__)
438    strcpy(fileName, name);
439    GetExtension(fileName, extension);
440    if(!extension[0])
441       strcat(fileName, ".dll");
442
443    {
444       uint16 _wfileName[MAX_LOCATION];
445       UTF8toUTF16Buffer(fileName, _wfileName, MAX_LOCATION);
446       library = LoadLibraryW(_wfileName);
447    }
448    if(library)
449    {
450 #ifdef _WIN64
451       *Load = (void *)GetProcAddress(library, "__ecereDll_Load");
452       *Unload = (void *)GetProcAddress(library, "__ecereDll_Unload");
453 #else
454       *Load = (void *)GetProcAddress(library, "__ecereDll_Load@4");
455       *Unload = (void *)GetProcAddress(library, "__ecereDll_Unload@4");
456 #endif
457       if(!*Load)
458          FreeLibrary(library);
459    }
460 #elif defined(__unix__) || defined(__APPLE__)
461    if(libLocation || strchr(name, '/'))
462       strcpy(fileName, libLocation ? libLocation : "");
463    else
464       strcpy(fileName, "lib");
465    strcat(fileName, name);
466    GetExtension(fileName, extension);
467    if(!extension[0])
468 #if defined(__APPLE__)
469       strcat(fileName, ".dylib");
470 #else
471       strcat(fileName, ".so");
472 #endif
473
474    library = dlopen(fileName, RTLD_LAZY);
475    while(!library && attempts < sizeof(paths)/sizeof(paths[0]))
476    {
477       if(paths[attempts])
478          strcpy(fileName, paths[attempts++]);
479       else
480       {
481          attempts++;
482 #ifdef DEB_HOST_MULTIARCH
483          strcpy(fileName, DEB_HOST_MULTIARCH);
484          strcat(fileName, "/ec/lib");
485 #else
486          continue;
487 #endif
488       }
489       strcat(fileName, name);
490       GetExtension(fileName, extension);
491       if(!extension[0])
492 #if defined(__APPLE__)
493          strcat(fileName, ".dylib");
494 #else
495          strcat(fileName, ".so");
496 #endif
497       library = dlopen(fileName, RTLD_LAZY);
498    }
499
500    if(library)
501    {
502       *Load = dlsym(library, "__ecereDll_Load");
503       *Unload = dlsym(library, "__ecereDll_Unload");
504       if(!*Load)
505          dlclose(library);
506    }
507 #elif defined(__APPLE__)
508    if(libLocation || strchr(name, '/'))
509       strcpy(fileName, libLocation ? libLocation : "");
510    else
511       strcpy(fileName, "lib");
512    strcat(fileName, name);
513    GetExtension(fileName, extension);
514    if(!extension[0])
515       strcat(fileName, ".dylib");
516    {
517       NSObjectFileImage *fileImage;
518       NSObjectFileImageReturnCode returnCode = NSCreateObjectFileImageFromFile(fileName, &fileImage);
519
520       if(returnCode == NSObjectFileImageSuccess)
521       {
522          printf("NSObjectFileImageSuccess!\n");
523          library = NSLinkModule(fileImage,fileName,
524               NSLINKMODULE_OPTION_RETURN_ON_ERROR
525             | NSLINKMODULE_OPTION_PRIVATE);
526          // NSDestroyObjectFileImage(fileImage);
527          if(library)
528          {
529             *Load = NSAddressOfSymbol(NSLookupSymbolInModule(library, "__ecereDll_Load"));
530             *Unload = NSAddressOfSymbol(NSLookupSymbolInModule(library, "__ecereDll_Unload"));
531             if(!*Load)
532             {
533                NSUnLinkModule(library, 0);
534             }
535             else
536                printf("Found Load!\n");
537          }
538       }
539       else
540          printf("No Success :(\n");
541    }
542 #endif
543    return library;
544 }
545
546 void Instance_Module_Free(void * library)
547 {
548 #if defined(__WIN32__)
549    if(library)
550       FreeLibrary(library);
551 #elif defined(__unix__) || defined(__APPLE__)
552    if(library)
553       dlclose(library);
554 #endif
555 }
556
557 #if defined(_DEBUG)
558    void InternalModuleLoadBreakpoint()
559    {
560    }
561 #endif