ecere/gui/GuiApplication: Fixed OS X compilation
[sdk] / compiler / ecs / ecs.ec
1 #ifdef ECERE_STATIC
2 import static "ecere"
3 import static "ec"
4 #else
5 import "ecere"
6 import "ec"
7 #endif
8
9 static define localeDir = "locale";
10 static bool i18n;
11 static bool outputPot;
12 static bool disabledPooling;
13
14 static Platform targetPlatform;
15 static int targetBits;
16
17 static bool isConsole;
18 static bool isDynamicLibrary;
19 static bool isStaticLibrary;
20 static OldList modules;
21 static File dcomSymbols;
22
23 static OldList _defines { };
24 static OldList _imports { };
25 static OldList _excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left };
26 static NameSpace globalData
27 {
28    classes.CompareKey = (void *)BinaryTree::CompareString;
29    defines.CompareKey = (void *)BinaryTree::CompareString;
30    functions.CompareKey = (void *)BinaryTree::CompareString;
31    nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
32 };
33 static Context theGlobalContext { };
34 static ModuleImport mainModule;
35 static Module privateModule;
36
37 static char mainModuleName[MAX_LOCATION];
38 static char projectName[MAX_LOCATION];
39 static void LoadImports(const char * fileName)
40 {
41    File f = FileOpen(fileName, read);
42    if(f)
43    {
44       for(;;)
45       {
46          char line[1024];
47          if(!f.GetLine(line, sizeof(line))) break;
48          TrimLSpaces(line, line);
49
50          if(line[0] == '[')
51          {
52             if(!strcmp(line, "[Imported Modules]"))
53             {
54                ModuleImport module = null;
55                for(;;)
56                {
57                   if(!f.GetLine(line, sizeof(line))) break;
58                   TrimLSpaces(line, line);
59                   if(!strcmp(line, ".")) break;
60
61                   if(line[0] == '[')
62                   {
63                      ClassImport _class = null;
64                      FunctionImport function = null;
65
66                      if(!strcmp(line, "[This]"))
67                      {
68                         if((mainModule = GetMainModule()))
69                            module = mainModule;
70                         else
71                         {
72                            mainModule = ModuleImport { };
73                            SetMainModule(mainModule);
74                            module = mainModule;
75                            _imports.AddName(module);
76                         }
77                      }
78                      else if(!strcmp(line, "[Static]"))
79                      {
80                         module.importType = staticImport;
81                      }
82                      else if(!strcmp(line, "[Remote]"))
83                      {
84                         module.importType = remoteImport;
85                      }
86                      else if(!strcmp(line, "[Private]"))
87                      {
88                         if(module.importAccess != publicAccess)
89                            module.importAccess = privateAccess;
90                      }
91                      else if(!strcmp(line, "[Public]"))
92                      {
93                         module.importAccess = publicAccess;
94                      }
95                      else if(!strcmp(line, "[Imported Classes]"))
96                      {
97                         for(;;)
98                         {
99                            if(!f.GetLine(line, sizeof(line))) break;
100                            TrimLSpaces(line, line);
101                            if(!strcmp(line, ".")) break;
102
103                            if(line[0] == '[')
104                            {
105                               if(!strcmp(line, "[Instantiated]"))
106                               {
107                                  _class.itself = true;
108                               }
109                               else if(!strcmp(line, "[Remote]"))
110                               {
111                                  _class.isRemote = 1;
112                               }
113                               else if(!strcmp(line, "[Imported Methods]"))
114                               {
115                                  MethodImport method = null;
116                                  for(;;)
117                                  {
118                                     if(!f.GetLine(line, sizeof(line))) break;
119                                     TrimLSpaces(line, line);
120                                     if(!strcmp(line, ".")) break;
121                                     if(line[0] != '[')
122                                     {
123                                        if(!(method = _class.methods.FindName(line, false)))
124                                        {
125                                           method = MethodImport { name = CopyString(line) };
126                                           _class.methods.AddName(method);
127                                        }
128                                     }
129                                     else if(!strcmp(line, "[Virtual]"))
130                                        method.isVirtual = true;
131
132                                  }
133                               }
134                               else if(!strcmp(line, "[Imported Properties]"))
135                               {
136                                  PropertyImport prop = null;
137                                  for(;;)
138                                  {
139                                     if(!f.GetLine(line, sizeof(line))) break;
140                                     TrimLSpaces(line, line);
141                                     if(!strcmp(line, ".")) break;
142                                     if(line[0] != '[')
143                                     {
144                                        if(!(prop = _class.properties.FindName(line, false)))
145                                        {
146                                           prop = PropertyImport { name = CopyString(line) };
147                                           _class.properties.AddName(prop);
148                                        }
149                                     }
150                                     else if(!strcmp(line, "[Set]"))
151                                           prop.hasSet = true;
152                                     else if(!strcmp(line, "[Get]"))
153                                        prop.hasGet = true;
154                                     else if(!strcmp(line, "[Virtual]"))
155                                        prop.isVirtual = true;
156                                  }
157                               }
158                            }
159                            else
160                            {
161                               if(!(_class = module.classes.FindName(line, false)))
162                               {
163                                  _class = ClassImport { name = CopyString(line) };
164                                  module.classes.AddName(_class);
165                               }
166                            }
167                         }
168                      }
169                      else if(!strcmp(line, "[Imported Functions]"))
170                      {
171                         for(;;)
172                         {
173                            if(!f.GetLine(line, sizeof(line))) break;
174                            TrimLSpaces(line, line);
175                            if(!strcmp(line, ".")) break;
176
177                            if(line[0] == '[')
178                            {
179                            }
180                            else
181                            {
182                               if(!(function = module.functions.FindName(line, false)))
183                               {
184                                  function = FunctionImport { name = CopyString(line) };
185                                  module.functions.AddName(function);
186                               }
187                            }
188                         }
189                      }
190                   }
191                   else
192                   {
193                      if(!(module = _imports.FindName(line, false)))
194                      {
195                         if(!strcmp(line, "ecereCOM"))
196                         {
197                            module = _imports.FindName("ecere", false);
198                         }
199                         else if(!strcmp(line, "ecere"))
200                         {
201                            module = _imports.FindName("ecereCOM", false);
202                            if(module)
203                            {
204                               delete module.name;
205                               module.name = CopyString("ecere");
206                            }
207                         }
208                         if(!module)
209                         {
210                            module = ModuleImport { name = CopyString(line) };
211                            _imports.AddName(module);
212                         }
213                      }
214                   }
215                }
216             }
217          }
218       }
219       delete f;
220    }
221 }
222
223 // static Class applicationClass;
224 static Class thisAppClass;
225
226 class ModuleInfo : struct
227 {
228    ModuleInfo prev, next;
229    char * name;
230    bool globalInstance;
231 };
232
233 /* OBSOLETE
234 static bool SeardchModuleName(Module searchIn, char * name)
235 {
236    SubModule subModule;
237
238    if(searchIn.name && !strcmp(searchIn.name, name))
239       return true;
240
241    for(subModule = searchIn.modules.first; subModule; subModule = subModule.next)
242    {
243       if(SearchModuleName(subModule.module, name))
244          return true;
245    }
246    return false;
247 }
248 */
249 static void WriteMain(const char * fileName)
250 {
251    File f = FileOpen(fileName, write);
252    if(f)
253    {
254       ModuleImport module;
255       ModuleInfo defModule;
256       bool /*nonInst = false, */anyMethod = false, anyProp = false, anyFunction = false;
257       ImportedModule importedModule;
258
259       GetLastDirectory(fileName, mainModuleName);
260       StripExtension(mainModuleName);
261       if(!projectName[0])
262       {
263          strcpy(projectName, mainModuleName);
264          StripExtension(projectName);
265       }
266       FixModuleName(mainModuleName);
267
268       if(targetPlatform == win32 && !isConsole && !isStaticLibrary && !isDynamicLibrary)
269       {
270          //f.Puts("#include <windows.h>\n\n");
271
272          f.Puts("typedef void * HINSTANCE;\n");
273          f.Puts("#define WINAPI __stdcall\n");
274       }
275
276       for(importedModule = ::_defines.first; importedModule; importedModule = importedModule.next)
277       {
278          if(importedModule.type == moduleDefinition)
279          {
280             f.Printf("import ");
281             if(importedModule.importType == staticImport)
282                f.Printf("static ", importedModule.name);
283             f.Printf("\"%s\"\n", importedModule.name);
284          }
285       }
286
287       f.Puts("default:\n");
288       f.Puts("static Module __currentModule;\n\n");
289
290       if(!isStaticLibrary)
291          f.Puts("Module __thisModule;\n\n");
292
293       // TOCHECK: Problem compiling Scrabble.main.ec when binding Client first
294       BindDCOMServer();
295       BindDCOMClient();
296
297       if(dcomSymbols)
298          f.Printf("void __ecereRegisterModule_%s(Module module);\n\n", mainModuleName);
299
300       for(module = _imports.first; module; module = module.next)
301       {
302          ClassImport _class;
303          FunctionImport function;
304          if(module.importType == staticImport)
305          {
306             /*if(targetPlatform == win32)
307             {
308                f.Printf("bool __stdcall __ecereDll_Load_%s(Module module);\n", module.name);
309                f.Printf("bool __stdcall __ecereDll_Unload_%s(Module module);\n", module.name);
310             }
311             else*/
312             {
313                f.Printf("bool __ecereDll_Load_%s(Module module);\n", module.name);
314                f.Printf("bool __ecereDll_Unload_%s(Module module);\n", module.name);
315             }
316          }
317          for(_class = module.classes.first; _class; _class = _class.next)
318          {
319             MethodImport method;
320             PropertyImport prop;
321             char className[1024] = "";
322             Class regClass = eSystem_FindClass(privateModule, _class.name);
323
324             FullClassNameCat(className, _class.name, true);
325
326             if(_class.itself)
327                f.Printf("Class __ecereClass_%s;\n", className);
328             /*else
329                nonInst = true;*/
330             //if(!_class.isRemote)
331             {
332                //if(strcmp(_class.name, "SerialBuffer"))
333                {
334                   for(method = _class.methods.first; method; method = method.next)
335                   {
336                      Method meth = eClass_FindMethod(regClass, method.name, privateModule);
337                      if(meth && !meth.dataType)
338                      {
339                         Context context = SetupTemplatesContext(regClass);
340                         meth.dataType = ProcessTypeString(meth.dataTypeString, false);
341                         FinishTemplatesContext(context);
342                      }
343
344                      if(method.isVirtual)
345                         f.Printf("int __ecereVMethodID_%s_%s;\n", className, method.name);
346                      else if((!strcmp(_class.name, "float") || !strcmp(_class.name, "double") || module.name) && module.importType != staticImport && (!meth || !meth.dataType.dllExport))
347                      {
348                         /*char name[4096];
349
350                         Type type
351                         {
352                            kind = TypePointer,
353                            type = method.
354                         };
355                         type.refCount++;
356                         sprintf(name, "__ecereMethod_%s_%s", className, method.name);
357                         PrintType(type, name, true);
358                         f.Printf("%s;\n", name);
359                         delete type;
360                         */
361                         //f.Printf("void * __ecereMethod_%s_%s;\n", className, method.name);
362
363                         f.Printf("int (*__ecereMethod_%s_%s)();\n", className, method.name);
364                      }
365
366                      anyMethod = true;
367                   }
368                }
369
370                for(prop = _class.properties.first; prop; prop = prop.next)
371                {
372                   char propName[1024];
373                   propName[0] = 0;
374                   FullClassNameCat(propName, prop.name, true);
375
376                   if((!strcmp(_class.name, "float") || !strcmp(_class.name, "double") || module.name) && module.importType != staticImport)
377                   {
378                      if(prop.hasSet)
379                         f.Printf("void * __ecereProp_%s_Set_%s;\n", className, propName);
380                      if(prop.hasGet)
381                         f.Printf("void * __ecereProp_%s_Get_%s;\n", className, propName);
382                   }
383                   f.Printf("Property __ecereProp_%s_%s;\n", className, propName);
384                   anyProp = true;
385                }
386             }
387          }
388          for(function = module.functions.first; function; function = function.next)
389          {
390             GlobalFunction func = eSystem_FindFunction(privateModule, function.name);
391             if(func && !func.dataType)
392                func.dataType = ProcessTypeString(func.dataTypeString, false);
393
394             if(module.name && module.importType != staticImport && (!func || !func.dataType || !func.dataType.dllExport))
395             {
396                char functionName[1024];
397                functionName[0] = 0;
398                FullClassNameCat(functionName, function.name, false);
399                f.Printf("void * __ecereFunction_%s;\n", functionName);
400                anyFunction = true;
401             }
402          }
403       }
404
405       for(defModule = ::modules.first; defModule; defModule = defModule.next)
406       {
407          char moduleName[1024];
408          strcpy(moduleName, defModule.name);
409          FixModuleName(moduleName);
410          f.Printf("void __ecereRegisterModule_%s(Module module);\n", moduleName);
411          f.Printf("void __ecereUnregisterModule_%s(Module module);\n", moduleName);
412          if(defModule.globalInstance)
413          {
414             f.Printf("void __ecereCreateModuleInstances_%s();\n", moduleName);
415             f.Printf("void __ecereDestroyModuleInstances_%s();\n", moduleName);
416          }
417       }
418
419       // DCOM Stuff
420       if(dcomSymbols)
421       {
422          f.Printf("\n");
423
424          // Insert DCOM bindings here
425          dcomSymbols.Seek(0, start);
426          while(!dcomSymbols.Eof())
427          {
428             char buffer[4096];
429             int read = dcomSymbols.Read(buffer, 1, sizeof(buffer));
430             if(!read) break;
431             f.Write(buffer, 1, read);
432          }
433          f.Printf("\n");
434       }
435
436       // Main Function
437
438       if(isStaticLibrary)
439       {
440          /*if(targetPlatform == win32)
441             f.Printf("\nbool __stdcall __ecereDll_Load_%s(Module module)\n{\n", projectName);
442          else*/
443             f.Printf("\nbool __ecereDll_Load_%s(Module module)\n{\n", projectName);
444       }
445       else if(isDynamicLibrary)
446       {
447          if(targetPlatform == win32)
448             f.Puts("\ndllexport bool __stdcall __ecereDll_Load(Module module)\n{\n");
449          else
450             f.Puts("\ndllexport bool __ecereDll_Load(Module module)\n{\n");
451       }
452       else if(targetPlatform == win32 && !isConsole)
453       {
454          f.Puts("\nint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, char * cmdLine, int show)\n{\n");
455       }
456       else
457          f.Puts("\nint main(int _argc, char * _argv[])\n{\n");
458
459       if(!isDynamicLibrary)
460       {
461          f.Puts("   int exitCode;\n");
462          f.Puts("   Module module;\n");
463       }
464
465       //if(nonInst || thisAppClass)    // We use it all the time to get "Application" for the exit code now...
466          f.Puts("   __attribute__((unused)) Class _class;\n");
467
468       if(anyMethod)
469          f.Puts("   __attribute__((unused)) Method method;\n");
470       if(anyProp)
471          f.Puts("   __attribute__((unused)) Property _property;\n");
472       if(anyFunction)
473          f.Puts("   __attribute__((unused)) GlobalFunction function;\n");
474
475       f.Puts("\n");
476
477       if(disabledPooling)
478       {
479          f.Puts("   eSystem_SetPoolingDisabled(true);\n");
480          f.Puts("\n");
481       }
482
483       if(isDynamicLibrary)
484       {
485          f.Puts("   if(!__currentModule)\n");
486          f.Puts("   {\n");
487          f.Puts("      __currentModule = module;\n");
488          if(!isStaticLibrary)
489             f.Puts("      __thisModule = module;\n");
490          f.Puts("   }\n\n");
491       }
492       else if(targetPlatform == win32 && !isConsole)
493          f.Puts("   __thisModule = __currentModule = module = __ecere_COM_Initialize(1, 0, null);\n\n");
494       else
495          f.Puts("   __thisModule = __currentModule = module = __ecere_COM_Initialize(1, _argc, (void *)_argv);\n\n");
496
497       // First load all modules
498       if(_imports.count)
499       {
500          for(module = _imports.first; module; module = module.next)
501          {
502             if(module.name)
503             {
504                //if(strcmp(module.name, "ecereCOM") && strcmp(module.name, "ecere") )
505                {
506                   if(module.importType == staticImport)
507                      f.Printf("   eModule_LoadStatic(module, \"%s\", %s, __ecereDll_Load_%s, __ecereDll_Unload_%s);\n", module.name, (module.importAccess == privateAccess) ? "privateAccess" : "publicAccess", module.name,module.name);
508                   else
509                      f.Printf("   eModule_Load(module, \"%s\", %s);\n", module.name, (module.importAccess == privateAccess) ? "privateAccess" : "publicAccess");
510                }
511             }
512          }
513          f.Printf("\n");
514       }
515
516       // Then define the classes
517       if(::modules.count)
518       {
519          for(defModule = ::modules.first; defModule; defModule = defModule.next)
520          {
521             char moduleName[1024];
522             strcpy(moduleName, defModule.name);
523             FixModuleName(moduleName);
524             f.Printf("   __ecereRegisterModule_%s(module);\n", moduleName);
525          }
526          f.Printf("\n");
527       }
528
529       // Register Remote Modules
530       if(dcomSymbols)
531       {
532          f.Printf("   __ecereRegisterModule_%s(module);\n\n", mainModuleName);
533          delete dcomSymbols;
534       }
535
536       if(isDynamicLibrary)
537       {
538          f.Puts("   if(__currentModule == module)\n");
539          f.Puts("   {\n");
540       }
541       // Then load the imports
542       for(module = _imports.first; module; module = module.next)
543       {
544          ClassImport _class;
545          FunctionImport function;
546          if(module.classes.count)
547          {
548             for(_class = module.classes.first; _class; _class = _class.next)
549             {
550                Class regClass = eSystem_FindClass(privateModule, _class.name);
551
552                //if(!_class.isRemote)
553                {
554                   MethodImport method;
555                   PropertyImport prop;
556                   char classID[1024];
557                   char className[1024] = "";
558                   FullClassNameCat(className, _class.name, true);
559
560                   if(_class.itself)
561                      sprintf(classID, "__ecereClass_%s", className);
562                   else
563                      strcpy(classID, "_class");
564
565                   if(isDynamicLibrary && !isStaticLibrary)
566                      f.Printf("   %s = eSystem_FindClass(__currentModule, \"%s\");\n", classID, _class.name);
567                   else
568                      f.Printf("   %s = eSystem_FindClass(module, \"%s\");\n", classID, _class.name);
569
570                   for(method = _class.methods.first; method; method = method.next)
571                   {
572                      Method meth = eClass_FindMethod(regClass, method.name, privateModule);
573                      if(!meth || !meth.dataType.dllExport)
574                      {
575                         if(method.isVirtual || ((!strcmp(_class.name, "float") || !strcmp(_class.name, "double") || module.name) && module.importType != staticImport))
576                         {
577                            f.Printf("   method = eClass_FindMethod(%s, \"%s\", module);\n",
578                               classID, method.name);
579                            if(method.isVirtual)
580                               f.Printf("   if(method) __ecereVMethodID_%s_%s = method.vid;\n", className, method.name);
581                            else
582                               f.Printf("   if(method) __ecereMethod_%s_%s = method.function;\n", className, method.name);
583                         }
584                      }
585                   }
586
587                   for(prop = _class.properties.first; prop; prop = prop.next)
588                   {
589                      char propName[1024];
590                      propName[0] = 0;
591                      FullClassNameCat(propName, prop.name, true);
592
593                      f.Printf("   __ecereProp_%s_%s = _property = eClass_FindProperty(%s, \"%s\", module);\n",
594                         className, propName, classID, prop.name);
595
596                      if((!strcmp(_class.name, "float") || !strcmp(_class.name, "double") || module.name) && module.importType != staticImport)
597                      {
598                         if(prop.hasSet)
599                            f.Printf("   __ecereProp_%s_Set_%s = _property.Set;\n", className, propName);
600                         if(prop.hasGet)
601                            f.Printf("   __ecereProp_%s_Get_%s = _property.Get;\n", className, propName);
602                      }
603                   }
604                   f.Printf("\n");
605                }
606             }
607          }
608          if(module.functions.count)
609          {
610             for(function = module.functions.first; function; function = function.next)
611             {
612                GlobalFunction func = eSystem_FindFunction(privateModule, function.name);
613                if(module.name && module.importType != staticImport && (!func || !func.dataType || !func.dataType.dllExport))
614                {
615                   char functionName[1024];
616                   functionName[0] = 0;
617                   FullClassNameCat(functionName, function.name, false);
618
619                   if(isDynamicLibrary && !isStaticLibrary)
620                      f.Printf("   function = eSystem_FindFunction(__currentModule, \"%s\");\n", function.name);
621                   else
622                      f.Printf("   function = eSystem_FindFunction(module, \"%s\");\n", function.name);
623
624                   f.Printf("   if(function) __ecereFunction_%s = function.function;\n", functionName);
625                   f.Printf("\n");
626                }
627             }
628             f.Printf("\n");
629          }
630       }
631
632       for(defModule = ::modules.first; defModule; defModule = defModule.next)
633          if(defModule.globalInstance)
634          {
635             if(!strcmp(defModule.name, "i18n"))
636                f.Printf("   __ecereCreateModuleInstances_i18n();\n");
637          }
638       if(i18n)
639       {
640          if(isDynamicLibrary)
641             f.Printf("      LoadTranslatedStrings(\"%s\", \"%s\");\n", projectName, projectName);
642          else
643             f.Printf("      LoadTranslatedStrings(null, \"%s\");\n", projectName);
644       }
645       if(isDynamicLibrary)
646       {
647          //f.Printf("   module._vTbl[10](module);\n");
648          f.Puts("   }\n");
649       }
650
651       if(!isDynamicLibrary && thisAppClass)
652       {
653          f.Printf("   _class = eSystem_FindClass(__currentModule, \"%s\");\n", thisAppClass.name);
654          f.Printf("   eInstance_Evolve((Instance *)&__currentModule, _class);\n");
655          f.Printf("   __thisModule = __currentModule;\n");
656       }
657
658       if(isDynamicLibrary)
659       {
660          f.Puts("   if(__currentModule == module)\n");
661          f.Puts("   {\n");
662       }
663
664       // Then check if there's any global instances to create
665       if(::modules.count)
666       {
667          for(defModule = ::modules.first; defModule; defModule = defModule.next)
668             if(defModule.globalInstance)
669             {
670                char moduleName[1024];
671                if(!strcmp(defModule.name, "i18n")) continue;
672                strcpy(moduleName, defModule.name);
673                FixModuleName(moduleName);
674                f.Printf("   __ecereCreateModuleInstances_%s();\n", moduleName);
675             }
676
677          f.Printf("\n");
678       }
679
680       if(isDynamicLibrary)
681       {
682          f.Puts("   }\n");
683       }
684       if(!isDynamicLibrary && thisAppClass)
685       {
686          f.Printf("   ((void(*)(void *))(void *)__currentModule._vTbl[12])(__currentModule);\n");
687       }
688
689       if(isDynamicLibrary)
690       {
691          f.Puts("   return true;\n");
692          f.Puts("}\n");
693          if(isStaticLibrary)
694          {
695             /*if(targetPlatform == win32)
696                f.Printf("\nbool __stdcall __ecereDll_Unload_%s(Module module)\n{\n", projectName);
697             else*/
698                f.Printf("\nbool __ecereDll_Unload_%s(Module module)\n{\n", projectName);
699          }
700          else
701          {
702             if(targetPlatform == win32)
703                f.Puts("\ndllexport bool __stdcall __ecereDll_Unload(Module module)\n{\n");
704             else
705                f.Puts("\ndllexport bool __ecereDll_Unload(Module module)\n{\n");
706          }
707       }
708
709       if(isDynamicLibrary)
710       {
711          f.Puts("   if(__currentModule == module)\n");
712          f.Puts("   {\n");
713       }
714       // Then check if there's any global instances to destroy
715       {
716          bool destroyI18n = false;
717          if(::modules.count)
718          {
719             for(defModule = ::modules.last; defModule; defModule = defModule.prev)
720                if(defModule.globalInstance)
721                {
722                   char moduleName[1024];
723                   if(!strcmp(defModule.name, "i18n")) { destroyI18n = true; continue; }
724                   strcpy(moduleName, defModule.name);
725                   FixModuleName(moduleName);
726                   f.Printf("   __ecereDestroyModuleInstances_%s();\n", moduleName);
727                }
728
729             f.Printf("\n");
730          }
731          if(i18n)
732             //f.Printf("   UnloadTranslatedStrings(__currentModule);\n");
733             f.Printf("   UnloadTranslatedStrings(\"%s\");\n", projectName);
734          if(destroyI18n)
735             f.Printf("   __ecereDestroyModuleInstances_i18n();\n");
736       }
737       if(isDynamicLibrary)
738       {
739          f.Puts("   }\n");
740
741          if(isDynamicLibrary)
742          {
743             //f.Printf("   module._vTbl[11](module);\n");
744          }
745
746          if(::modules.count)
747          {
748             for(defModule = ::modules.first; defModule; defModule = defModule.next)
749             {
750                char moduleName[1024];
751                strcpy(moduleName, defModule.name);
752                FixModuleName(moduleName);
753                f.Printf("   __ecereUnregisterModule_%s(module);\n", moduleName);
754             }
755             f.Printf("\n");
756          }
757          f.Puts("   if(__currentModule == module)\n");
758          f.Puts("      __currentModule = (void *)0;\n");
759          if(!isStaticLibrary)
760          {
761             f.Puts("   if(__thisModule == module)\n");
762             f.Puts("      __thisModule = (void *)0;\n");
763          }
764       }
765
766       if(!isDynamicLibrary)
767       {
768          f.Puts(
769             "\n"
770             "   _class = eSystem_FindClass(__currentModule, \"ecere::com::Application\");\n"
771             "   exitCode = ((ecere::com::Application)__currentModule).exitCode;\n"
772             "   delete __currentModule;\n"
773             "   return exitCode;\n");
774       }
775       else
776          f.Puts("   return true;\n");
777       f.Puts("}\n");
778       eInstance_Delete(f);
779    }
780 }
781
782 static Class FindAppClass(NameSpace * nameSpace, bool thisModule)
783 {
784    BTNamedLink link;
785    NameSpace * ns;
786    for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
787    {
788       Class _class = link.data;
789       /*
790       applicationClass = eSystem_FindClass(_class.module, "Application");
791       if(_class != applicationClass && eClass_IsDerived(_class, applicationClass) && (!thisModule || _class.module == privateModule))
792          return _class;
793       */
794       if(strcmp(_class.fullName, "ecere::com::Application") && (!thisModule || _class.module == privateModule))
795       {
796          Class base;
797          for(base = _class.base; base && base.type != systemClass; base = base.base)
798             if(!strcmp(base.fullName, "ecere::com::Application"))
799                return _class;
800       }
801    }
802
803    for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
804    {
805       Class _class = FindAppClass(ns, thisModule);
806       if(_class) // && _class != applicationClass)
807          return _class;
808    }
809    return null; //applicationClass;
810 }
811
812 static Class SearchAppClass_Module(Module module)
813 {
814    Class appClass;
815    SubModule subModule;
816
817    appClass = FindAppClass(module.publicNameSpace, false);
818    if(appClass) return appClass;
819    appClass = FindAppClass(module.privateNameSpace, false);
820    if(appClass) return appClass;
821
822    for(subModule = module.modules.first; subModule; subModule = subModule.next)
823    {
824       appClass = SearchAppClass_Module(subModule.module);
825       if(appClass) return appClass;
826    }
827    return null;
828 }
829
830 static void BindDCOMClient()
831 {
832    Class dcomClientObjectClass = eSystem_FindClass(privateModule, "ecere::net::DCOMClientObject");
833    OldLink deriv;
834
835    if(dcomClientObjectClass && dcomClientObjectClass.derivatives.first)
836    {
837       File f;
838       if(!dcomSymbols) dcomSymbols = TempFile { };
839       f = dcomSymbols;
840
841       // CLIENT BINDINGS
842       for(deriv = dcomClientObjectClass.derivatives.first; deriv; deriv = deriv.next)
843       {
844          Class _class = deriv.data;
845          Method method, next;
846          int id = 0;
847          int vid;
848          bool doVirtual;
849
850          DeclareClass(null, FindClass("ecere::net::DCOMClientObject"), "__ecereClass___ecereNameSpace__ecere__net__DCOMClientObject");
851          f.Printf("class %s : ecere::net::DCOMClientObject\n", _class.fullName);
852          f.Printf("{\n");
853
854          // CLIENT VIRTUAL METHODS BINDINGS
855          if(_class.vTblSize > _class.base.vTblSize)
856          {
857             int vid;
858             f.Printf("   virtual void CallVirtualMethod(uint __ecereMethodID, SerialBuffer __ecereBuffer)\n");
859             f.Printf("   {\n");
860             f.Printf("      switch(__ecereMethodID)\n");
861             f.Printf("      {\n");
862
863             for(vid = _class.base.vTblSize; vid < _class.vTblSize; vid++)
864             {
865                Method method;
866                for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
867                {
868                   if(method.type == virtualMethod && method._class == _class && method.vid == vid)
869                      break;
870                }
871                if(method)
872                {
873                   Type param;
874                   method.dataType = ProcessTypeString(method.dataTypeString, false);
875                   if(method.dataType && method.dataType.name)
876                   {
877                      f.Printf("         case %d:\n", vid - _class.base.vTblSize);
878                      f.Printf("         {\n");
879                      {
880                         if(method.dataType.returnType.kind != voidType)
881                         {
882                            TypeName resultType;
883                            OldList * specs = MkList();
884                            Declarator decl;
885                            char type[1024] = "";
886                            char className[1024];
887                            Symbol classSym;
888
889                            if(method.dataType.returnType.kind == classType)
890                               classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
891                            else
892                            {
893                               PrintTypeNoConst(method.dataType.returnType, type, false, true);
894                               classSym = FindClass(type);
895                               type[0] = 0;
896                            }
897                            strcpy(className, "__ecereClass_");
898                            FullClassNameCat(className, classSym.string, true);
899                            DeclareClass(null, classSym, className);
900
901                            PrintType(method.dataType.returnType, type, true, true);
902
903                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
904                            resultType = MkTypeName(specs, decl);
905
906                            f.Printf("            ");
907                            OutputTypeName(resultType, f, false);
908                            f.Printf(";\n");
909                         }
910
911                         for(param = method.dataType.params.first; param; param = param.next)
912                         {
913                            if(param.kind == classType && !strcmp(param._class.string, "String"))
914                            {
915                               // Hardcode 1024 chars max string for now
916                               f.Printf("            char %s[1024];\n", param.name);
917                               DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
918                               DeclareClass(null, FindClass("String"), "__ecereClass_String");
919                            }
920                            else
921                            {
922                               TypeName paramTypeName;
923                               OldList * specs = MkList();
924                               Declarator decl;
925                               char type[1024] = "";
926                               char className[1024];
927                               Symbol classSym;
928
929                               if(param.kind == classType)
930                                  classSym = param._class; // VERIFY THIS FindClass(param._class.string);
931                               else
932                               {
933                                  PrintTypeNoConst(param, type, false, true);
934                                  classSym = FindClass(type);
935                                  type[0] = 0;
936                               }
937
938                               strcpy(className, "__ecereClass_");
939                               FullClassNameCat(className, classSym.string, true);
940                               DeclareClass(null, classSym, className);
941
942                               PrintType(param, type, true, true);
943
944                               decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier(param.name /*"__ecereResult"*/)));
945                               paramTypeName = MkTypeName(specs, decl);
946
947                               f.Printf("            ");
948                               OutputTypeName(paramTypeName, f, false);
949
950                               f.Printf(";\n");
951                            }
952                         }
953                         f.Printf("\n");
954
955                         for(param = method.dataType.params.first; param; param = param.next)
956                         {
957                            f.Printf("            __ecereBuffer.Unserialize(");
958                            if(param.kind == classType && !strcmp(param._class.string, "String"))
959                            {
960                               DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
961                               f.Printf("(StaticString)");
962                            }
963                            f.Puts(param.name);
964                            f.Printf(");\n");
965                         }
966
967                         f.Printf("            ");
968                         if(method.dataType.returnType.kind != voidType)
969                            f.Printf("__ecereResult = ");
970
971                         // f.Printf("this.instance.%s(", method.name);
972                         f.Printf("%s(", method.name);
973
974                         for(param = method.dataType.params.first; param; param = param.next)
975                         {
976                            if(param.prev)
977                               f.Printf(", ");
978                            f.Printf("%s", param.name);
979                         }
980
981                         f.Printf(");\n");
982
983                         for(param = method.dataType.params.first; param; param = param.next)
984                         {
985                            if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
986                            {
987                               if(!strcmp(param._class.string, "String"))
988                               {
989                                  DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
990                                  f.Printf("            __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
991                               }
992                               else
993                                  f.Printf("            __ecereBuffer.Serialize(%s);\n", param.name);
994                            }
995                         }
996                         if(method.dataType.returnType.kind != voidType)
997                         {
998                            f.Printf("            __ecereBuffer.Serialize(__ecereResult);\n");
999                         }
1000
1001                         for(param = method.dataType.params.first; param; param = param.next)
1002                         {
1003                            if(param.kind == classType && strcmp(param._class.string, "String") && param._class.registered &&
1004                               (param._class.registered.type == normalClass || param._class.registered.type == noHeadClass))
1005                            {
1006                               f.Printf("            delete %s;\n", param.name);
1007                            }
1008                         }
1009                         if(method.dataType.returnType.kind == classType && strcmp(method.dataType.returnType._class.string, "String") && method.dataType.returnType._class.registered &&
1010                               (method.dataType.returnType._class.registered.type == normalClass || method.dataType.returnType._class.registered.type == noHeadClass))
1011                         {
1012                            f.Printf("            delete __ecereResult;\n");
1013                         }
1014                      }
1015
1016                      f.Printf("            break;\n");
1017                      f.Printf("         }\n");
1018                   }
1019                }
1020             }
1021             f.Printf("      }\n");
1022             f.Printf("   }\n");
1023             f.Printf("\n");
1024          }
1025
1026          doVirtual = true;
1027          id = 0;
1028          vid = _class.base.vTblSize;
1029
1030          next = (Method)_class.methods.first;
1031          while(next && ((next.type == virtualMethod) != doVirtual || (doVirtual && next.vid != vid)))
1032          {
1033             id++;
1034             next = (Method)((BTNode)next).next;
1035             if(!next && doVirtual)
1036             {
1037                if(vid == _class.vTblSize)
1038                   doVirtual = false;
1039                else
1040                   vid++;
1041                id = 0;
1042                next = (Method)_class.methods.first;
1043             }
1044          }
1045          for(method = next; method; method = next)
1046          {
1047             Type param;
1048
1049             if(!method.dataType)
1050                method.dataType = ProcessTypeString(method.dataTypeString, false);
1051
1052             if(method.dataType.name)
1053             {
1054                f.Printf("   ");
1055                if(doVirtual)
1056                {
1057                   char name[1024];
1058                   strcpy(name, "__ecereVMethodID_");
1059                   FullClassNameCat(name, method._class.fullName, true);
1060                   strcat(name, "_");
1061                   strcat(name, method.name);
1062                   DeclareMethod(null, method, name);
1063
1064                   f.Printf("virtual ");
1065                }
1066                f.Printf("%s\n", method.dataTypeString);
1067                f.Printf("   {\n");
1068
1069                if(method.dataType)
1070                {
1071                   if(method.dataType.returnType.kind != voidType)
1072                   {
1073                      TypeName resultType;
1074                      OldList * specs = MkList();
1075                      Declarator decl;
1076                      char type[1024] = "";
1077                      char className[1024];
1078                      Symbol classSym;
1079
1080                      if(method.dataType.returnType.kind == classType)
1081                         classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1082                      else
1083                      {
1084                         PrintTypeNoConst(method.dataType.returnType, type, false, true);
1085                         classSym = FindClass(type);
1086                         type[0] = 0;
1087                      }
1088
1089                      strcpy(className, "__ecereClass_");
1090                      FullClassNameCat(className, classSym.string, true);
1091                      DeclareClass(null, classSym, className);
1092
1093                      PrintType(method.dataType.returnType, type, true, true);
1094
1095                      decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1096                      resultType = MkTypeName(specs, decl);
1097
1098                      f.Printf("      ");
1099                      OutputTypeName(resultType, f, false);
1100                      if(method.dataType.returnType.kind == structType)
1101                         f.Printf(" = { 0 }");
1102                      else if(method.dataType.returnType.kind == classType && method.dataType.returnType._class.registered && method.dataType.returnType._class.registered.type == structClass)
1103                         f.Printf(" { }");
1104                      else
1105                         f.Printf(" = 0");
1106                      f.Printf(";\n\n");
1107                   }
1108                   // f.Printf("      incref this;\n");
1109                   f.Printf("      safeIncRef();\n");
1110                   for(param = method.dataType.params.first; param; param = param.next)
1111                   {
1112                      char type[1024] = "";
1113                      char className[1024];
1114                      Symbol classSym;
1115
1116                      if(param.kind == classType)
1117                         classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1118                      else
1119                      {
1120                         PrintTypeNoConst(param, type, false, true);
1121                         classSym = FindClass(type);
1122                         type[0] = 0;
1123                      }
1124                      strcpy(className, "__ecereClass_");
1125                      FullClassNameCat(className, classSym.string, true);
1126
1127                      DeclareClass(null, classSym, className);
1128
1129                      if(param.kind == classType && !strcmp(param._class.string, "String"))
1130                      {
1131                         DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1132                         f.Printf("      __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
1133                      }
1134                      else
1135                         f.Printf("      __ecereBuffer.Serialize(%s);\n", param.name);
1136                   }
1137                   DeclareMethod(null,
1138                      eClass_FindMethod(
1139                         eSystem_FindClass(privateModule, "ecere::net::DCOMClientObject"), "CallMethod", privateModule),
1140                      "__ecereMethod___ecereNameSpace__ecere__net__DCOMClientObject_CallMethod");
1141
1142                   f.Printf("      if(DCOMClientObject::CallMethod(%d))\n", id++);
1143                   f.Printf("      {\n");
1144                   for(param = method.dataType.params.first; param; param = param.next)
1145                   {
1146                      if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1147                      {
1148                         if(!strcmp(param._class.string, "String"))
1149                         {
1150                            DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1151                            f.Printf("         __ecereBuffer.Unserialize((StaticString)%s);\n", param.name);
1152                         }
1153                         else
1154                            f.Printf("         __ecereBuffer.Unserialize(%s);\n", param.name);
1155                      }
1156                   }
1157                   if(method.dataType.returnType.kind != voidType)
1158                   {
1159                      if(method.dataType.returnType.kind == classType && !strcmp(method.dataType.returnType._class.string, "String"))
1160                      {
1161                         DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1162                         f.Printf("         __ecereBuffer.Unserialize((StaticString)__ecereResult);\n");
1163                      }
1164                      else
1165                         f.Printf("         __ecereBuffer.Unserialize(__ecereResult);\n");
1166                   }
1167                   f.Printf("      }\n");
1168                   f.Printf("      __ecereBuffer.Free();\n");
1169                   //f.Printf("      delete this;\n");
1170                   f.Printf("      safeDecRef();\n");
1171                   if(method.dataType.returnType.kind != voidType)
1172                   {
1173                      f.Printf("      return __ecereResult;\n");
1174                   }
1175                }
1176
1177                f.Printf("   }\n");
1178             }
1179             next = (Method)((BTNode)method).next;
1180             while((!next && doVirtual) || (next && ((next.type == virtualMethod) != doVirtual || (doVirtual && next.vid != vid))))
1181             {
1182                id++;
1183                next = next ? (Method)((BTNode)next).next : null;
1184                if(!next && doVirtual)
1185                {
1186                   if(vid == _class.vTblSize)
1187                      doVirtual = false;
1188                   else
1189                      vid++;
1190                   id = 0;
1191                   next = (Method)_class.methods.first;
1192                }
1193             }
1194
1195             if(next)
1196                f.Printf("\n");
1197          }
1198
1199          f.Printf("}\n");
1200          if(deriv.next)
1201             f.Printf("\n");
1202       }
1203    }
1204 }
1205
1206 static void BindDCOMServer()
1207 {
1208    bool mutexDeclared = false;
1209    Class _class;
1210    for(_class = privateModule.classes.first; _class; _class = _class.next)
1211    {
1212       if(_class.isRemote == 3) //)
1213          break;
1214    }
1215
1216    if(_class)
1217    {
1218       File f;
1219       if(!dcomSymbols) dcomSymbols = TempFile { };
1220       f = dcomSymbols;
1221
1222       DeclareClass(null, FindClass("ecere::net::DCOMServerObject"), "__ecereClass___ecereNameSpace__ecere__net__DCOMServerObject");
1223
1224       // SERVER BINDINGS
1225       for(_class = privateModule.classes.first; _class; _class = _class.next)
1226       {
1227          if(_class.isRemote == 3) //2 && !strncmp(_class.fullName, "DCOMServer_", strlen("DCOMServer_")))
1228          {
1229             Method method;
1230             int id = 0;
1231             int vid;
1232
1233             f.Printf("class DCOM%s : ecere::net::DCOMServerObject\n", _class.fullName);
1234             // f.Printf("class DCOM%s\n", _class.fullName);
1235             f.Printf("{\n");
1236             /*
1237             f.Printf("   %s instance;\n", _class.fullName);
1238             f.Printf("   unsigned int id;\n");
1239             f.Printf("   SerialBuffer buffer { };\n");
1240             */
1241
1242             /*
1243             f.Printf("   DCOM%s()\n", _class.fullName);
1244             f.Printf("   {\n");
1245             f.Printf("      instance = eInstance_New(class(%s));\n", _class.fullName);
1246             f.Printf("   }\n");
1247             */
1248             // f.Printf("\n");
1249             f.Printf("   virtual void CallMethod(uint __ecereMethodID, SerialBuffer __ecereBuffer)\n");
1250             f.Printf("   {\n");
1251             f.Printf("      %s inst = (%s)instance;\n", _class.fullName, _class.fullName);
1252             f.Printf("      incref inst;\n");
1253             f.Printf("      switch(__ecereMethodID)\n");
1254             f.Printf("      {\n");
1255
1256             for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
1257             {
1258                Type param;
1259                method.dataType = ProcessTypeString(method.dataTypeString, false);
1260                if(method.dataType && method.dataType.name)
1261                {
1262                   f.Printf("         case %d:\n", id++);
1263                   f.Printf("         {\n");
1264
1265                   {
1266                      if(method.dataType.returnType.kind != voidType)
1267                      {
1268                         TypeName resultType;
1269                         OldList * specs = MkList();
1270                         Declarator decl;
1271                         char type[1024] = "";
1272                         char className[1024];
1273                         Symbol classSym;
1274
1275                         if(method.dataType.returnType.kind == classType)
1276                            classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1277                         else
1278                         {
1279                            PrintTypeNoConst(method.dataType.returnType, type, false, true);
1280                            classSym = FindClass(type);
1281                            type[0] = 0;
1282                         }
1283                         strcpy(className, "__ecereClass_");
1284                         FullClassNameCat(className, classSym.string, true);
1285                         DeclareClass(null, classSym, className);
1286
1287                         PrintType(method.dataType.returnType, type, true, true);
1288
1289                         decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1290                         resultType = MkTypeName(specs, decl);
1291
1292                         f.Printf("            ");
1293                         OutputTypeName(resultType, f, false);
1294                         f.Printf(";\n");
1295                      }
1296
1297                      for(param = method.dataType.params.first; param; param = param.next)
1298                      {
1299                         if(param.kind == classType && !strcmp(param._class.string, "String"))
1300                         {
1301                            // Hardcode 1024 chars max string for now
1302                            f.Printf("            char %s[1024];\n", param.name);
1303                            DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1304                            DeclareClass(null, FindClass("String"), "__ecereClass_String");
1305                         }
1306                         else
1307                         {
1308                            TypeName paramTypeName;
1309                            OldList * specs = MkList();
1310                            Declarator decl;
1311                            char type[1024] = "";
1312                            char className[1024];
1313                            Symbol classSym;
1314
1315                            if(param.kind == classType)
1316                               classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1317                            else
1318                            {
1319                               PrintTypeNoConst(param, type, false, true);
1320                               classSym = FindClass(type);
1321                               type[0] = 0;
1322                            }
1323
1324                            strcpy(className, "__ecereClass_");
1325                            FullClassNameCat(className, classSym.string, true);
1326                            DeclareClass(null, classSym, className);
1327
1328                            PrintType(param, type, true, true);
1329
1330                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier(param.name /*"__ecereResult"*/)));
1331                            paramTypeName = MkTypeName(specs, decl);
1332
1333                            f.Printf("            ");
1334                            OutputTypeName(paramTypeName, f, false);
1335
1336                            f.Printf(";\n");
1337                         }
1338                      }
1339                      f.Printf("\n");
1340
1341                      for(param = method.dataType.params.first; param; param = param.next)
1342                      {
1343                         f.Printf("            __ecereBuffer.Unserialize(");
1344                         if(param.kind == classType && !strcmp(param._class.string, "String"))
1345                         {
1346                            DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1347                            f.Printf("(StaticString)");
1348                         }
1349                         f.Puts(param.name);
1350                         f.Printf(");\n");
1351                      }
1352
1353                      f.Printf("            ");
1354                      if(method.dataType.returnType.kind != voidType)
1355                         f.Printf("__ecereResult = ");
1356
1357                      // f.Printf("this.instance.%s(", method.name);
1358                      f.Printf("((%s)instance).%s(", _class.fullName, method.name);
1359
1360                      for(param = method.dataType.params.first; param; param = param.next)
1361                      {
1362                         if(param.prev)
1363                            f.Printf(", ");
1364                         f.Printf("%s", param.name);
1365                      }
1366
1367                      f.Printf(");\n");
1368
1369                      for(param = method.dataType.params.first; param; param = param.next)
1370                      {
1371                         if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1372                         {
1373                            if(!strcmp(param._class.string, "String"))
1374                            {
1375                               DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1376                               f.Printf("            __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
1377                            }
1378                            else
1379                               f.Printf("            __ecereBuffer.Serialize(%s);\n", param.name);
1380                         }
1381                      }
1382                      if(method.dataType.returnType.kind != voidType)
1383                      {
1384                         f.Printf("            __ecereBuffer.Serialize(__ecereResult);\n");
1385                      }
1386
1387                      for(param = method.dataType.params.first; param; param = param.next)
1388                      {
1389                         if(param.kind == classType && strcmp(param._class.string, "String") && param._class.registered &&
1390                            (param._class.registered.type == normalClass || param._class.registered.type == noHeadClass))
1391                         {
1392                            f.Printf("            delete %s;\n", param.name);
1393                         }
1394                      }
1395                      if(method.dataType.returnType.kind == classType && strcmp(method.dataType.returnType._class.string, "String") && method.dataType.returnType._class.registered &&
1396                            (method.dataType.returnType._class.registered.type == normalClass || method.dataType.returnType._class.registered.type == noHeadClass))
1397                      {
1398                         f.Printf("            delete __ecereResult;\n");
1399                      }
1400                   }
1401
1402                   f.Printf("            break;\n");
1403                   f.Printf("         }\n");
1404                }
1405             }
1406             f.Printf("      }\n");
1407             f.Printf("      delete inst;\n");
1408             f.Printf("   }\n");
1409
1410             // *** VIRTUAL FUNCTIONS BINDINGS ***
1411             for(vid = _class.base.vTblSize; vid < _class.vTblSize; vid++)
1412             {
1413                Method method;
1414                Type param;
1415
1416                for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
1417                   if(method.type == virtualMethod && method._class == _class && method.vid == vid)
1418                      break;
1419                if(method)
1420                {
1421                   if(!mutexDeclared)
1422                   {
1423                      DeclareClass(null, FindClass("ecere::sys::Mutex"), "__ecereClass___ecereNameSpace__ecere__sys__Mutex");
1424                      DeclareMethod(null,
1425                         eClass_FindMethod(
1426                            eSystem_FindClass(privateModule, "ecere::sys::Mutex"), "Wait", privateModule),
1427                               "__ecereMethod___ecereNameSpace__ecere__sys__Mutex_Wait");
1428                      DeclareMethod(null,
1429                         eClass_FindMethod(
1430                            eSystem_FindClass(privateModule, "ecere::sys::Mutex"), "Release", privateModule),
1431                               "__ecereMethod___ecereNameSpace__ecere__sys__Mutex_Release");
1432                      mutexDeclared = true;
1433                   }
1434
1435                   f.Printf("\n");
1436                   if(!method.dataType)
1437                      method.dataType = ProcessTypeString(method.dataTypeString, false);
1438
1439                   if(method.dataType.name)
1440                   {
1441                      f.Printf("   virtual %s\n", method.dataTypeString);
1442                      f.Printf("   {\n");
1443
1444                      if(method.dataType)
1445                      {
1446                         f.Printf("      DCOM%s __ecereObject = (void *)_vTbl[-1];\n", _class.fullName);
1447                         if(method.dataType.returnType.kind != voidType)
1448                         {
1449                            TypeName resultType;
1450                            OldList * specs = MkList();
1451                            Declarator decl;
1452                            char type[1024] = "";
1453                            char className[1024];
1454                            Symbol classSym;
1455
1456                            if(method.dataType.returnType.kind == classType)
1457                               classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1458                            else
1459                            {
1460                               PrintTypeNoConst(method.dataType.returnType, type, false, true);
1461                               classSym = FindClass(type);
1462                               type[0] = 0;
1463                            }
1464
1465                            strcpy(className, "__ecereClass_");
1466                            FullClassNameCat(className, classSym.string, true);
1467                            DeclareClass(null, classSym, className);
1468
1469                            PrintType(method.dataType.returnType, type, true, true);
1470
1471                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1472                            resultType = MkTypeName(specs, decl);
1473
1474                            f.Printf("      ");
1475                            OutputTypeName(resultType, f, false);
1476                            if(method.dataType.returnType.kind == structType)
1477                               f.Printf(" = { 0 }");
1478                            else if(method.dataType.returnType.kind == classType && method.dataType.returnType._class.registered && method.dataType.returnType._class.registered.type == structClass)
1479                               f.Printf(" { }");
1480                            else
1481                               f.Printf(" = 0");
1482                            f.Printf(";\n\n");
1483                         }
1484
1485                         f.Printf("      incref __ecereObject;\n");
1486                         f.Printf("      __ecereMethod___ecereNameSpace__ecere__sys__Mutex_Wait(__ecereObject.mutex);\n");
1487
1488                         //f.Printf("      incref this;\n");
1489                         for(param = method.dataType.params.first; param; param = param.next)
1490                         {
1491                            char type[1024] = "";
1492                            char className[1024];
1493                            Symbol classSym;
1494
1495                            if(param.kind == classType)
1496                               classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1497                            else
1498                            {
1499                               PrintTypeNoConst(param, type, false, true);
1500                               classSym = FindClass(type);
1501                               type[0] = 0;
1502                            }
1503                            strcpy(className, "__ecereClass_");
1504                            FullClassNameCat(className, classSym.string, true);
1505                            DeclareClass(null, classSym, className);
1506
1507                            if(param.kind == classType && !strcmp(param._class.string, "String"))
1508                            {
1509                               DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1510                               f.Printf("      __ecereObject.argsBuffer.Serialize((StaticString)%s);\n", param.name);
1511                            }
1512                            else
1513                               f.Printf("      __ecereObject.argsBuffer.Serialize(%s);\n", param.name);
1514                         }
1515
1516                         DeclareMethod(null,
1517                            eClass_FindMethod(
1518                               eSystem_FindClass(privateModule, "ecere::net::DCOMServerObject"), "CallVirtualMethod", privateModule),
1519                            "__ecereMethod___ecereNameSpace__ecere__net__DCOMServerObject_CallVirtualMethod");
1520
1521                         // Check if this method needs to return anything (hasReturnValue)
1522                         {
1523                            bool hasReturnValue = method.dataType.returnType.kind != voidType;
1524                            if(!hasReturnValue)
1525                            {
1526                               for(param = method.dataType.params.first; param; param = param.next)
1527                               {
1528                                  if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1529                                  {
1530                                     hasReturnValue = true;
1531                                     break;
1532                                  }
1533                               }
1534                            }
1535                            f.Printf("      if(__ecereObject.CallVirtualMethod(%d, %s))\n", vid - _class.base.vTblSize,
1536                               hasReturnValue ? "true" : "false");
1537                         }
1538                         f.Printf("      {\n");
1539                         for(param = method.dataType.params.first; param; param = param.next)
1540                         {
1541                            if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1542                            {
1543                               if(!strcmp(param._class.string, "String"))
1544                               {
1545                                  DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1546                                  f.Printf("         __ecereObject.returnBuffer.Unserialize((StaticString)%s);\n", param.name);
1547                               }
1548                               else
1549                                  f.Printf("         __ecereObject.returnBuffer.Unserialize(%s);\n", param.name);
1550                            }
1551                         }
1552                         if(method.dataType.returnType.kind != voidType)
1553                         {
1554                            if(method.dataType.returnType.kind == classType && !strcmp(method.dataType.returnType._class.string, "String"))
1555                            {
1556                               DeclareClass(null, FindClass("StaticString"), "__ecereClass_StaticString");
1557                               f.Printf("         __ecereObject.returnBuffer.Unserialize((StaticString)__ecereResult);\n");
1558                            }
1559                            else
1560                               f.Printf("         __ecereObject.returnBuffer.Unserialize(__ecereResult);\n");
1561                         }
1562                         f.Printf("      }\n");
1563                         f.Printf("      else\n");
1564                         f.Printf("         ((%s)this).%s::%s(", _class.fullName, _class.fullName, method.name);
1565                         for(param = method.dataType.params.first; param; param = param.next)
1566                         {
1567                            f.Printf("%s", param.name);
1568                            if(param.next) f.Printf(", ");
1569                         }
1570                         f.Printf(");\n");
1571
1572                         f.Printf("      __ecereObject.returnBuffer.Free();\n");
1573                         f.Printf("      __ecereMethod___ecereNameSpace__ecere__sys__Mutex_Release(__ecereObject.mutex);\n");
1574                         //f.Printf("      delete this;\n");
1575                         f.Printf("      delete __ecereObject;\n");
1576                         if(method.dataType.returnType.kind != voidType)
1577                         {
1578                            f.Printf("      return __ecereResult;\n");
1579                         }
1580                      }
1581
1582                      f.Printf("   }\n");
1583                      /*if(vid < _class.vTblSize)
1584                         f.Printf("\n");*/
1585                   }
1586                }
1587             }
1588             f.Printf("}\n");
1589          }
1590       }
1591    }
1592 }
1593
1594 class SymbolgenApp : Application
1595 {
1596    void Main()
1597    {
1598       /*
1599       char ** argv = null;
1600       int argc = 0;
1601       */
1602       int c;
1603       bool valid = true;
1604       const char * output = null;
1605
1606       outputPot = false;
1607       disabledPooling = false;
1608       targetPlatform = __runtimePlatform;
1609       targetBits = GetHostBits();
1610
1611       /*
1612       for(c = 0; c<this.argc; c++)
1613       {
1614          char * arg = this.argv[c];
1615          int argLen = strlen(arg);
1616
1617          argv = renew argv char *[argc + 1];
1618          argv[argc] = new char[argLen+1];
1619          strcpy(argv[argc], arg);
1620
1621          while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
1622          {
1623             int len;
1624
1625             c++;
1626             arg = this.argv[c];
1627             len = strlen(arg);
1628             argv[argc] = renew argv[argc] char[argLen + len + 1];
1629
1630             argv[argc][argLen-1] = ' ';
1631             strcpy(argv[argc] + argLen, arg);
1632             argLen += len;
1633          }
1634          argc++;
1635       }
1636       */
1637
1638 #if 0 //def _DEBUG
1639       printf("\nArguments given:\n");
1640       for(c=1; c<argc; c++)
1641          printf(" %s", argv[c]);
1642       printf("\n\n");
1643       for(c=1; c<argc; c++)
1644          PrintLn("Arg", c, ": ", argv[c]);
1645       printf("\n");
1646       //getch();
1647 #endif
1648
1649       for(c = 1; c<argc; c++)
1650       {
1651          const char * arg = argv[c];
1652          if(arg[0] == '-')
1653          {
1654             if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64"))
1655             {
1656                targetBits = !strcmp(arg + 1, "m32") ? 32 : 64;
1657             }
1658             else if(!strcmp(arg + 1, "t32") || !strcmp(arg + 1, "t64"))
1659             {
1660                targetBits = !strcmp(arg + 1, "t32") ? 32 : 64;
1661             }
1662             else if(!strcmp(arg+1, "o"))
1663             {
1664                if(!output && c + 1 < argc)
1665                {
1666                   output = argv[c+1];
1667                   c++;
1668                }
1669                else
1670                   valid = false;
1671             }
1672             else if(!strcmp(arg, "-name"))
1673             {
1674                if(c + 1 < argc)
1675                {
1676                   strcpy(projectName, argv[c+1]);
1677                   c++;
1678                }
1679                else
1680                   valid = false;
1681             }
1682             else if(!strcmp(arg, "-t"))
1683             {
1684                if(++c < argc)
1685                   targetPlatform = argv[c];
1686                else
1687                   valid = false;
1688             }
1689             else if(!strcmp(arg, "-outputpot"))
1690                outputPot = true;
1691             else if(!strcmp(arg, "-disabled-pooling"))
1692                disabledPooling = true;
1693             else if(!strcmp(arg, "-console"))
1694                isConsole = true;
1695             else if(!strcmp(arg, "-dynamiclib"))
1696                isDynamicLibrary = true;
1697             else if(!strcmp(arg, "-staticlib"))
1698             {
1699                isDynamicLibrary = true;   // TOFIX: unmixup
1700                isStaticLibrary = true;
1701             }
1702             else if(!strcmp(arg, "-symbols"))
1703             {
1704                if(c + 1 < argc)
1705                {
1706                   SetSymbolsDir(argv[c+1]);
1707                   c++;
1708                }
1709                else
1710                   valid = false;
1711             }
1712          }
1713       }
1714       if(!output)
1715          valid = false;
1716
1717       if(!valid)
1718       {
1719          printf("%s", $"Syntax:\n   ecs [-t <target platform>] <input>[, <input>]* -o <output>\n");
1720       }
1721       else
1722       {
1723          int c;
1724          char ext[MAX_EXTENSION];
1725          char symbolModule[MAX_FILENAME];
1726          GetExtension(output, ext);
1727          GetLastDirectory(output, symbolModule);
1728
1729          SetDefines(&::_defines);
1730          SetImports(&_imports);
1731          SetGlobalData(&globalData);
1732          SetExcludedSymbols(&_excludedSymbols);
1733          SetGlobalContext(theGlobalContext);
1734          SetTopContext(theGlobalContext);
1735          SetCurrentContext(theGlobalContext);
1736          SetTargetPlatform(targetPlatform);
1737          SetTargetBits(targetBits);
1738          SetInSymbolGen(true);
1739
1740          privateModule = (Module)__ecere_COM_Initialize((bool)(true | (targetBits == sizeof(uintptr)*8 ? 0 : targetBits == 64 ? 2 : targetBits==32 ? 4 : 0) | 8), 1, null);
1741          SetPrivateModule(privateModule);
1742          mainModule = ModuleImport { };
1743          SetMainModule(mainModule);
1744          _imports.Add(mainModule);
1745
1746          //if(!strcmp(ext, "c"))
1747          {
1748             //const String symbolsDir = GetSymbolsDir();
1749             // Only generating .pot files when building from release.* directory for now
1750             //bool outputPot = symbolsDir && SearchString(symbolsDir, 0, "release.", false, false);
1751             Map<ContextStringPair, List<String> > intlStrings { };
1752             MapIterator<ContextStringPair, List<String>> it { map = intlStrings };
1753
1754             for(c = 1; c<argc; c++)
1755             {
1756                const char * file = argv[c];
1757                File f = null;
1758                char line[16384];
1759                int count = 0;
1760                char * tokens[512];
1761                if(file[0] == '-')
1762                {
1763                   if(!strcmp(file, "-c"))
1764                      c++;
1765                }
1766                else if(file[0] == '@')
1767                   f = FileOpen(&file[1], read);
1768                else
1769                {
1770                   count = 1;
1771                   tokens[0] = (char *)file;
1772                }
1773                while(count || f)
1774                {
1775                   int c;
1776                   if(f)
1777                   {
1778                      while(!count && f.GetLine(line, sizeof(line)))
1779                         count = Tokenize(line, sizeof(tokens)/sizeof(tokens[0]), tokens, forArgsPassing);
1780                      if(!count)
1781                         delete f;
1782                   }
1783                   for(c = 0; c < count; c++)
1784                   {
1785                      char ext[MAX_EXTENSION];
1786                      file = tokens[c];
1787                      GetExtension(file, ext);
1788                      if(!strcmp(ext, "imp"))
1789                         LoadImports(file);
1790                   }
1791                   count = 0;
1792                }
1793             }
1794
1795             // What is this supposed to do?
1796             for(c = 1; c<argc; c++)
1797             {
1798                const char * file = argv[c];
1799                if(file[0] == '-')
1800                {
1801                   if(!strcmp(file, "-c"))
1802                      c++;
1803                }
1804             }
1805
1806             for(c = 1; c<argc; c++)
1807             {
1808                const char * file = argv[c];
1809                File f = null;
1810                char line[16384];
1811                int count = 0;
1812                char * tokens[512];
1813                if(file[0] == '-')
1814                {
1815                   // Don't even know what it does here?
1816                   if(!strcmp(file, "-c"))
1817                      c++;
1818                }
1819                else if(file[0] == '@')
1820                   f = FileOpen(&file[1], read);
1821                else
1822                {
1823                   count = 1;
1824                   tokens[0] = (char *)file;
1825                }
1826
1827                while(count || f)
1828                {
1829                   int c;
1830                   if(f)
1831                   {
1832                      while(!count && f.GetLine(line, sizeof(line)))
1833                         count = Tokenize(line, sizeof(tokens)/sizeof(tokens[0]), tokens, forArgsPassing);
1834                      if(!count)
1835                         delete f;
1836                   }
1837                   for(c = 0; c < count; c++)
1838                   {
1839                      char ext[MAX_EXTENSION];
1840                      char moduleName[MAX_LOCATION];
1841
1842                      file = tokens[c];
1843
1844                      GetExtension(file, ext);
1845
1846                      GetLastDirectory(file, moduleName);
1847                      StripExtension(moduleName);
1848                      strcat(moduleName, ".ec");
1849
1850                      if(fstrcmp(moduleName, symbolModule) && (!strcmp(ext, "sym") || !strcmp(ext, "ec")))
1851                      {
1852                         ImportedModule importedModule;
1853                         ModuleInfo module { };
1854                         char fileName[MAX_FILENAME];
1855                         ::modules.Add(module);
1856
1857                         GetLastDirectory(file, fileName);
1858
1859                         module.name = CopyString(fileName);
1860
1861                         StripExtension(module.name);
1862
1863                         for(importedModule = ::_defines.first; importedModule; importedModule = importedModule.next)
1864                         {
1865                            if(importedModule.type == moduleDefinition && !strcmpi(importedModule.name, module.name) && !(importedModule.importType == remoteImport))
1866                               break;
1867                         }
1868
1869                         if(importedModule)
1870                            module.globalInstance = importedModule.globalInstance;
1871                         else
1872                         {
1873                            importedModule = ImportedModule
1874                            {
1875                               name = CopyString(module.name),
1876                               type = moduleDefinition,
1877                               importType = normalImport
1878                            };
1879                            ::_defines.AddName(importedModule);
1880
1881                            module.globalInstance = LoadSymbols(file, normalImport, false);
1882                            CheckDataRedefinitions();
1883                         }
1884
1885                         // I18n code
1886                         {
1887                            File f;
1888                            ChangeExtension(file, "bowl", fileName);
1889                            f = FileOpen(fileName, read);
1890                            if(f)
1891                            {
1892                               static char line[65536];
1893                               List<String> comments { };
1894                               String msgid = null, msgstr = null, msgctxt = null;
1895                               while(!f.Eof())
1896                               {
1897                                  if(f.GetLine(line, sizeof(line)))
1898                                  {
1899                                     int len;
1900                                     TrimLSpaces(line, line);
1901                                     if(line[0] == '#')
1902                                     {
1903                                        comments.Add(CopyString(line));
1904                                     }
1905                                     else if(strstr(line, "msgid \"") == line)
1906                                     {
1907                                        delete msgid;
1908                                        msgid = CopyString(line + 7);
1909                                        len = strlen(msgid);
1910                                        if(len) msgid[len-1] = 0;
1911                                     }
1912                                     else if(strstr(line, "msgctxt \"") == line)
1913                                     {
1914                                        delete msgctxt;
1915                                        msgctxt = CopyString(line + 9);
1916                                        len = strlen(msgctxt);
1917                                        if(len) msgctxt[len-1] = 0;
1918                                     }
1919                                     else if(strstr(line, "msgstr \"") == line)
1920                                     {
1921                                        delete msgstr;
1922                                        msgstr = CopyString(line + 8);
1923                                        len = strlen(msgstr);
1924                                        if(len) msgstr[len-1] = 0;
1925                                     }
1926
1927                                     if(msgid && msgstr)
1928                                     {
1929                                        ContextStringPair pair { msgid, msgctxt };
1930                                        i18n = true;
1931                                        if(!it.Index(pair, false))
1932                                        {
1933                                           msgid = null; msgctxt = null;
1934                                           intlStrings[pair] = comments;
1935                                           comments = { };
1936                                        }
1937                                        else
1938                                        {
1939                                           for(s : comments)
1940                                              it.data.Add(s);
1941                                           comments.RemoveAll();
1942                                        }
1943
1944                                        delete msgid;
1945                                        delete msgctxt;
1946                                        delete msgstr;
1947                                     }
1948                                  }
1949                               }
1950                               comments.Free();
1951                               delete comments;
1952                               delete f;
1953                            }
1954                         }
1955                      }
1956                   }
1957                   count = 0;
1958                }
1959             }
1960
1961             ComputeModuleClasses(privateModule);
1962
1963             if(!isDynamicLibrary)
1964             {
1965                // applicationClass = eSystem_FindClass(privateModule, "Application");
1966                /*
1967                thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, true);
1968                if(!thisAppClass)
1969                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, true);
1970                if(!thisAppClass)
1971                   thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, false);
1972                if(!thisAppClass)
1973                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, false);
1974                */
1975                thisAppClass = SearchAppClass_Module(privateModule);
1976             }
1977             WriteMain(output);
1978
1979             if(outputPot && intlStrings.count)
1980             {
1981                File potFile;
1982                char potFileName[MAX_LOCATION];
1983                //strcpy(potFileName, output);
1984                //StripExtension(potFileName);
1985                strcpy(potFileName, "locale");
1986                PathCat(potFileName, projectName);
1987                ChangeExtension(potFileName, "pot", potFileName);
1988                potFile = FileOpen(potFileName, write);
1989                if(potFile)
1990                {
1991                   // Write header:
1992                   potFile.Puts("msgid \"\"\n");
1993                   potFile.Puts("msgstr \"\"\n");
1994                   potFile.Puts("\"Project-Id-Version: \\n\"\n");
1995                   potFile.Puts("\"POT-Creation-Date: \\n\"\n");
1996                   potFile.Puts("\"PO-Revision-Date: \\n\"\n");
1997                   potFile.Puts("\"Last-Translator: \\n\"\n");
1998                   potFile.Puts("\"Language-Team: \\n\"\n");
1999                   potFile.Puts("\"MIME-Version: 1.0\\n\"\n");
2000                   potFile.Puts("\"Content-Type: text/plain; charset=iso-8859-1\\n\"\n");
2001                   potFile.Puts("\"Content-Transfer-Encoding: 8bit\\n\"\n");
2002                   potFile.Puts("\"X-Poedit-Basepath: ../\\n\"\n");
2003                   potFile.Puts("\n");
2004
2005                   for(i : intlStrings)
2006                   {
2007                      ContextStringPair pair = &i;
2008                      List<String> comments = i;
2009                      for(s : comments)
2010                      {
2011                         potFile.Printf(s);
2012                         potFile.Puts("\n");
2013                      }
2014
2015                      if(pair.context)
2016                      {
2017                         potFile.Puts("msgctxt \""); potFile.Puts(pair.context); potFile.Puts("\"\n");
2018                      }
2019                      potFile.Puts("msgid \""); potFile.Puts(pair.string); potFile.Puts("\"\n");
2020                      potFile.Puts("msgstr \""); potFile.Puts(pair.string); potFile.Puts("\"\n");
2021                      potFile.Puts("\n");
2022                   }
2023                   intlStrings.Free();
2024                   delete intlStrings;
2025                   delete potFile;
2026                }
2027             }
2028          }
2029
2030          FreeContext(theGlobalContext);
2031          FreeExcludedSymbols(_excludedSymbols);
2032
2033          ::_defines.Free(FreeModuleDefine);
2034          _imports.Free(FreeModuleImport);
2035
2036          //precompDefines.Free(FreeDefinition);
2037
2038          FreeTypeData(privateModule);
2039          FreeIncludeFiles();
2040          FreeGlobalData(globalData);
2041
2042          delete privateModule;
2043       }
2044
2045       SetSymbolsDir(null); // Free symbols dir
2046
2047       /*
2048       for(c = 0; c<argc; c++)
2049          delete argv[c];
2050       delete argv;
2051       */
2052
2053 #if 0 //defined(_DEBUG) && defined(__WIN32__)
2054       getch();
2055 #endif
2056    }
2057 }