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