23885752ddb9a1c76a0acf564581332a87eff8d0
[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)&((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(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(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             MangleClassName(className);
326
327             if(_class.itself)
328                f.Printf("Class __ecereClass_%s;\n", className);
329             else
330                nonInst = true;
331             //if(!_class.isRemote)
332             {
333                //if(strcmp(_class.name, "SerialBuffer"))
334                {
335                   for(method = _class.methods.first; method; method = method.next)
336                   {
337                      Method meth = eClass_FindMethod(regClass, method.name, privateModule);
338                      if(meth && !meth.dataType)
339                      {
340                         Context context = SetupTemplatesContext(regClass);
341                         meth.dataType = ProcessTypeString(meth.dataTypeString, false);
342                         FinishTemplatesContext(context);
343                      }
344
345                      if(method.isVirtual)
346                         f.Printf("int __ecereVMethodID_%s_%s;\n", className, method.name);
347                      else if(module.name && module.importType != staticImport && (!meth || !meth.dataType.dllExport))
348                      {
349                         /*char name[4096];
350
351                         Type type
352                         {
353                            kind = TypePointer,
354                            type = method.
355                         };
356                         type.refCount++;
357                         sprintf(name, "__ecereMethod_%s_%s", className, method.name);
358                         PrintType(type, name, true);
359                         f.Printf("%s;\n", name);
360                         delete type;
361                         */
362                         //f.Printf("void * __ecereMethod_%s_%s;\n", className, method.name);
363
364                         f.Printf("int (*__ecereMethod_%s_%s)();\n", className, method.name);
365                      }
366
367                      anyMethod = true;
368                   }
369                }
370
371                for(prop = _class.properties.first; prop; prop = prop.next)
372                {
373                   char propName[1024];
374                   propName[0] = 0;
375                   FullClassNameCat(propName, prop.name, true);
376                   // strcpy(propName, prop.name);
377                   MangleClassName(propName);
378
379                   if(module.name && module.importType != staticImport)
380                   {
381                      if(prop.hasSet)
382                         f.Printf("void * __ecereProp_%s_Set_%s;\n", className, propName);
383                      if(prop.hasGet)
384                         f.Printf("void * __ecereProp_%s_Get_%s;\n", className, propName);
385                   }
386                   f.Printf("Property __ecereProp_%s_%s;\n", className, propName);
387                   anyProp = true;
388                }
389             }
390          }
391          for(function = module.functions.first; function; function = function.next)
392          {
393             GlobalFunction func = eSystem_FindFunction(privateModule, function.name);
394             if(func && !func.dataType)
395                func.dataType = ProcessTypeString(func.dataTypeString, false);
396
397             if(module.name && module.importType != staticImport && (!func || !func.dataType || !func.dataType.dllExport))
398             {
399                char functionName[1024];
400                functionName[0] = 0;
401                FullClassNameCat(functionName, function.name, false);
402                f.Printf("void * __ecereFunction_%s;\n", functionName);
403                anyFunction = true;
404             }
405          }
406       }
407
408       for(defModule = ::modules.first; defModule; defModule = defModule.next)
409       {
410          char moduleName[1024];
411          strcpy(moduleName, defModule.name);
412          FixModuleName(moduleName);
413          f.Printf("void __ecereRegisterModule_%s(Module module);\n", moduleName);
414          f.Printf("void __ecereUnregisterModule_%s(Module module);\n", moduleName);
415          if(defModule.globalInstance)
416          {
417             f.Printf("void __ecereCreateModuleInstances_%s();\n", moduleName);
418             f.Printf("void __ecereDestroyModuleInstances_%s();\n", moduleName);
419          }
420       }
421
422       // DCOM Stuff
423       if(dcomSymbols)
424       {
425          f.Printf("\n");
426
427          // Insert DCOM bindings here
428          dcomSymbols.Seek(0, start);
429          while(!dcomSymbols.Eof())
430          {
431             char buffer[4096];
432             int read = dcomSymbols.Read(buffer, 1, sizeof(buffer));
433             if(!read) break;
434             f.Write(buffer, 1, read);
435          }
436          f.Printf("\n");
437       }
438
439       // Main Function
440
441       if(isStaticLibrary)
442       {
443          /*if(targetPlatform == win32)
444             f.Printf("\nbool __stdcall __ecereDll_Load_%s(Module module)\n{\n", projectName);
445          else*/
446             f.Printf("\nbool __ecereDll_Load_%s(Module module)\n{\n", projectName);
447       }
448       else if(isDynamicLibrary)
449       {
450          if(targetPlatform == win32)
451             f.Puts("\ndllexport bool __stdcall __ecereDll_Load(Module module)\n{\n");
452          else
453             f.Puts("\ndllexport bool __ecereDll_Load(Module module)\n{\n");
454       }
455       else if(targetPlatform == win32 && !isConsole)
456       {
457          f.Puts("\nint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, char * cmdLine, int show)\n{\n");
458       }
459       else
460          f.Puts("\nint main(int _argc, char * _argv[])\n{\n");
461
462       if(!isDynamicLibrary)
463       {
464          f.Puts("   int exitCode;\n");
465          f.Puts("   Module module;\n");
466       }
467
468       //if(nonInst || thisAppClass)    // We use it all the time to get "Application" for the exit code now...
469          f.Puts("   Class _class;\n");
470
471       if(anyMethod)
472          f.Puts("   Method method;\n");
473       if(anyProp)
474          f.Puts("   Property _property;\n");
475       if(anyFunction)
476          f.Puts("   GlobalFunction function;\n");
477
478       f.Puts("\n");
479
480       if(disabledPooling)
481       {
482          f.Puts("   eSystem_SetPoolingDisabled(true);\n");
483          f.Puts("\n");
484       }
485
486       if(isDynamicLibrary)
487       {
488          f.Puts("   if(!__currentModule)\n");
489          f.Puts("   {\n");
490          f.Puts("      __currentModule = module;\n");
491          if(!isStaticLibrary)
492             f.Puts("      __thisModule = module;\n");
493          f.Puts("   }\n\n");
494       }
495       else if(targetPlatform == win32 && !isConsole)
496          f.Puts("   __thisModule = __currentModule = module = __ecere_COM_Initialize(1, 0, null);\n\n");
497       else
498          f.Puts("   __thisModule = __currentModule = module = __ecere_COM_Initialize(1, _argc, (void *)_argv);\n\n");
499
500       // First load all modules
501       if(_imports.count)
502       {
503          for(module = _imports.first; module; module = module.next)
504          {
505             if(module.name)
506             {
507                //if(strcmp(module.name, "ecereCOM") && strcmp(module.name, "ecere") )
508                {
509                   if(module.importType == staticImport)
510                      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);
511                   else
512                      f.Printf("   eModule_Load(module, \"%s\", %s);\n", module.name, (module.importAccess == privateAccess) ? "privateAccess" : "publicAccess");
513                }
514             }
515          }
516          f.Printf("\n");
517       }
518
519       // Then define the classes
520       if(::modules.count)
521       {
522          for(defModule = ::modules.first; defModule; defModule = defModule.next)
523          {
524             char moduleName[1024];
525             strcpy(moduleName, defModule.name);
526             FixModuleName(moduleName);
527             f.Printf("   __ecereRegisterModule_%s(module);\n", moduleName);
528          }
529          f.Printf("\n");
530       }
531
532       // Register Remote Modules
533       if(dcomSymbols)
534       {
535          f.Printf("   __ecereRegisterModule_%s(module);\n\n", mainModuleName);
536          delete dcomSymbols;
537       }
538
539       if(isDynamicLibrary)
540       {
541          f.Puts("   if(__currentModule == module)\n");
542          f.Puts("   {\n");
543       }
544       // Then load the imports
545       for(module = _imports.first; module; module = module.next)
546       {
547          ClassImport _class;
548          FunctionImport function;
549          if(module.classes.count)
550          {
551             for(_class = module.classes.first; _class; _class = _class.next)
552             {
553                Class regClass = eSystem_FindClass(privateModule, _class.name);
554
555                //if(!_class.isRemote)
556                {
557                   MethodImport method;
558                   PropertyImport prop;
559                   char classID[1024];
560                   char className[1024] = "";
561                   FullClassNameCat(className, _class.name, true);
562                   MangleClassName(className);
563
564                   if(_class.itself)
565                      sprintf(classID, "__ecereClass_%s", className);
566                   else
567                      strcpy(classID, "_class");
568
569                   if(isDynamicLibrary && !isStaticLibrary)
570                      f.Printf("   %s = eSystem_FindClass(__currentModule, \"%s\");\n", classID, _class.name);
571                   else
572                      f.Printf("   %s = eSystem_FindClass(module, \"%s\");\n", classID, _class.name);
573
574                   for(method = _class.methods.first; method; method = method.next)
575                   {
576                      Method meth = eClass_FindMethod(regClass, method.name, privateModule);
577                      if(!meth || !meth.dataType.dllExport)
578                      {
579                         if(method.isVirtual || (module.name && module.importType != staticImport))
580                         {
581                            f.Printf("   method = eClass_FindMethod(%s, \"%s\", module);\n",
582                               classID, method.name);
583                            if(method.isVirtual)
584                               f.Printf("   if(method) __ecereVMethodID_%s_%s = method.vid;\n", className, method.name);
585                            else
586                               f.Printf("   if(method) __ecereMethod_%s_%s = method.function;\n", className, method.name);
587                         }
588                      }
589                   }
590
591                   for(prop = _class.properties.first; prop; prop = prop.next)
592                   {
593                      char propName[1024];
594                      propName[0] = 0;
595                      FullClassNameCat(propName, prop.name, true);
596                      // strcpy(propName, prop.name);
597                      MangleClassName(propName);
598
599                      f.Printf("   __ecereProp_%s_%s = _property = eClass_FindProperty(%s, \"%s\", module);\n",
600                         className, propName, classID, prop.name);
601
602                      if(module.name && module.importType != staticImport)
603                      {
604                         if(prop.hasSet)
605                            f.Printf("   __ecereProp_%s_Set_%s = _property.Set;\n", className, propName);
606                         if(prop.hasGet)
607                            f.Printf("   __ecereProp_%s_Get_%s = _property.Get;\n", className, propName);
608                      }
609                   }
610                   f.Printf("\n");
611                }
612             }
613          }
614          if(module.functions.count)
615          {
616             for(function = module.functions.first; function; function = function.next)
617             {
618                GlobalFunction func = eSystem_FindFunction(privateModule, function.name);
619                if(module.name && module.importType != staticImport && (!func || !func.dataType || !func.dataType.dllExport))
620                {
621                   char functionName[1024];
622                   functionName[0] = 0;
623                   FullClassNameCat(functionName, function.name, false);
624
625                   if(isDynamicLibrary && !isStaticLibrary)
626                      f.Printf("   function = eSystem_FindFunction(__currentModule, \"%s\");\n", function.name);
627                   else
628                      f.Printf("   function = eSystem_FindFunction(module, \"%s\");\n", function.name);
629
630                   f.Printf("   if(function) __ecereFunction_%s = function.function;\n", functionName);
631                   f.Printf("\n");
632                }
633             }
634             f.Printf("\n");
635          }
636       }
637
638       for(defModule = ::modules.first; defModule; defModule = defModule.next)
639          if(defModule.globalInstance)
640          {
641             if(!strcmp(defModule.name, "i18n"))
642                f.Printf("   __ecereCreateModuleInstances_i18n();\n");
643          }
644       if(i18n)
645          f.Printf("      LoadTranslatedStrings(module, \"%s\");\n", projectName);
646       if(isDynamicLibrary)
647       {
648          //f.Printf("   module._vTbl[10](module);\n");
649          f.Puts("   }\n");
650       }
651
652       if(!isDynamicLibrary && thisAppClass)
653       {
654          f.Printf("   _class = eSystem_FindClass(__currentModule, \"%s\");\n", thisAppClass.name);
655          f.Printf("   eInstance_Evolve((Instance *)&__currentModule, _class);\n");
656          f.Printf("   __thisModule = __currentModule;\n");
657       }
658
659       if(isDynamicLibrary)
660       {
661          f.Puts("   if(__currentModule == module)\n");
662          f.Puts("   {\n");
663       }
664
665       // Then check if there's any global instances to create
666       if(::modules.count)
667       {
668          for(defModule = ::modules.first; defModule; defModule = defModule.next)
669             if(defModule.globalInstance)
670             {
671                char moduleName[1024];
672                if(!strcmp(defModule.name, "i18n")) continue;
673                strcpy(moduleName, defModule.name);
674                FixModuleName(moduleName);
675                f.Printf("   __ecereCreateModuleInstances_%s();\n", moduleName);
676             }
677
678          f.Printf("\n");
679       }
680
681       if(isDynamicLibrary)
682       {
683          f.Puts("   }\n");
684       }
685       if(!isDynamicLibrary && thisAppClass)
686       {
687          f.Printf("   ((void(*)(void *))(void *)__currentModule._vTbl[12])(__currentModule);\n");
688       }
689
690       if(isDynamicLibrary)
691       {
692          f.Puts("   return true;\n");
693          f.Puts("}\n");
694          if(isStaticLibrary)
695          {
696             /*if(targetPlatform == win32)
697                f.Printf("\nbool __stdcall __ecereDll_Unload_%s(Module module)\n{\n", projectName);
698             else*/
699                f.Printf("\nbool __ecereDll_Unload_%s(Module module)\n{\n", projectName);
700          }
701          else
702          {
703             if(targetPlatform == win32)
704                f.Puts("\ndllexport bool __stdcall __ecereDll_Unload(Module module)\n{\n");
705             else
706                f.Puts("\ndllexport bool __ecereDll_Unload(Module module)\n{\n");
707          }
708       }
709
710       if(isDynamicLibrary)
711       {
712          f.Puts("   if(__currentModule == module)\n");
713          f.Puts("   {\n");
714       }
715       // Then check if there's any global instances to destroy
716       {
717          bool destroyI18n = false;
718          if(::modules.count)
719          {
720             for(defModule = ::modules.first; defModule; defModule = defModule.next)
721                if(defModule.globalInstance)
722                {
723                   char moduleName[1024];
724                   if(!strcmp(defModule.name, "i18n")) { destroyI18n = true; continue; }
725                   strcpy(moduleName, defModule.name);
726                   FixModuleName(moduleName);
727                   f.Printf("   __ecereDestroyModuleInstances_%s();\n", moduleName);
728                }
729
730             f.Printf("\n");
731          }
732          if(i18n)
733             f.Printf("   UnloadTranslatedStrings(__currentModule);\n");
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(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                            MangleClassName(className);
900                            DeclareClass(classSym, className);
901
902                            PrintType(method.dataType.returnType, type, true, true);
903
904                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
905                            resultType = MkTypeName(specs, decl);
906
907                            f.Printf("            ");
908                            OutputTypeName(resultType, f, false);
909                            f.Printf(";\n");
910                         }
911
912                         for(param = method.dataType.params.first; param; param = param.next)
913                         {
914                            if(param.kind == classType && !strcmp(param._class.string, "String"))
915                            {
916                               // Hardcode 1024 chars max string for now
917                               f.Printf("            char %s[1024];\n", param.name);
918                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
919                               DeclareClass(FindClass("String"), "__ecereClass_String");
920                            }
921                            else
922                            {
923                               TypeName paramTypeName;
924                               OldList * specs = MkList();
925                               Declarator decl;
926                               char type[1024] = "";
927                               char className[1024];
928                               Symbol classSym;
929
930                               if(param.kind == classType)
931                                  classSym = param._class; // VERIFY THIS FindClass(param._class.string);
932                               else
933                               {
934                                  PrintTypeNoConst(param, type, false, true);
935                                  classSym = FindClass(type);
936                                  type[0] = 0;
937                               }
938
939                               strcpy(className, "__ecereClass_");
940                               FullClassNameCat(className, classSym.string, true);
941                               MangleClassName(className);
942                               DeclareClass(classSym, className);
943
944                               PrintType(param, type, true, true);
945
946                               decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier(param.name /*"__ecereResult"*/)));
947                               paramTypeName = MkTypeName(specs, decl);
948
949                               f.Printf("            ");
950                               OutputTypeName(paramTypeName, f, false);
951
952                               f.Printf(";\n");
953                            }
954                         }
955                         f.Printf("\n");
956
957                         for(param = method.dataType.params.first; param; param = param.next)
958                         {
959                            f.Printf("            __ecereBuffer.Unserialize(");
960                            if(param.kind == classType && !strcmp(param._class.string, "String"))
961                            {
962                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
963                               f.Printf("(StaticString)");
964                            }
965                            f.Puts(param.name);
966                            f.Printf(");\n");
967                         }
968
969                         f.Printf("            ");
970                         if(method.dataType.returnType.kind != voidType)
971                            f.Printf("__ecereResult = ");
972
973                         // f.Printf("this.instance.%s(", method.name);
974                         f.Printf("%s(", method.name);
975
976                         for(param = method.dataType.params.first; param; param = param.next)
977                         {
978                            if(param.prev)
979                               f.Printf(", ");
980                            f.Printf("%s", param.name);
981                         }
982
983                         f.Printf(");\n");
984
985                         for(param = method.dataType.params.first; param; param = param.next)
986                         {
987                            if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
988                            {
989                               if(!strcmp(param._class.string, "String"))
990                               {
991                                  DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
992                                  f.Printf("            __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
993                               }
994                               else
995                                  f.Printf("            __ecereBuffer.Serialize(%s);\n", param.name);
996                            }
997                         }
998                         if(method.dataType.returnType.kind != voidType)
999                         {
1000                            f.Printf("            __ecereBuffer.Serialize(__ecereResult);\n");
1001                         }
1002
1003                         for(param = method.dataType.params.first; param; param = param.next)
1004                         {
1005                            if(param.kind == classType && strcmp(param._class.string, "String") && param._class.registered &&
1006                               (param._class.registered.type == normalClass || param._class.registered.type == noHeadClass))
1007                            {
1008                               f.Printf("            delete %s;\n", param.name);
1009                            }
1010                         }
1011                         if(method.dataType.returnType.kind == classType && strcmp(method.dataType.returnType._class.string, "String") && method.dataType.returnType._class.registered &&
1012                               (method.dataType.returnType._class.registered.type == normalClass || method.dataType.returnType._class.registered.type == noHeadClass))
1013                         {
1014                            f.Printf("            delete __ecereResult;\n");
1015                         }
1016                      }
1017
1018                      f.Printf("            break;\n");
1019                      f.Printf("         }\n");
1020                   }
1021                }
1022             }
1023             f.Printf("      }\n");
1024             f.Printf("   }\n");
1025             f.Printf("\n");
1026          }
1027
1028          doVirtual = true;
1029          id = 0;
1030          vid = _class.base.vTblSize;
1031
1032          next = (Method)_class.methods.first;
1033          while(next && ((next.type == virtualMethod) != doVirtual || (doVirtual && next.vid != vid)))
1034          {
1035             id++;
1036             next = (Method)((BTNode)next).next;
1037             if(!next && doVirtual)
1038             {
1039                if(vid == _class.vTblSize)
1040                   doVirtual = false;
1041                else
1042                   vid++;
1043                id = 0;
1044                next = (Method)_class.methods.first;
1045             }
1046          }
1047          for(method = next; method; method = next)
1048          {
1049             Type param;
1050
1051             if(!method.dataType)
1052                method.dataType = ProcessTypeString(method.dataTypeString, false);
1053
1054             if(method.dataType.name)
1055             {
1056                f.Printf("   ");
1057                if(doVirtual)
1058                {
1059                   char name[1024];
1060                   strcpy(name, "__ecereVMethodID_");
1061                   FullClassNameCat(name, method._class.fullName, true);
1062                   strcat(name, "_");
1063                   strcat(name, method.name);
1064                   DeclareMethod(method, name);
1065
1066                   f.Printf("virtual ");
1067                }
1068                f.Printf("%s\n", method.dataTypeString);
1069                f.Printf("   {\n");
1070
1071                if(method.dataType)
1072                {
1073                   if(method.dataType.returnType.kind != voidType)
1074                   {
1075                      TypeName resultType;
1076                      OldList * specs = MkList();
1077                      Declarator decl;
1078                      char type[1024] = "";
1079                      char className[1024];
1080                      Symbol classSym;
1081
1082                      if(method.dataType.returnType.kind == classType)
1083                         classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1084                      else
1085                      {
1086                         PrintTypeNoConst(method.dataType.returnType, type, false, true);
1087                         classSym = FindClass(type);
1088                         type[0] = 0;
1089                      }
1090
1091                      strcpy(className, "__ecereClass_");
1092                      FullClassNameCat(className, classSym.string, true);
1093                      MangleClassName(className);
1094                      DeclareClass(classSym, className);
1095
1096                      PrintType(method.dataType.returnType, type, true, true);
1097
1098                      decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1099                      resultType = MkTypeName(specs, decl);
1100
1101                      f.Printf("      ");
1102                      OutputTypeName(resultType, f, false);
1103                      if(method.dataType.returnType.kind == structType)
1104                         f.Printf(" = { 0 }");
1105                      else if(method.dataType.returnType.kind == classType && method.dataType.returnType._class.registered && method.dataType.returnType._class.registered.type == structClass)
1106                         f.Printf(" { }");
1107                      else
1108                         f.Printf(" = 0");
1109                      f.Printf(";\n\n");
1110                   }
1111                   f.Printf("      incref this;\n");
1112                   for(param = method.dataType.params.first; param; param = param.next)
1113                   {
1114                      char type[1024] = "";
1115                      char className[1024];
1116                      Symbol classSym;
1117
1118                      if(param.kind == classType)
1119                         classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1120                      else
1121                      {
1122                         PrintTypeNoConst(param, type, false, true);
1123                         classSym = FindClass(type);
1124                         type[0] = 0;
1125                      }
1126                      strcpy(className, "__ecereClass_");
1127                      FullClassNameCat(className, classSym.string, true);
1128
1129                      MangleClassName(className);
1130                      DeclareClass(classSym, className);
1131
1132                      if(param.kind == classType && !strcmp(param._class.string, "String"))
1133                      {
1134                         DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1135                         f.Printf("      __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
1136                      }
1137                      else
1138                         f.Printf("      __ecereBuffer.Serialize(%s);\n", param.name);
1139                   }
1140                   DeclareMethod(
1141                      eClass_FindMethod(
1142                         eSystem_FindClass(privateModule, "ecere::net::DCOMClientObject"), "CallMethod", privateModule),
1143                      "__ecereMethod___ecereNameSpace__ecere__net__DCOMClientObject_CallMethod");
1144
1145                   f.Printf("      if(DCOMClientObject::CallMethod(%d))\n", id++);
1146                   f.Printf("      {\n");
1147                   for(param = method.dataType.params.first; param; param = param.next)
1148                   {
1149                      if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1150                      {
1151                         if(!strcmp(param._class.string, "String"))
1152                         {
1153                            DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1154                            f.Printf("         __ecereBuffer.Unserialize((StaticString)%s);\n", param.name);
1155                         }
1156                         else
1157                            f.Printf("         __ecereBuffer.Unserialize(%s);\n", param.name);
1158                      }
1159                   }
1160                   if(method.dataType.returnType.kind != voidType)
1161                   {
1162                      if(method.dataType.returnType.kind == classType && !strcmp(method.dataType.returnType._class.string, "String"))
1163                      {
1164                         DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1165                         f.Printf("         __ecereBuffer.Unserialize((StaticString)__ecereResult);\n");
1166                      }
1167                      else
1168                         f.Printf("         __ecereBuffer.Unserialize(__ecereResult);\n");
1169                   }
1170                   f.Printf("      }\n");
1171                   f.Printf("      __ecereBuffer.Free();\n");
1172                   f.Printf("      delete this;\n");
1173                   if(method.dataType.returnType.kind != voidType)
1174                   {
1175                      f.Printf("      return __ecereResult;\n");
1176                   }
1177                }
1178
1179                f.Printf("   }\n");
1180             }
1181             next = (Method)((BTNode)method).next;
1182             while(next && ((next.type == virtualMethod) != doVirtual || (doVirtual && next.vid != vid)))
1183             {
1184                id++;
1185                next = (Method)((BTNode)next).next;
1186                if(!next && doVirtual)
1187                {
1188                   if(vid == _class.vTblSize)
1189                      doVirtual = false;
1190                   else
1191                      vid++;
1192                   id = 0;
1193                   next = (Method)_class.methods.first;
1194                }
1195             }
1196
1197             if(next)
1198                f.Printf("\n");
1199          }
1200
1201          f.Printf("}\n");
1202          if(deriv.next)
1203             f.Printf("\n");
1204       }
1205    }
1206 }
1207
1208 static void BindDCOMServer()
1209 {
1210    bool mutexDeclared = false;
1211    Class _class;
1212    for(_class = privateModule.classes.first; _class; _class = _class.next)
1213    {
1214       if(_class.isRemote == 3) //)
1215          break;
1216    }
1217
1218    if(_class)
1219    {
1220       File f;
1221       if(!dcomSymbols) dcomSymbols = TempFile { };
1222       f = dcomSymbols;
1223
1224       DeclareClass(FindClass("ecere::net::DCOMServerObject"), "__ecereClass___ecereNameSpace__ecere__net__DCOMServerObject");
1225
1226       // SERVER BINDINGS
1227       for(_class = privateModule.classes.first; _class; _class = _class.next)
1228       {
1229          if(_class.isRemote == 3) //2 && !strncmp(_class.fullName, "DCOMServer_", strlen("DCOMServer_")))
1230          {
1231             Method method;
1232             int id = 0;
1233             int vid;
1234
1235             f.Printf("class DCOM%s : ecere::net::DCOMServerObject\n", _class.fullName);
1236             // f.Printf("class DCOM%s\n", _class.fullName);
1237             f.Printf("{\n");
1238             /*
1239             f.Printf("   %s instance;\n", _class.fullName);
1240             f.Printf("   unsigned int id;\n");
1241             f.Printf("   SerialBuffer buffer { };\n");
1242             */
1243
1244             /*
1245             f.Printf("   DCOM%s()\n", _class.fullName);
1246             f.Printf("   {\n");
1247             f.Printf("      instance = eInstance_New(class(%s));\n", _class.fullName);
1248             f.Printf("   }\n");
1249             */
1250             // f.Printf("\n");
1251             f.Printf("   virtual void CallMethod(uint __ecereMethodID, SerialBuffer __ecereBuffer)\n");
1252             f.Printf("   {\n");
1253             f.Printf("      %s inst = (%s)instance;\n", _class.fullName, _class.fullName);
1254             f.Printf("      incref inst;\n");
1255             f.Printf("      switch(__ecereMethodID)\n");
1256             f.Printf("      {\n");
1257
1258             for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
1259             {
1260                Type param;
1261                method.dataType = ProcessTypeString(method.dataTypeString, false);
1262                if(method.dataType && method.dataType.name)
1263                {
1264                   f.Printf("         case %d:\n", id++);
1265                   f.Printf("         {\n");
1266
1267                   {
1268                      if(method.dataType.returnType.kind != voidType)
1269                      {
1270                         TypeName resultType;
1271                         OldList * specs = MkList();
1272                         Declarator decl;
1273                         char type[1024] = "";
1274                         char className[1024];
1275                         Symbol classSym;
1276
1277                         if(method.dataType.returnType.kind == classType)
1278                            classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1279                         else
1280                         {
1281                            PrintTypeNoConst(method.dataType.returnType, type, false, true);
1282                            classSym = FindClass(type);
1283                            type[0] = 0;
1284                         }
1285                         strcpy(className, "__ecereClass_");
1286                         FullClassNameCat(className, classSym.string, true);
1287                         MangleClassName(className);
1288                         DeclareClass(classSym, className);
1289
1290                         PrintType(method.dataType.returnType, type, true, true);
1291
1292                         decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1293                         resultType = MkTypeName(specs, decl);
1294
1295                         f.Printf("            ");
1296                         OutputTypeName(resultType, f, false);
1297                         f.Printf(";\n");
1298                      }
1299
1300                      for(param = method.dataType.params.first; param; param = param.next)
1301                      {
1302                         if(param.kind == classType && !strcmp(param._class.string, "String"))
1303                         {
1304                            // Hardcode 1024 chars max string for now
1305                            f.Printf("            char %s[1024];\n", param.name);
1306                            DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1307                            DeclareClass(FindClass("String"), "__ecereClass_String");
1308                         }
1309                         else
1310                         {
1311                            TypeName paramTypeName;
1312                            OldList * specs = MkList();
1313                            Declarator decl;
1314                            char type[1024] = "";
1315                            char className[1024];
1316                            Symbol classSym;
1317
1318                            if(param.kind == classType)
1319                               classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1320                            else
1321                            {
1322                               PrintTypeNoConst(param, type, false, true);
1323                               classSym = FindClass(type);
1324                               type[0] = 0;
1325                            }
1326
1327                            strcpy(className, "__ecereClass_");
1328                            FullClassNameCat(className, classSym.string, true);
1329                            MangleClassName(className);
1330                            DeclareClass(classSym, className);
1331
1332                            PrintType(param, type, true, true);
1333
1334                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier(param.name /*"__ecereResult"*/)));
1335                            paramTypeName = MkTypeName(specs, decl);
1336
1337                            f.Printf("            ");
1338                            OutputTypeName(paramTypeName, f, false);
1339
1340                            f.Printf(";\n");
1341                         }
1342                      }
1343                      f.Printf("\n");
1344
1345                      for(param = method.dataType.params.first; param; param = param.next)
1346                      {
1347                         f.Printf("            __ecereBuffer.Unserialize(");
1348                         if(param.kind == classType && !strcmp(param._class.string, "String"))
1349                         {
1350                            DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1351                            f.Printf("(StaticString)");
1352                         }
1353                         f.Puts(param.name);
1354                         f.Printf(");\n");
1355                      }
1356
1357                      f.Printf("            ");
1358                      if(method.dataType.returnType.kind != voidType)
1359                         f.Printf("__ecereResult = ");
1360
1361                      // f.Printf("this.instance.%s(", method.name);
1362                      f.Printf("((%s)instance).%s(", _class.fullName, method.name);
1363
1364                      for(param = method.dataType.params.first; param; param = param.next)
1365                      {
1366                         if(param.prev)
1367                            f.Printf(", ");
1368                         f.Printf("%s", param.name);
1369                      }
1370
1371                      f.Printf(");\n");
1372
1373                      for(param = method.dataType.params.first; param; param = param.next)
1374                      {
1375                         if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1376                         {
1377                            if(!strcmp(param._class.string, "String"))
1378                            {
1379                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1380                               f.Printf("            __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
1381                            }
1382                            else
1383                               f.Printf("            __ecereBuffer.Serialize(%s);\n", param.name);
1384                         }
1385                      }
1386                      if(method.dataType.returnType.kind != voidType)
1387                      {
1388                         f.Printf("            __ecereBuffer.Serialize(__ecereResult);\n");
1389                      }
1390
1391                      for(param = method.dataType.params.first; param; param = param.next)
1392                      {
1393                         if(param.kind == classType && strcmp(param._class.string, "String") && param._class.registered &&
1394                            (param._class.registered.type == normalClass || param._class.registered.type == noHeadClass))
1395                         {
1396                            f.Printf("            delete %s;\n", param.name);
1397                         }
1398                      }
1399                      if(method.dataType.returnType.kind == classType && strcmp(method.dataType.returnType._class.string, "String") && method.dataType.returnType._class.registered &&
1400                            (method.dataType.returnType._class.registered.type == normalClass || method.dataType.returnType._class.registered.type == noHeadClass))
1401                      {
1402                         f.Printf("            delete __ecereResult;\n");
1403                      }
1404                   }
1405
1406                   f.Printf("            break;\n");
1407                   f.Printf("         }\n");
1408                }
1409             }
1410             f.Printf("      }\n");
1411             f.Printf("      delete inst;\n");
1412             f.Printf("   }\n");
1413
1414             // *** VIRTUAL FUNCTIONS BINDINGS ***
1415             for(vid = _class.base.vTblSize; vid < _class.vTblSize; vid++)
1416             {
1417                Method method;
1418                Type param;
1419
1420                for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
1421                   if(method.type == virtualMethod && method._class == _class && method.vid == vid)
1422                      break;
1423                if(method)
1424                {
1425                   if(!mutexDeclared)
1426                   {
1427                      DeclareClass(FindClass("ecere::sys::Mutex"), "__ecereClass___ecereNameSpace__ecere__sys__Mutex");
1428                      DeclareMethod(
1429                         eClass_FindMethod(
1430                            eSystem_FindClass(privateModule, "ecere::sys::Mutex"), "Wait", privateModule),
1431                               "__ecereMethod___ecereNameSpace__ecere__sys__Mutex_Wait");
1432                      DeclareMethod(
1433                         eClass_FindMethod(
1434                            eSystem_FindClass(privateModule, "ecere::sys::Mutex"), "Release", privateModule),
1435                               "__ecereMethod___ecereNameSpace__ecere__sys__Mutex_Release");
1436                      mutexDeclared = true;
1437                   }
1438
1439                   f.Printf("\n");
1440                   if(!method.dataType)
1441                      method.dataType = ProcessTypeString(method.dataTypeString, false);
1442
1443                   if(method.dataType.name)
1444                   {
1445                      f.Printf("   virtual %s\n", method.dataTypeString);
1446                      f.Printf("   {\n");
1447
1448                      if(method.dataType)
1449                      {
1450                         f.Printf("      DCOM%s __ecereObject = (void *)_vTbl[-1];\n", _class.fullName);
1451                         if(method.dataType.returnType.kind != voidType)
1452                         {
1453                            TypeName resultType;
1454                            OldList * specs = MkList();
1455                            Declarator decl;
1456                            char type[1024] = "";
1457                            char className[1024];
1458                            Symbol classSym;
1459
1460                            if(method.dataType.returnType.kind == classType)
1461                               classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1462                            else
1463                            {
1464                               PrintTypeNoConst(method.dataType.returnType, type, false, true);
1465                               classSym = FindClass(type);
1466                               type[0] = 0;
1467                            }
1468
1469                            strcpy(className, "__ecereClass_");
1470                            FullClassNameCat(className, classSym.string, true);
1471                            MangleClassName(className);
1472                            DeclareClass(classSym, className);
1473
1474                            PrintType(method.dataType.returnType, type, true, true);
1475
1476                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1477                            resultType = MkTypeName(specs, decl);
1478
1479                            f.Printf("      ");
1480                            OutputTypeName(resultType, f, false);
1481                            if(method.dataType.returnType.kind == structType)
1482                               f.Printf(" = { 0 }");
1483                            else if(method.dataType.returnType.kind == classType && method.dataType.returnType._class.registered && method.dataType.returnType._class.registered.type == structClass)
1484                               f.Printf(" { }");
1485                            else
1486                               f.Printf(" = 0");
1487                            f.Printf(";\n\n");
1488                         }
1489
1490                         f.Printf("      incref __ecereObject;\n");
1491                         f.Printf("      __ecereMethod___ecereNameSpace__ecere__sys__Mutex_Wait(__ecereObject.mutex);\n");
1492
1493                         //f.Printf("      incref this;\n");
1494                         for(param = method.dataType.params.first; param; param = param.next)
1495                         {
1496                            char type[1024] = "";
1497                            char className[1024];
1498                            Symbol classSym;
1499
1500                            if(param.kind == classType)
1501                               classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1502                            else
1503                            {
1504                               PrintTypeNoConst(param, type, false, true);
1505                               classSym = FindClass(type);
1506                               type[0] = 0;
1507                            }
1508                            strcpy(className, "__ecereClass_");
1509                            FullClassNameCat(className, classSym.string, true);
1510                            MangleClassName(className);
1511                            DeclareClass(classSym, className);
1512
1513                            if(param.kind == classType && !strcmp(param._class.string, "String"))
1514                            {
1515                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1516                               f.Printf("      __ecereObject.argsBuffer.Serialize((StaticString)%s);\n", param.name);
1517                            }
1518                            else
1519                               f.Printf("      __ecereObject.argsBuffer.Serialize(%s);\n", param.name);
1520                         }
1521
1522                         DeclareMethod(
1523                            eClass_FindMethod(
1524                               eSystem_FindClass(privateModule, "ecere::net::DCOMServerObject"), "CallVirtualMethod", privateModule),
1525                            "__ecereMethod___ecereNameSpace__ecere__net__DCOMServerObject_CallVirtualMethod");
1526
1527                         // Check if this method needs to return anything (hasReturnValue)
1528                         {
1529                            bool hasReturnValue = method.dataType.returnType.kind != voidType;
1530                            if(!hasReturnValue)
1531                            {
1532                               for(param = method.dataType.params.first; param; param = param.next)
1533                               {
1534                                  if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1535                                  {
1536                                     hasReturnValue = true;
1537                                     break;
1538                                  }
1539                               }
1540                            }
1541                            f.Printf("      if(__ecereObject.CallVirtualMethod(%d, %s))\n", vid - _class.base.vTblSize,
1542                               hasReturnValue ? "true" : "false");
1543                         }
1544                         f.Printf("      {\n");
1545                         for(param = method.dataType.params.first; param; param = param.next)
1546                         {
1547                            if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1548                            {
1549                               if(!strcmp(param._class.string, "String"))
1550                               {
1551                                  DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1552                                  f.Printf("         __ecereObject.returnBuffer.Unserialize((StaticString)%s);\n", param.name);
1553                               }
1554                               else
1555                                  f.Printf("         __ecereObject.returnBuffer.Unserialize(%s);\n", param.name);
1556                            }
1557                         }
1558                         if(method.dataType.returnType.kind != voidType)
1559                         {
1560                            if(method.dataType.returnType.kind == classType && !strcmp(method.dataType.returnType._class.string, "String"))
1561                            {
1562                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1563                               f.Printf("         __ecereObject.returnBuffer.Unserialize((StaticString)__ecereResult);\n");
1564                            }
1565                            else
1566                               f.Printf("         __ecereObject.returnBuffer.Unserialize(__ecereResult);\n");
1567                         }
1568                         f.Printf("      }\n");
1569                         f.Printf("      else\n");
1570                         f.Printf("         ((%s)this).%s::%s(", _class.fullName, _class.fullName, method.name);
1571                         for(param = method.dataType.params.first; param; param = param.next)
1572                         {
1573                            f.Printf("%s", param.name);
1574                            if(param.next) f.Printf(", ");
1575                         }
1576                         f.Printf(");\n");
1577
1578                         f.Printf("      __ecereObject.returnBuffer.Free();\n");
1579                         f.Printf("      __ecereMethod___ecereNameSpace__ecere__sys__Mutex_Release(__ecereObject.mutex);\n");
1580                         //f.Printf("      delete this;\n");
1581                         f.Printf("      delete __ecereObject;\n");
1582                         if(method.dataType.returnType.kind != voidType)
1583                         {
1584                            f.Printf("      return __ecereResult;\n");
1585                         }
1586                      }
1587
1588                      f.Printf("   }\n");
1589                      /*if(vid < _class.vTblSize)
1590                         f.Printf("\n");*/
1591                   }
1592                }
1593             }
1594             f.Printf("}\n");
1595          }
1596       }
1597    }
1598 }
1599
1600 class SymbolgenApp : Application
1601 {
1602    void Main()
1603    {
1604       /*
1605       char ** argv = null;
1606       int argc = 0;
1607       */
1608       int c;
1609       bool valid = true;
1610       char * output = null;
1611
1612       outputPot = false;
1613       disabledPooling = false;
1614       targetPlatform = GetRuntimePlatform();
1615       targetBits = GetHostBits();
1616
1617       /*
1618       for(c = 0; c<this.argc; c++)
1619       {
1620          char * arg = this.argv[c];
1621          int argLen = strlen(arg);
1622
1623          argv = renew argv char *[argc + 1];
1624          argv[argc] = new char[argLen+1];
1625          strcpy(argv[argc], arg);
1626
1627          while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
1628          {
1629             int len;
1630
1631             c++;
1632             arg = this.argv[c];
1633             len = strlen(arg);
1634             argv[argc] = renew argv[argc] char[argLen + len + 1];
1635
1636             argv[argc][argLen-1] = ' ';
1637             strcpy(argv[argc] + argLen, arg);
1638             argLen += len;
1639          }
1640          argc++;
1641       }
1642       */
1643
1644 #ifdef _DEBUG
1645       printf("\nArguments given:\n");
1646       for(c=1; c<argc; c++)
1647          printf(" %s", argv[c]);
1648       printf("\n\n");
1649       for(c=1; c<argc; c++)
1650          PrintLn("Arg", c, ": ", argv[c]);
1651       printf("\n");
1652       //getch();
1653 #endif
1654
1655       for(c = 1; c<argc; c++)
1656       {
1657          char * arg = argv[c];
1658          if(arg[0] == '-')
1659          {
1660             if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64"))
1661             {
1662                targetBits = !strcmp(arg + 1, "m32") ? 32 : 64;
1663             }
1664             else if(!strcmp(arg + 1, "t32") || !strcmp(arg + 1, "t64"))
1665             {
1666                targetBits = !strcmp(arg + 1, "t32") ? 32 : 64;
1667             }
1668             else if(!strcmp(arg+1, "o"))
1669             {
1670                if(!output && c + 1 < argc)
1671                {
1672                   output = argv[c+1];
1673                   c++;
1674                }
1675                else
1676                   valid = false;
1677             }
1678             else if(!strcmp(arg, "-name"))
1679             {
1680                if(c + 1 < argc)
1681                {
1682                   strcpy(projectName, argv[c+1]);
1683                   c++;
1684                }
1685                else
1686                   valid = false;
1687             }
1688             else if(!strcmp(arg, "-t"))
1689             {
1690                if(++c < argc)
1691                   targetPlatform = argv[c];
1692                else
1693                   valid = false;
1694             }
1695             else if(!strcmp(arg, "-outputpot"))
1696                outputPot = true;
1697             else if(!strcmp(arg, "-disabled-pooling"))
1698                disabledPooling = true;
1699             else if(!strcmp(arg, "-console"))
1700                isConsole = true;
1701             else if(!strcmp(arg, "-dynamiclib"))
1702                isDynamicLibrary = true;
1703             else if(!strcmp(arg, "-staticlib"))
1704             {
1705                isDynamicLibrary = true;   // TOFIX: unmixup
1706                isStaticLibrary = true;
1707             }
1708             else if(!strcmp(arg, "-symbols"))
1709             {
1710                if(c + 1 < argc)
1711                {
1712                   SetSymbolsDir(argv[c+1]);
1713                   c++;
1714                }
1715                else
1716                   valid = false;
1717             }
1718          }
1719       }
1720       if(!output)
1721          valid = false;
1722
1723       if(!valid)
1724       {
1725          printf($"Syntax:\n   ecs [-t <target platform>] <input>[, <input>]* -o <output>\n");
1726       }
1727       else
1728       {
1729          int c;
1730          char ext[MAX_EXTENSION];
1731          char symbolModule[MAX_FILENAME];
1732          GetExtension(output, ext);
1733          GetLastDirectory(output, symbolModule);
1734
1735          SetDefines(&::_defines);
1736          SetImports(&_imports);
1737          SetGlobalData(&globalData);
1738          SetExcludedSymbols(&_excludedSymbols);
1739          SetGlobalContext(theGlobalContext);
1740          SetTopContext(theGlobalContext);
1741          SetCurrentContext(theGlobalContext);
1742          SetTargetPlatform(targetPlatform);
1743          SetTargetBits(targetBits);
1744          SetInSymbolGen(true);
1745
1746          privateModule = (Module)__ecere_COM_Initialize(true | (targetBits == sizeof(uintptr)*8 ? 0 : targetBits == 64 ? 2 : targetBits==32 ? 4 : 0) | 8, 1, null);
1747          SetPrivateModule(privateModule);
1748          mainModule = ModuleImport { };
1749          SetMainModule(mainModule);
1750          _imports.Add(mainModule);
1751
1752          //if(!strcmp(ext, "c"))
1753          {
1754             String symbolsDir = GetSymbolsDir();
1755             // Only generating .pot files when building from release.* directory for now
1756             //bool outputPot = symbolsDir && SearchString(symbolsDir, 0, "release.", false, false);
1757             Map<ContextStringPair, List<String> > intlStrings { };
1758             MapIterator<ContextStringPair, List<String>> it { map = intlStrings };
1759
1760             for(c = 1; c<argc; c++)
1761             {
1762                char * file = argv[c];
1763                File f = null;
1764                char line[16384];
1765                int count = 0;
1766                char * tokens[512];
1767                if(file[0] == '-')
1768                {
1769                   if(!strcmp(file, "-c"))
1770                      c++;
1771                }
1772                else if(file[0] == '@')
1773                   f = FileOpen(&file[1], read);
1774                else
1775                {
1776                   count = 1;
1777                   tokens[0] = file;
1778                }
1779                while(count || f)
1780                {
1781                   int c;
1782                   if(f)
1783                   {
1784                      while(!count && f.GetLine(line, sizeof(line)))
1785                         count = Tokenize(line, sizeof(tokens)/sizeof(tokens[0]), tokens, forArgsPassing);
1786                      if(!count)
1787                         delete f;
1788                   }
1789                   for(c = 0; c < count; c++)
1790                   {
1791                      char ext[MAX_EXTENSION];
1792                      file = tokens[c];
1793                      GetExtension(file, ext);
1794                      if(!strcmp(ext, "imp"))
1795                         LoadImports(file);
1796                   }
1797                   count = 0;
1798                }
1799             }
1800
1801             // What is this supposed to do?
1802             for(c = 1; c<argc; c++)
1803             {
1804                char * file = argv[c];
1805                if(file[0] == '-')
1806                {
1807                   if(!strcmp(file, "-c"))
1808                      c++;
1809                }
1810             }
1811
1812             for(c = 1; c<argc; c++)
1813             {
1814                char * file = argv[c];
1815                File f = null;
1816                char line[16384];
1817                int count = 0;
1818                char * tokens[512];
1819                if(file[0] == '-')
1820                {
1821                   // Don't even know what it does here?
1822                   if(!strcmp(file, "-c"))
1823                      c++;
1824                }
1825                else if(file[0] == '@')
1826                   f = FileOpen(&file[1], read);
1827                else
1828                {
1829                   count = 1;
1830                   tokens[0] = file;
1831                }
1832
1833                while(count || f)
1834                {
1835                   int c;
1836                   if(f)
1837                   {
1838                      while(!count && f.GetLine(line, sizeof(line)))
1839                         count = Tokenize(line, sizeof(tokens)/sizeof(tokens[0]), tokens, forArgsPassing);
1840                      if(!count)
1841                         delete f;
1842                   }
1843                   for(c = 0; c < count; c++)
1844                   {
1845                      char ext[MAX_EXTENSION];
1846                      char moduleName[MAX_LOCATION];
1847
1848                      file = tokens[c];
1849
1850                      GetExtension(file, ext);
1851
1852                      GetLastDirectory(file, moduleName);
1853                      StripExtension(moduleName);
1854                      strcat(moduleName, ".ec");
1855
1856                      if(fstrcmp(moduleName, symbolModule) && (!strcmp(ext, "sym") || !strcmp(ext, "ec")))
1857                      {
1858                         ImportedModule importedModule;
1859                         ModuleInfo module { };
1860                         char fileName[MAX_FILENAME];
1861                         ::modules.Add(module);
1862
1863                         GetLastDirectory(file, fileName);
1864
1865                         module.name = CopyString(fileName);
1866
1867                         StripExtension(module.name);
1868
1869                         for(importedModule = ::_defines.first; importedModule; importedModule = importedModule.next)
1870                         {
1871                            if(importedModule.type == moduleDefinition && !strcmpi(importedModule.name, module.name) && !(importedModule.importType == remoteImport))
1872                               break;
1873                         }
1874
1875                         if(importedModule)
1876                            module.globalInstance = importedModule.globalInstance;
1877                         else
1878                         {
1879                            importedModule = ImportedModule
1880                            {
1881                               name = CopyString(module.name),
1882                               type = moduleDefinition,
1883                               importType = normalImport
1884                            };
1885                            ::_defines.AddName(importedModule);
1886
1887                            module.globalInstance = LoadSymbols(file, normalImport, false);
1888                            CheckDataRedefinitions();
1889                         }
1890
1891                         // I18n code
1892                         {
1893                            File f;
1894                            ChangeExtension(file, "bowl", fileName);
1895                            f = FileOpen(fileName, read);
1896                            if(f)
1897                            {
1898                               static char line[65536];
1899                               List<String> comments { };
1900                               String msgid = null, msgstr = null, msgctxt = null;
1901                               while(!f.Eof())
1902                               {
1903                                  if(f.GetLine(line, sizeof(line)))
1904                                  {
1905                                     int len;
1906                                     TrimLSpaces(line, line);
1907                                     if(line[0] == '#')
1908                                     {
1909                                        comments.Add(CopyString(line));
1910                                     }
1911                                     else if(strstr(line, "msgid \"") == line)
1912                                     {
1913                                        delete msgid;
1914                                        msgid = CopyString(line + 7);
1915                                        len = strlen(msgid);
1916                                        if(len) msgid[len-1] = 0;
1917                                     }
1918                                     else if(strstr(line, "msgctxt \"") == line)
1919                                     {
1920                                        delete msgctxt;
1921                                        msgctxt = CopyString(line + 9);
1922                                        len = strlen(msgctxt);
1923                                        if(len) msgctxt[len-1] = 0;
1924                                     }
1925                                     else if(strstr(line, "msgstr \"") == line)
1926                                     {
1927                                        delete msgstr;
1928                                        msgstr = CopyString(line + 8);
1929                                        len = strlen(msgstr);
1930                                        if(len) msgstr[len-1] = 0;
1931                                     }
1932
1933                                     if(msgid && msgstr)
1934                                     {
1935                                        ContextStringPair pair { msgid, msgctxt };
1936                                        i18n = true;
1937                                        if(!it.Index(pair, false))
1938                                        {
1939                                           msgid = null; msgctxt = null;
1940                                           intlStrings[pair] = comments;
1941                                           comments = { };
1942                                        }
1943                                        else
1944                                        {
1945                                           for(s : comments)
1946                                              it.data.Add(s);
1947                                           comments.RemoveAll();
1948                                        }
1949
1950                                        delete msgid;
1951                                        delete msgctxt;
1952                                        delete msgstr;
1953                                     }
1954                                  }
1955                               }
1956                               comments.Free();
1957                               delete comments;
1958                               delete f;
1959                            }
1960                         }
1961                      }
1962                   }
1963                   count = 0;
1964                }
1965             }
1966
1967             ComputeModuleClasses(privateModule);
1968
1969             if(!isDynamicLibrary)
1970             {
1971                // applicationClass = eSystem_FindClass(privateModule, "Application");
1972                /*
1973                thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, true);
1974                if(!thisAppClass)
1975                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, true);
1976                if(!thisAppClass)
1977                   thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, false);
1978                if(!thisAppClass)
1979                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, false);
1980                */
1981                thisAppClass = SearchAppClass_Module(privateModule);
1982             }
1983             WriteMain(output);
1984
1985             if(outputPot && intlStrings.count)
1986             {
1987                File potFile;
1988                char potFileName[MAX_LOCATION];
1989                //strcpy(potFileName, output);
1990                //StripExtension(potFileName);
1991                strcpy(potFileName, "locale");
1992                MakeDir(potFileName);
1993                PathCat(potFileName, projectName);
1994                ChangeExtension(potFileName, "pot", potFileName);
1995                potFile = FileOpen(potFileName, write);
1996                if(potFile)
1997                {
1998                   // Write header:
1999                   potFile.Puts("msgid \"\"\n");
2000                   potFile.Puts("msgstr \"\"\n");
2001                   potFile.Puts("\"Project-Id-Version: \\n\"\n");
2002                   potFile.Puts("\"POT-Creation-Date: \\n\"\n");
2003                   potFile.Puts("\"PO-Revision-Date: \\n\"\n");
2004                   potFile.Puts("\"Last-Translator: \\n\"\n");
2005                   potFile.Puts("\"Language-Team: \\n\"\n");
2006                   potFile.Puts("\"MIME-Version: 1.0\\n\"\n");
2007                   potFile.Puts("\"Content-Type: text/plain; charset=iso-8859-1\\n\"\n");
2008                   potFile.Puts("\"Content-Transfer-Encoding: 8bit\\n\"\n");
2009                   potFile.Puts("\"X-Poedit-Basepath: ../\\n\"\n");
2010                   potFile.Puts("\n");
2011
2012                   for(i : intlStrings)
2013                   {
2014                      ContextStringPair pair = &i;
2015                      List<String> comments = i;
2016                      for(s : comments)
2017                      {
2018                         potFile.Printf(s);
2019                         potFile.Puts("\n");
2020                      }
2021
2022                      if(pair.context)
2023                      {
2024                         potFile.Puts("msgctxt \""); potFile.Puts(pair.context); potFile.Puts("\"\n");
2025                      }
2026                      potFile.Puts("msgid \""); potFile.Puts(pair.string); potFile.Puts("\"\n");
2027                      potFile.Puts("msgstr \""); potFile.Puts(pair.string); potFile.Puts("\"\n");
2028                      potFile.Puts("\n");
2029                   }
2030                   intlStrings.Free();
2031                   delete intlStrings;
2032                   delete potFile;
2033                }
2034             }
2035          }
2036
2037          FreeContext(theGlobalContext);
2038          FreeExcludedSymbols(_excludedSymbols);
2039
2040          ::_defines.Free(FreeModuleDefine);
2041          _imports.Free(FreeModuleImport);
2042
2043          //precompDefines.Free(FreeDefinition);
2044
2045          FreeTypeData(privateModule);
2046          FreeIncludeFiles();
2047          FreeGlobalData(globalData);
2048
2049          delete privateModule;
2050       }
2051
2052       SetSymbolsDir(null); // Free symbols dir
2053
2054       /*
2055       for(c = 0; c<argc; c++)
2056          delete argv[c];
2057       delete argv;
2058       */
2059
2060 #ifdef _DEBUG
2061       getch();
2062 #endif
2063    }
2064 }