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