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