a509c9e088d73dfb1c73cac7346272a3aa693f61
[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, "o"))
1665             {
1666                if(!output && c + 1 < argc)
1667                {
1668                   output = argv[c+1];
1669                   c++;
1670                }
1671                else
1672                   valid = false;
1673             }
1674             else if(!strcmp(arg, "-name"))
1675             {
1676                if(c + 1 < argc)
1677                {
1678                   strcpy(projectName, argv[c+1]);
1679                   c++;
1680                }
1681                else
1682                   valid = false;
1683             }
1684             else if(!strcmp(arg, "-t"))
1685             {
1686                if(++c < argc)
1687                   targetPlatform = argv[c];
1688                else
1689                   valid = false;
1690             }
1691             else if(!strcmp(arg, "-outputpot"))
1692                outputPot = true;
1693             else if(!strcmp(arg, "-disabled-pooling"))
1694                disabledPooling = true;
1695             else if(!strcmp(arg, "-console"))
1696                isConsole = true;
1697             else if(!strcmp(arg, "-dynamiclib"))
1698                isDynamicLibrary = true;
1699             else if(!strcmp(arg, "-staticlib"))
1700             {
1701                isDynamicLibrary = true;   // TOFIX: unmixup
1702                isStaticLibrary = true;
1703             }
1704             else if(!strcmp(arg, "-symbols"))
1705             {
1706                if(c + 1 < argc)
1707                {
1708                   SetSymbolsDir(argv[c+1]);
1709                   c++;
1710                }
1711                else
1712                   valid = false;
1713             }
1714          }
1715       }
1716       if(!output)
1717          valid = false;
1718      
1719       if(!valid)
1720       {
1721          printf($"Syntax:\n   ecs [-t <target platform>] <input>[, <input>]* -o <output>\n");
1722       }
1723       else
1724       {
1725          int c;
1726          char ext[MAX_EXTENSION];
1727          char symbolModule[MAX_FILENAME];
1728          GetExtension(output, ext);
1729          GetLastDirectory(output, symbolModule);
1730          
1731          SetDefines(&::_defines);
1732          SetImports(&_imports);
1733          SetGlobalData(&globalData);
1734          SetExcludedSymbols(&_excludedSymbols);
1735          SetGlobalContext(theGlobalContext);
1736          SetTopContext(theGlobalContext);
1737          SetCurrentContext(theGlobalContext);
1738          SetTargetPlatform(targetPlatform);
1739          SetTargetBits(targetBits);
1740          SetInSymbolGen(true);
1741
1742          privateModule = (Module)__ecere_COM_Initialize(true | (targetBits == sizeof(uintptr)*8 ? 0 : targetBits == 64 ? 2 : targetBits==32 ? 4 : 0) | 8, 1, null);
1743          SetPrivateModule(privateModule);
1744          mainModule = ModuleImport { };
1745          SetMainModule(mainModule);
1746          _imports.Add(mainModule);
1747
1748          //if(!strcmp(ext, "c"))
1749          {
1750             String symbolsDir = GetSymbolsDir();
1751             // Only generating .pot files when building from release.* directory for now
1752             //bool outputPot = symbolsDir && SearchString(symbolsDir, 0, "release.", false, false);
1753             Map<ContextStringPair, List<String> > intlStrings { };
1754             MapIterator<ContextStringPair, List<String>> it { map = intlStrings };
1755
1756             for(c = 1; c<argc; c++)
1757             {
1758                char * file = argv[c];
1759                if(file[0] == '-')
1760                {
1761                   if(!strcmp(file, "-c"))
1762                      c++;
1763                }
1764                else
1765                {
1766                   char ext[MAX_EXTENSION];
1767                   GetExtension(file,ext);
1768                   if(!strcmp(ext, "imp"))
1769                      LoadImports(file);
1770                }
1771             }
1772
1773             // What is this supposed to do?
1774             for(c = 1; c<argc; c++)
1775             {
1776                char * file = argv[c];
1777                if(file[0] == '-')
1778                {
1779                   if(!strcmp(file, "-c"))
1780                      c++;
1781                }
1782             }
1783
1784             for(c = 1; c<argc; c++)
1785             {
1786                char * file = argv[c];
1787                if(file[0] == '-')
1788                {
1789                   // Don't even know what it does here?
1790                   if(!strcmp(file, "-c"))
1791                      c++;
1792                }
1793                else
1794                {
1795                   char ext[MAX_EXTENSION];
1796                   char moduleName[MAX_LOCATION];
1797
1798                   GetExtension(file,ext);
1799
1800                   GetLastDirectory(file, moduleName);
1801                   StripExtension(moduleName);
1802                   strcat(moduleName, ".ec");
1803
1804                   if(fstrcmp(moduleName, symbolModule) && (!strcmp(ext, "sym") || !strcmp(ext, "ec")))
1805                   {
1806                      ImportedModule importedModule;
1807                      ModuleInfo module { };
1808                      char fileName[MAX_FILENAME];
1809                      ::modules.Add(module);
1810
1811                      GetLastDirectory(file, fileName);
1812
1813                      module.name = CopyString(fileName);
1814                      
1815                      StripExtension(module.name);                     
1816
1817                      for(importedModule = ::_defines.first; importedModule; importedModule = importedModule.next)
1818                      {
1819                         if(importedModule.type == moduleDefinition && !strcmpi(importedModule.name, module.name) && !(importedModule.importType == remoteImport))
1820                            break;
1821                      }
1822
1823                      if(importedModule)
1824                         module.globalInstance = importedModule.globalInstance;
1825                      else
1826                      {
1827                         importedModule = ImportedModule
1828                         {
1829                            name = CopyString(module.name),
1830                            type = moduleDefinition,
1831                            importType = normalImport
1832                         };
1833                         ::_defines.AddName(importedModule);
1834
1835                         module.globalInstance = LoadSymbols(file, normalImport, false);
1836                         CheckDataRedefinitions();
1837                      }
1838
1839                      // I18n code
1840                      {
1841                         File f;
1842                         ChangeExtension(file, "bowl", fileName);
1843                         f = FileOpen(fileName, read);
1844                         if(f)
1845                         {
1846                            static char line[65536];
1847                            List<String> comments { };
1848                            String msgid = null, msgstr = null, msgctxt = null;
1849                            while(!f.Eof())
1850                            {
1851                               if(f.GetLine(line, sizeof(line)))
1852                               {
1853                                  int len;
1854                                  TrimLSpaces(line, line);
1855                                  if(line[0] == '#')
1856                                  {
1857                                     comments.Add(CopyString(line));
1858                                  }
1859                                  else if(strstr(line, "msgid \"") == line)
1860                                  {
1861                                     delete msgid;
1862                                     msgid = CopyString(line + 7);
1863                                     len = strlen(msgid);
1864                                     if(len) msgid[len-1] = 0;
1865                                  }
1866                                  else if(strstr(line, "msgctxt \"") == line)
1867                                  {
1868                                     delete msgctxt;
1869                                     msgctxt = CopyString(line + 9);
1870                                     len = strlen(msgctxt);
1871                                     if(len) msgctxt[len-1] = 0;
1872                                  }
1873                                  else if(strstr(line, "msgstr \"") == line)
1874                                  {
1875                                     delete msgstr;
1876                                     msgstr = CopyString(line + 8);
1877                                     len = strlen(msgstr);
1878                                     if(len) msgstr[len-1] = 0;
1879                                  }
1880
1881                                  if(msgid && msgstr)
1882                                  {
1883                                     ContextStringPair pair { msgid, msgctxt };
1884                                     i18n = true;
1885                                     if(!it.Index(pair, false))
1886                                     {
1887                                        msgid = null; msgctxt = null;
1888                                        intlStrings[pair] = comments;
1889                                        comments = { };
1890                                     }
1891                                     else
1892                                     {
1893                                        for(s : comments)
1894                                           it.data.Add(s);
1895                                        comments.RemoveAll();
1896                                     }
1897
1898                                     delete msgid;
1899                                     delete msgctxt;
1900                                     delete msgstr;
1901                                  }
1902                               }
1903                            }
1904                            comments.Free();
1905                            delete comments;
1906                            delete f;
1907                         }
1908                      }
1909                   }
1910                }
1911             }
1912
1913             ComputeModuleClasses(privateModule);
1914
1915             if(!isDynamicLibrary)
1916             {
1917                // applicationClass = eSystem_FindClass(privateModule, "Application");
1918                /*
1919                thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, true);
1920                if(!thisAppClass)
1921                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, true);
1922                if(!thisAppClass)
1923                   thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, false);
1924                if(!thisAppClass)
1925                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, false);
1926                */
1927                thisAppClass = SearchAppClass_Module(privateModule);
1928             }
1929             WriteMain(output);
1930
1931             if(outputPot && intlStrings.count)
1932             {
1933                File potFile;
1934                char potFileName[MAX_LOCATION];
1935                //strcpy(potFileName, output);
1936                //StripExtension(potFileName);
1937                strcpy(potFileName, "locale");
1938                MakeDir(potFileName);
1939                PathCat(potFileName, projectName);
1940                ChangeExtension(potFileName, "pot", potFileName);
1941                potFile = FileOpen(potFileName, write);
1942                if(potFile)
1943                {
1944                   // Write header:
1945                   potFile.Puts("msgid \"\"\n");
1946                   potFile.Puts("msgstr \"\"\n");
1947                   potFile.Puts("\"Project-Id-Version: \\n\"\n");
1948                   potFile.Puts("\"POT-Creation-Date: \\n\"\n");
1949                   potFile.Puts("\"PO-Revision-Date: \\n\"\n");
1950                   potFile.Puts("\"Last-Translator: \\n\"\n");
1951                   potFile.Puts("\"Language-Team: \\n\"\n");
1952                   potFile.Puts("\"MIME-Version: 1.0\\n\"\n");
1953                   potFile.Puts("\"Content-Type: text/plain; charset=iso-8859-1\\n\"\n");
1954                   potFile.Puts("\"Content-Transfer-Encoding: 8bit\\n\"\n");
1955                   potFile.Puts("\"X-Poedit-Basepath: ../\\n\"\n");
1956                   potFile.Puts("\n");
1957
1958                   for(i : intlStrings)
1959                   {
1960                      ContextStringPair pair = &i;
1961                      List<String> comments = i;
1962                      for(s : comments)
1963                      {
1964                         potFile.Printf(s);
1965                         potFile.Puts("\n");
1966                      }
1967
1968                      if(pair.context)
1969                      {
1970                         potFile.Puts("msgctxt \""); potFile.Puts(pair.context); potFile.Puts("\"\n");
1971                      }
1972                      potFile.Puts("msgid \""); potFile.Puts(pair.string); potFile.Puts("\"\n");
1973                      potFile.Puts("msgstr \""); potFile.Puts(pair.string); potFile.Puts("\"\n");
1974                      potFile.Puts("\n");
1975                   }
1976                   intlStrings.Free();
1977                   delete intlStrings;
1978                   delete potFile;
1979                }
1980             }
1981          }
1982
1983          FreeContext(theGlobalContext);
1984          FreeExcludedSymbols(_excludedSymbols);
1985
1986          ::_defines.Free(FreeModuleDefine);
1987          _imports.Free(FreeModuleImport);
1988
1989          //precompDefines.Free(FreeDefinition);   
1990
1991          FreeTypeData(privateModule);
1992          FreeIncludeFiles();
1993          FreeGlobalData(globalData);
1994
1995          delete privateModule;
1996       }
1997
1998       SetSymbolsDir(null); // Free symbols dir
1999
2000       /*
2001       for(c = 0; c<argc; c++)
2002          delete argv[c];
2003       delete argv;
2004       */
2005
2006 #ifdef _DEBUG
2007       getch();
2008 #endif
2009    }
2010 }