ecere & compiler: Built-in internationalization support
[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       if(isDynamicLibrary)
638       {
639          //f.Printf("   module._vTbl[10](module);\n");
640          f.Puts("   }\n");
641       }
642
643       if(i18n)
644          f.Printf("   LoadTranslatedStrings(module, \"%s\");\n", projectName);
645
646       if(!isDynamicLibrary && thisAppClass)
647       {
648          f.Printf("   _class = eSystem_FindClass(__currentModule, \"%s\");\n", thisAppClass.name);
649          f.Printf("   eInstance_Evolve((Instance *)&__currentModule, _class);\n");
650          f.Printf("   __thisModule = __currentModule;\n");
651       }
652
653       if(isDynamicLibrary)
654       {
655          f.Puts("   if(__currentModule == module)\n");
656          f.Puts("   {\n");
657       }
658
659       // Then check if there's any global instances to create
660       if(::modules.count)
661       {
662          for(defModule = ::modules.first; defModule; defModule = defModule.next)
663             if(defModule.globalInstance)
664             {
665                char moduleName[1024];
666                strcpy(moduleName, defModule.name);
667                ChangeCh(moduleName, ' ', '_');
668                ChangeCh(moduleName, '-', '_');
669                ChangeCh(moduleName, '.', '_');
670
671                f.Printf("   __ecereCreateModuleInstances_%s();\n", moduleName);
672             }
673
674          f.Printf("\n");
675       }
676
677       if(isDynamicLibrary)
678       {
679          f.Puts("   }\n");
680       }
681       if(!isDynamicLibrary && thisAppClass)
682       {
683          f.Printf("   __currentModule._vTbl[12](__currentModule);\n");
684       }
685
686       if(isDynamicLibrary)
687       {
688          f.Puts("   return true;\n");
689          f.Puts("}\n");
690          if(isStaticLibrary)
691          {
692             /*if(targetPlatform == win32)
693                f.Printf("\nbool __stdcall __ecereDll_Unload_%s(Module module)\n{\n", projectName);
694             else*/
695                f.Printf("\nbool __ecereDll_Unload_%s(Module module)\n{\n", projectName);
696          }
697          else
698          {
699             if(targetPlatform == win32)
700                f.Puts("\ndllexport bool __stdcall __ecereDll_Unload(Module module)\n{\n");
701             else
702                f.Puts("\ndllexport bool __ecereDll_Unload(Module module)\n{\n");
703          }
704       }
705
706       if(isDynamicLibrary)
707       {
708          f.Puts("   if(__currentModule == module)\n");
709          f.Puts("   {\n");
710       }
711       // Then check if there's any global instances to destroy
712       if(::modules.count)
713       {
714          for(defModule = ::modules.first; defModule; defModule = defModule.next)
715             if(defModule.globalInstance)
716             {
717                char moduleName[1024];
718                strcpy(moduleName, defModule.name);
719                ChangeCh(moduleName, ' ', '_');
720                ChangeCh(moduleName, '-', '_');
721                ChangeCh(moduleName, '.', '_');
722                f.Printf("   __ecereDestroyModuleInstances_%s();\n", moduleName);
723             }
724
725          f.Printf("\n");
726       }
727       if(i18n)
728          f.Printf("   UnloadTranslatedStrings(__currentModule);\n");
729       if(isDynamicLibrary)
730       {
731          f.Puts("   }\n");
732
733          if(isDynamicLibrary)
734          {
735             //f.Printf("   module._vTbl[11](module);\n");
736          }
737
738          if(::modules.count)
739          {
740             for(defModule = ::modules.first; defModule; defModule = defModule.next)
741             {
742                char moduleName[1024];
743                strcpy(moduleName, defModule.name);
744                ChangeCh(moduleName, ' ', '_');
745                ChangeCh(moduleName, '-', '_');
746                ChangeCh(moduleName, '.', '_');
747                f.Printf("   __ecereUnregisterModule_%s(module);\n", moduleName);
748             }
749             f.Printf("\n");
750          }
751          f.Puts("   if(__currentModule == module)\n");
752          f.Puts("      __currentModule = (void *)0;\n");
753          if(!isStaticLibrary)
754          {
755             f.Puts("   if(__thisModule == module)\n");
756             f.Puts("      __thisModule = (void *)0;\n");
757          }
758       }
759
760       if(!isDynamicLibrary)
761       {
762          f.Puts(
763             "\n"
764             "   _class = eSystem_FindClass(__currentModule, \"ecere::com::Application\");\n"
765             "   exitCode = ((ecere::com::Application)__currentModule).exitCode;\n"
766             "   delete __currentModule;\n"
767             "   return exitCode;\n");
768       }
769       else
770          f.Puts("   return true;\n");
771       f.Puts("}\n");
772       eInstance_Delete(f);
773    }
774 }
775
776 static Class FindAppClass(NameSpace * nameSpace, bool thisModule)
777 {
778    BTNamedLink link;
779    NameSpace * ns;
780    for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
781    {
782       Class _class = link.data;
783       /*
784       applicationClass = eSystem_FindClass(_class.module, "Application");
785       if(_class != applicationClass && eClass_IsDerived(_class, applicationClass) && (!thisModule || _class.module == privateModule))
786          return _class;
787       */
788       if(strcmp(_class.fullName, "ecere::com::Application") && (!thisModule || _class.module == privateModule))
789       {
790          Class base;
791          for(base = _class.base; base && base.type != systemClass; base = base.base)
792             if(!strcmp(base.fullName, "ecere::com::Application"))
793                return _class;
794       }
795    }
796
797    for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
798    {
799       Class _class = FindAppClass(ns, thisModule);
800       if(_class) // && _class != applicationClass)
801          return _class;
802    }
803    return null; //applicationClass;
804 }
805
806 static Class SearchAppClass_Module(Module module)
807 {
808    Class appClass;
809    SubModule subModule;
810
811    appClass = FindAppClass(module.publicNameSpace, false);
812    if(appClass) return appClass;
813    appClass = FindAppClass(module.privateNameSpace, false);
814    if(appClass) return appClass;
815
816    for(subModule = module.modules.first; subModule; subModule = subModule.next)
817    {
818       appClass = SearchAppClass_Module(subModule.module);
819       if(appClass) return appClass;
820    }
821    return null;
822 }
823
824 static void BindDCOMClient()
825 {
826    Class dcomClientObjectClass = eSystem_FindClass(privateModule, "ecere::net::DCOMClientObject");
827    OldLink deriv;
828
829    if(dcomClientObjectClass && dcomClientObjectClass.derivatives.first)
830    {
831       File f;
832       if(!dcomSymbols) dcomSymbols = TempFile { };
833       f = dcomSymbols;
834
835       // CLIENT BINDINGS
836       for(deriv = dcomClientObjectClass.derivatives.first; deriv; deriv = deriv.next)
837       {
838          Class _class = deriv.data;
839          Method method, next;
840          int id = 0;
841          int vid;
842          bool doVirtual;
843
844          DeclareClass(FindClass("ecere::net::DCOMClientObject"), "__ecereClass___ecereNameSpace__ecere__net__DCOMClientObject");
845          f.Printf("class %s : ecere::net::DCOMClientObject\n", _class.fullName);
846          f.Printf("{\n");
847
848          // CLIENT VIRTUAL METHODS BINDINGS
849          if(_class.vTblSize > _class.base.vTblSize)
850          {
851             int vid;
852             f.Printf("   virtual void CallVirtualMethod(uint __ecereMethodID, SerialBuffer __ecereBuffer)\n");
853             f.Printf("   {\n");
854             f.Printf("      switch(__ecereMethodID)\n");
855             f.Printf("      {\n");
856
857             for(vid = _class.base.vTblSize; vid < _class.vTblSize; vid++)
858             {
859                Method method;
860                for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
861                {
862                   if(method.type == virtualMethod && method._class == _class && method.vid == vid)
863                      break;
864                }
865                if(method)
866                {
867                   Type param;
868                   method.dataType = ProcessTypeString(method.dataTypeString, false);
869                   if(method.dataType && method.dataType.name)
870                   {
871                      f.Printf("         case %d:\n", vid - _class.base.vTblSize);
872                      f.Printf("         {\n");
873                      {
874                         if(method.dataType.returnType.kind != voidType)
875                         {
876                            TypeName resultType;
877                            OldList * specs = MkList();
878                            Declarator decl;
879                            char type[1024] = "";
880                            char className[1024];
881                            Symbol classSym;
882
883                            if(method.dataType.returnType.kind == classType)
884                               classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
885                            else
886                            {
887                               PrintType(method.dataType.returnType, type, false, true);
888                               classSym = FindClass(type);
889                               type[0] = 0;
890                            }
891                            strcpy(className, "__ecereClass_");
892                            FullClassNameCat(className, classSym.string, true);
893                            MangleClassName(className);
894                            DeclareClass(classSym, className);
895
896                            PrintType(method.dataType.returnType, type, true, true);
897
898                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
899                            resultType = MkTypeName(specs, decl);
900
901                            f.Printf("            ");
902                            OutputTypeName(resultType, f);
903                            f.Printf(";\n");
904                         }
905
906                         for(param = method.dataType.params.first; param; param = param.next)
907                         {
908                            if(param.kind == classType && !strcmp(param._class.string, "String"))
909                            {
910                               // Hardcode 1024 chars max string for now
911                               f.Printf("            char %s[1024];\n", param.name);
912                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
913                               DeclareClass(FindClass("String"), "__ecereClass_String");
914                            }
915                            else
916                            {
917                               TypeName paramTypeName;
918                               OldList * specs = MkList();
919                               Declarator decl;
920                               char type[1024] = "";
921                               char className[1024];
922                               Symbol classSym;
923
924                               if(param.kind == classType)
925                                  classSym = param._class; // VERIFY THIS FindClass(param._class.string);
926                               else
927                               {
928                                  PrintType(param, type, false, true);
929                                  classSym = FindClass(type);
930                                  type[0] = 0;
931                               }
932
933                               strcpy(className, "__ecereClass_");
934                               FullClassNameCat(className, classSym.string, true);
935                               MangleClassName(className);
936                               DeclareClass(classSym, className);
937
938                               PrintType(param, type, true, true);
939
940                               decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier(param.name /*"__ecereResult"*/)));
941                               paramTypeName = MkTypeName(specs, decl);
942
943                               f.Printf("            ");
944                               OutputTypeName(paramTypeName, f);
945
946                               f.Printf(";\n");
947                            }
948                         }
949                         f.Printf("\n");
950
951                         for(param = method.dataType.params.first; param; param = param.next)
952                         {
953                            f.Printf("            __ecereBuffer.Unserialize(");
954                            if(param.kind == classType && !strcmp(param._class.string, "String"))
955                            {
956                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
957                               f.Printf("(StaticString)");
958                            }
959                            f.Puts(param.name);
960                            f.Printf(");\n");
961                         }
962
963                         f.Printf("            ");
964                         if(method.dataType.returnType.kind != voidType)
965                            f.Printf("__ecereResult = ");
966
967                         // f.Printf("this.instance.%s(", method.name);
968                         f.Printf("%s(", method.name);
969                         
970                         for(param = method.dataType.params.first; param; param = param.next)
971                         {
972                            if(param.prev)
973                               f.Printf(", ");
974                            f.Printf("%s", param.name);
975                         }
976
977                         f.Printf(");\n");
978
979                         for(param = method.dataType.params.first; param; param = param.next)
980                         {
981                            if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
982                            {
983                               if(!strcmp(param._class.string, "String"))
984                               {
985                                  DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
986                                  f.Printf("            __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
987                               }
988                               else
989                                  f.Printf("            __ecereBuffer.Serialize(%s);\n", param.name);
990                            }
991                         }
992                         if(method.dataType.returnType.kind != voidType)
993                         {
994                            f.Printf("            __ecereBuffer.Serialize(__ecereResult);\n");
995                         }
996
997                         for(param = method.dataType.params.first; param; param = param.next)
998                         {
999                            if(param.kind == classType && strcmp(param._class.string, "String") && param._class.registered && 
1000                               (param._class.registered.type == normalClass || param._class.registered.type == noHeadClass))
1001                            {
1002                               f.Printf("            delete %s;\n", param.name);
1003                            }
1004                         }
1005                         if(method.dataType.returnType.kind == classType && strcmp(method.dataType.returnType._class.string, "String") && method.dataType.returnType._class.registered && 
1006                               (method.dataType.returnType._class.registered.type == normalClass || method.dataType.returnType._class.registered.type == noHeadClass))
1007                         {
1008                            f.Printf("            delete __ecereResult;\n");
1009                         }
1010                      }
1011
1012                      f.Printf("            break;\n");
1013                      f.Printf("         }\n");
1014                   }
1015                }
1016             }
1017             f.Printf("      }\n");
1018             f.Printf("   }\n");
1019             f.Printf("\n");
1020          } 
1021
1022          doVirtual = true;
1023          id = 0;
1024          vid = _class.base.vTblSize;
1025
1026          next = (Method)_class.methods.first;
1027          while(next && ((next.type == virtualMethod) != doVirtual || (doVirtual && next.vid != vid)))
1028          {
1029             id++;
1030             next = (Method)((BTNode)next).next;
1031             if(!next && doVirtual)
1032             {
1033                if(vid == _class.vTblSize)
1034                   doVirtual = false;
1035                else
1036                   vid++;
1037                id = 0;
1038                next = (Method)_class.methods.first;
1039             }
1040          }
1041          for(method = next; method; method = next)
1042          {
1043             Type param;
1044
1045             if(!method.dataType)
1046                method.dataType = ProcessTypeString(method.dataTypeString, false);
1047
1048             if(method.dataType.name)
1049             {
1050                f.Printf("   ");
1051                if(doVirtual)
1052                {
1053                   char name[1024];
1054                   strcpy(name, "__ecereVMethodID_");
1055                   FullClassNameCat(name, method._class.fullName, true);
1056                   strcat(name, "_");
1057                   strcat(name, method.name);
1058                   DeclareMethod(method, name);
1059
1060                   f.Printf("virtual ");
1061                }
1062                f.Printf("%s\n", method.dataTypeString);
1063                f.Printf("   {\n");
1064
1065                if(method.dataType)
1066                {
1067                   if(method.dataType.returnType.kind != voidType)
1068                   {
1069                      TypeName resultType;
1070                      OldList * specs = MkList();
1071                      Declarator decl;
1072                      char type[1024] = "";
1073                      char className[1024];
1074                      Symbol classSym;
1075
1076                      if(method.dataType.returnType.kind == classType)
1077                         classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1078                      else
1079                      {
1080                         PrintType(method.dataType.returnType, type, false, true);
1081                         classSym = FindClass(type);
1082                         type[0] = 0;
1083                      }
1084
1085                      strcpy(className, "__ecereClass_");
1086                      FullClassNameCat(className, classSym.string, true);
1087                      MangleClassName(className);
1088                      DeclareClass(classSym, className);
1089
1090                      PrintType(method.dataType.returnType, type, true, true);
1091
1092                      decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1093                      resultType = MkTypeName(specs, decl);
1094
1095                      f.Printf("      ");
1096                      OutputTypeName(resultType, f);
1097                      if(method.dataType.returnType.kind == structType)
1098                         f.Printf(" = { 0 }");
1099                      else if(method.dataType.returnType.kind == classType && method.dataType.returnType._class.registered && method.dataType.returnType._class.registered.type == structClass)
1100                         f.Printf(" { }");
1101                      else
1102                         f.Printf(" = 0");
1103                      f.Printf(";\n\n");
1104                   }
1105                   //f.Printf("      incref this;\n");
1106                   for(param = method.dataType.params.first; param; param = param.next)
1107                   {
1108                      char type[1024] = "";
1109                      char className[1024];
1110                      Symbol classSym;
1111
1112                      if(param.kind == classType)
1113                         classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1114                      else
1115                      {
1116                         PrintType(param, type, false, true);
1117                         classSym = FindClass(type);
1118                         type[0] = 0;
1119                      }
1120                      strcpy(className, "__ecereClass_");
1121                      FullClassNameCat(className, classSym.string, true);
1122
1123                      MangleClassName(className);
1124                      DeclareClass(classSym, className);
1125
1126                      if(param.kind == classType && !strcmp(param._class.string, "String"))
1127                      {
1128                         DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1129                         f.Printf("      __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
1130                      }
1131                      else
1132                         f.Printf("      __ecereBuffer.Serialize(%s);\n", param.name);
1133                   }
1134                   DeclareMethod(
1135                      eClass_FindMethod(
1136                         eSystem_FindClass(privateModule, "ecere::net::DCOMClientObject"), "CallMethod", privateModule), 
1137                      "__ecereMethod___ecereNameSpace__ecere__net__DCOMClientObject_CallMethod");
1138
1139                   f.Printf("      if(DCOMClientObject::CallMethod(%d))\n", id++);
1140                   f.Printf("      {\n");
1141                   for(param = method.dataType.params.first; param; param = param.next)
1142                   {
1143                      if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1144                      {
1145                         if(!strcmp(param._class.string, "String"))
1146                         {
1147                            DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1148                            f.Printf("         __ecereBuffer.Unserialize((StaticString)%s);\n", param.name);
1149                         }
1150                         else
1151                            f.Printf("         __ecereBuffer.Unserialize(%s);\n", param.name);
1152                      }
1153                   }
1154                   if(method.dataType.returnType.kind != voidType)
1155                   {
1156                      if(method.dataType.returnType.kind == classType && !strcmp(method.dataType.returnType._class.string, "String"))
1157                      {
1158                         DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1159                         f.Printf("         __ecereBuffer.Unserialize((StaticString)__ecereResult);\n");
1160                      }
1161                      else
1162                         f.Printf("         __ecereBuffer.Unserialize(__ecereResult);\n");
1163                   }
1164                   f.Printf("      }\n");
1165                   f.Printf("      __ecereBuffer.Free();\n");
1166                   //f.Printf("      delete this;\n");
1167                   if(method.dataType.returnType.kind != voidType)
1168                   {
1169                      f.Printf("      return __ecereResult;\n");
1170                   }
1171                }
1172
1173                f.Printf("   }\n");
1174             }
1175             next = (Method)((BTNode)method).next;
1176             while(next && ((next.type == virtualMethod) != doVirtual || (doVirtual && next.vid != vid)))
1177             {
1178                id++;
1179                next = (Method)((BTNode)next).next;
1180                if(!next && doVirtual)
1181                {
1182                   if(vid == _class.vTblSize)
1183                      doVirtual = false;
1184                   else
1185                      vid++;
1186                   id = 0;
1187                   next = (Method)_class.methods.first;
1188                }
1189             }
1190             
1191             if(next) 
1192                f.Printf("\n");
1193          }
1194
1195          f.Printf("}\n");
1196          if(deriv.next) 
1197             f.Printf("\n");
1198       }
1199    }
1200 }
1201
1202 static void BindDCOMServer()
1203 {
1204    Class _class;
1205    for(_class = privateModule.classes.first; _class; _class = _class.next)
1206    {
1207       if(_class.isRemote == 3) //)
1208          break;
1209    }
1210
1211    if(_class)
1212    {
1213       File f;
1214       if(!dcomSymbols) dcomSymbols = TempFile { };
1215       f = dcomSymbols;
1216
1217       DeclareClass(FindClass("ecere::net::DCOMServerObject"), "__ecereClass___ecereNameSpace__ecere__net__DCOMServerObject");
1218
1219       // SERVER BINDINGS
1220       for(_class = privateModule.classes.first; _class; _class = _class.next)
1221       {
1222          if(_class.isRemote == 3) //2 && !strncmp(_class.fullName, "DCOMServer_", strlen("DCOMServer_")))
1223          {
1224             Method method;
1225             int id = 0;
1226             int vid;
1227
1228             f.Printf("class DCOM%s : ecere::net::DCOMServerObject\n", _class.fullName);
1229             // f.Printf("class DCOM%s\n", _class.fullName);
1230             f.Printf("{\n");
1231             /*
1232             f.Printf("   %s instance;\n", _class.fullName);
1233             f.Printf("   unsigned int id;\n");
1234             f.Printf("   SerialBuffer buffer { };\n");
1235             */
1236
1237             /*
1238             f.Printf("   DCOM%s()\n", _class.fullName);
1239             f.Printf("   {\n");
1240             f.Printf("      instance = eInstance_New(class(%s));\n", _class.fullName);
1241             f.Printf("   }\n");
1242             */
1243             // f.Printf("\n");
1244             f.Printf("   virtual void CallMethod(uint __ecereMethodID, SerialBuffer __ecereBuffer)\n");
1245             f.Printf("   {\n");
1246             f.Printf("      switch(__ecereMethodID)\n");
1247             f.Printf("      {\n");
1248
1249             for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
1250             {
1251                Type param;
1252                method.dataType = ProcessTypeString(method.dataTypeString, false);
1253                if(method.dataType && method.dataType.name)
1254                {
1255                   f.Printf("         case %d:\n", id++);
1256                   f.Printf("         {\n");
1257
1258                   {
1259                      if(method.dataType.returnType.kind != voidType)
1260                      {
1261                         TypeName resultType;
1262                         OldList * specs = MkList();
1263                         Declarator decl;
1264                         char type[1024] = "";
1265                         char className[1024];
1266                         Symbol classSym;
1267
1268                         if(method.dataType.returnType.kind == classType)
1269                            classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1270                         else
1271                         {
1272                            PrintType(method.dataType.returnType, type, false, true);
1273                            classSym = FindClass(type);
1274                            type[0] = 0;
1275                         }
1276                         strcpy(className, "__ecereClass_");
1277                         FullClassNameCat(className, classSym.string, true);
1278                         MangleClassName(className);
1279                         DeclareClass(classSym, className);
1280
1281                         PrintType(method.dataType.returnType, type, true, true);
1282
1283                         decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1284                         resultType = MkTypeName(specs, decl);
1285
1286                         f.Printf("            ");
1287                         OutputTypeName(resultType, f);
1288                         f.Printf(";\n");
1289                      }
1290
1291                      for(param = method.dataType.params.first; param; param = param.next)
1292                      {
1293                         if(param.kind == classType && !strcmp(param._class.string, "String"))
1294                         {
1295                            // Hardcode 1024 chars max string for now
1296                            f.Printf("            char %s[1024];\n", param.name);
1297                            DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1298                            DeclareClass(FindClass("String"), "__ecereClass_String");
1299                         }
1300                         else
1301                         {
1302                            TypeName paramTypeName;
1303                            OldList * specs = MkList();
1304                            Declarator decl;
1305                            char type[1024] = "";
1306                            char className[1024];
1307                            Symbol classSym;
1308
1309                            if(param.kind == classType)
1310                               classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1311                            else
1312                            {
1313                               PrintType(param, type, false, true);
1314                               classSym = FindClass(type);
1315                               type[0] = 0;
1316                            }
1317
1318                            strcpy(className, "__ecereClass_");
1319                            FullClassNameCat(className, classSym.string, true);
1320                            MangleClassName(className);
1321                            DeclareClass(classSym, className);
1322
1323                            PrintType(param, type, true, true);
1324
1325                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier(param.name /*"__ecereResult"*/)));
1326                            paramTypeName = MkTypeName(specs, decl);
1327
1328                            f.Printf("            ");
1329                            OutputTypeName(paramTypeName, f);
1330
1331                            f.Printf(";\n");
1332                         }
1333                      }
1334                      f.Printf("\n");
1335
1336                      for(param = method.dataType.params.first; param; param = param.next)
1337                      {
1338                         f.Printf("            __ecereBuffer.Unserialize(");
1339                         if(param.kind == classType && !strcmp(param._class.string, "String"))
1340                         {
1341                            DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1342                            f.Printf("(StaticString)");
1343                         }
1344                         f.Puts(param.name);
1345                         f.Printf(");\n");
1346                      }
1347
1348                      f.Printf("            ");
1349                      if(method.dataType.returnType.kind != voidType)
1350                         f.Printf("__ecereResult = ");
1351
1352                      // f.Printf("this.instance.%s(", method.name);
1353                      f.Printf("((%s)instance).%s(", _class.fullName, method.name);
1354                      
1355                      for(param = method.dataType.params.first; param; param = param.next)
1356                      {
1357                         if(param.prev)
1358                            f.Printf(", ");
1359                         f.Printf("%s", param.name);
1360                      }
1361
1362                      f.Printf(");\n");
1363
1364                      for(param = method.dataType.params.first; param; param = param.next)
1365                      {
1366                         if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1367                         {
1368                            if(!strcmp(param._class.string, "String"))
1369                            {
1370                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1371                               f.Printf("            __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
1372                            }
1373                            else
1374                               f.Printf("            __ecereBuffer.Serialize(%s);\n", param.name);
1375                         }
1376                      }
1377                      if(method.dataType.returnType.kind != voidType)
1378                      {
1379                         f.Printf("            __ecereBuffer.Serialize(__ecereResult);\n");
1380                      }
1381
1382                      for(param = method.dataType.params.first; param; param = param.next)
1383                      {
1384                         if(param.kind == classType && strcmp(param._class.string, "String") && param._class.registered && 
1385                            (param._class.registered.type == normalClass || param._class.registered.type == noHeadClass))
1386                         {
1387                            f.Printf("            delete %s;\n", param.name);
1388                         }
1389                      }
1390                      if(method.dataType.returnType.kind == classType && strcmp(method.dataType.returnType._class.string, "String") && method.dataType.returnType._class.registered && 
1391                            (method.dataType.returnType._class.registered.type == normalClass || method.dataType.returnType._class.registered.type == noHeadClass))
1392                      {
1393                         f.Printf("            delete __ecereResult;\n");
1394                      }
1395                   }
1396
1397                   f.Printf("            break;\n");
1398                   f.Printf("         }\n");
1399                }
1400             }
1401             f.Printf("      }\n");
1402             f.Printf("   }\n");
1403
1404             // *** VIRTUAL FUNCTIONS BINDINGS ***
1405             for(vid = _class.base.vTblSize; vid < _class.vTblSize; vid++)
1406             {
1407                Method method;
1408                Type param;
1409
1410                for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
1411                   if(method.type == virtualMethod && method._class == _class && method.vid == vid)
1412                      break;
1413                if(method)
1414                {
1415                   f.Printf("\n");
1416                   if(!method.dataType)
1417                      method.dataType = ProcessTypeString(method.dataTypeString, false);
1418
1419                   if(method.dataType.name)
1420                   {
1421                      f.Printf("   virtual %s\n", method.dataTypeString);
1422                      f.Printf("   {\n");
1423
1424                      if(method.dataType)
1425                      {
1426                         f.Printf("      DCOM%s __ecereObject = (void *)_vTbl[-1];\n", _class.fullName);
1427                         if(method.dataType.returnType.kind != voidType)
1428                         {
1429                            TypeName resultType;
1430                            OldList * specs = MkList();
1431                            Declarator decl;
1432                            char type[1024] = "";
1433                            char className[1024];
1434                            Symbol classSym;
1435
1436                            if(method.dataType.returnType.kind == classType)
1437                               classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1438                            else
1439                            {
1440                               PrintType(method.dataType.returnType, type, false, true);
1441                               classSym = FindClass(type);
1442                               type[0] = 0;
1443                            }
1444
1445                            strcpy(className, "__ecereClass_");
1446                            FullClassNameCat(className, classSym.string, true);
1447                            MangleClassName(className);
1448                            DeclareClass(classSym, className);
1449
1450                            PrintType(method.dataType.returnType, type, true, true);
1451
1452                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1453                            resultType = MkTypeName(specs, decl);
1454
1455                            f.Printf("      ");
1456                            OutputTypeName(resultType, f);
1457                            if(method.dataType.returnType.kind == structType)
1458                               f.Printf(" = { 0 }");
1459                            else if(method.dataType.returnType.kind == classType && method.dataType.returnType._class.registered && method.dataType.returnType._class.registered.type == structClass)
1460                               f.Printf(" { }");
1461                            else
1462                               f.Printf(" = 0");
1463                            f.Printf(";\n\n");
1464                         }
1465                         //f.Printf("      incref this;\n");
1466                         for(param = method.dataType.params.first; param; param = param.next)
1467                         {
1468                            char type[1024] = "";
1469                            char className[1024];
1470                            Symbol classSym;
1471
1472                            if(param.kind == classType)
1473                               classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1474                            else
1475                            {
1476                               PrintType(param, type, false, true);
1477                               classSym = FindClass(type);
1478                               type[0] = 0;
1479                            }
1480                            strcpy(className, "__ecereClass_");
1481                            FullClassNameCat(className, classSym.string, true);
1482                            MangleClassName(className);
1483                            DeclareClass(classSym, className);
1484
1485                            if(param.kind == classType && !strcmp(param._class.string, "String"))
1486                            {
1487                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1488                               f.Printf("      __ecereObject.virtualsBuffer.Serialize((StaticString)%s);\n", param.name);
1489                            }
1490                            else
1491                               f.Printf("      __ecereObject.virtualsBuffer.Serialize(%s);\n", param.name);
1492                         }
1493
1494                         DeclareMethod(
1495                            eClass_FindMethod(
1496                               eSystem_FindClass(privateModule, "ecere::net::DCOMServerObject"), "CallVirtualMethod", privateModule), 
1497                            "__ecereMethod___ecereNameSpace__ecere__net__DCOMServerObject_CallVirutalMethod");
1498
1499                         f.Printf("      if(__ecereObject.CallVirtualMethod(%d))\n", vid - _class.base.vTblSize);
1500                         f.Printf("      {\n");
1501                         for(param = method.dataType.params.first; param; param = param.next)
1502                         {
1503                            if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1504                            {
1505                               if(!strcmp(param._class.string, "String"))
1506                               {
1507                                  DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1508                                  f.Printf("         __ecereObject.virtualsBuffer.Unserialize((StaticString)%s);\n", param.name);
1509                               }
1510                               else
1511                                  f.Printf("         __ecereObject.virtualsBuffer.Unserialize(%s);\n", param.name);
1512                            }
1513                         }
1514                         if(method.dataType.returnType.kind != voidType)
1515                         {
1516                            if(method.dataType.returnType.kind == classType && !strcmp(method.dataType.returnType._class.string, "String"))
1517                            {
1518                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1519                               f.Printf("         __ecereObject.virtualsBuffer.Unserialize((StaticString)__ecereResult);\n");
1520                            }
1521                            else
1522                               f.Printf("         __ecereObject.virtualsBuffer.Unserialize(__ecereResult);\n");
1523                         }
1524                         f.Printf("      }\n");
1525                         f.Printf("      else\n");
1526                         f.Printf("         ((%s)this).%s::%s(", _class.fullName, _class.fullName, method.name);
1527                         for(param = method.dataType.params.first; param; param = param.next)
1528                         {
1529                            f.Printf("%s", param.name);
1530                            if(param.next) f.Printf(", ");
1531                         }
1532                         f.Printf(");\n");
1533
1534                         f.Printf("      __ecereObject.virtualsBuffer.Free();\n");
1535                         //f.Printf("      delete this;\n");
1536                         if(method.dataType.returnType.kind != voidType)
1537                         {
1538                            f.Printf("      return __ecereResult;\n");
1539                         }
1540                      }
1541
1542                      f.Printf("   }\n");
1543                      /*if(vid < _class.vTblSize) 
1544                         f.Printf("\n");*/
1545                   }
1546                }
1547             }
1548             f.Printf("}\n");
1549          }
1550       }
1551    }
1552 }
1553
1554 class SymbolgenApp : Application
1555 {
1556    void Main()
1557    {
1558       /*
1559       char ** argv = null;
1560       int argc = 0;
1561       */
1562       int c;
1563       bool valid = true;
1564       char * output = null;
1565
1566       targetPlatform = GetRuntimePlatform();
1567
1568       /*
1569       for(c = 0; c<this.argc; c++)
1570       {
1571          char * arg = this.argv[c];
1572          int argLen = strlen(arg);
1573
1574          argv = renew argv char *[argc + 1];
1575          argv[argc] = new char[argLen+1];
1576          strcpy(argv[argc], arg);
1577
1578          while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
1579          {
1580             int len;
1581
1582             c++;
1583             arg = this.argv[c];
1584             len = strlen(arg);
1585             argv[argc] = renew argv[argc] char[argLen + len + 1];
1586
1587             argv[argc][argLen-1] = ' ';
1588             strcpy(argv[argc] + argLen, arg);
1589             argLen += len;
1590          }
1591          argc++;
1592       }
1593       */
1594
1595       for(c = 1; c<argc; c++)
1596       {
1597          char * arg = argv[c];
1598          if(arg[0] == '-')
1599          {
1600             if(!strcmp(arg+1, "o"))
1601             {
1602                if(!output && c + 1 < argc)
1603                {
1604                   output = argv[c+1];
1605                   c++;
1606                }
1607                else
1608                   valid = false;
1609             }
1610             else if(!strcmp(arg, "-name"))
1611             {
1612                if(c + 1 < argc)
1613                {
1614                   strcpy(projectName, argv[c+1]);
1615                   c++;
1616                }
1617                else
1618                   valid = false;
1619             }
1620             else if(!strcmp(arg, "-t"))
1621             {
1622                if(++c < argc)
1623                   targetPlatform = argv[c];
1624                else
1625                   valid = false;
1626             }
1627             else if(!strcmp(arg, "-console"))
1628                isConsole = true;
1629             else if(!strcmp(arg, "-dynamiclib"))
1630                isDynamicLibrary = true;
1631             else if(!strcmp(arg, "-staticlib"))
1632             {
1633                isDynamicLibrary = true;   // TOFIX: unmixup
1634                isStaticLibrary = true;
1635             }
1636             else if(!strcmp(arg, "-symbols"))
1637             {
1638                if(c + 1 < argc)
1639                {
1640                   SetSymbolsDir(argv[c+1]);
1641                   c++;
1642                }
1643                else
1644                   valid = false;
1645             }
1646          }
1647       }
1648       if(!output)
1649          valid = false;
1650      
1651       if(!valid)
1652          printf("Syntax:\n   ecs [-t <target platform>] <input>[, <input>]* -o <output>\n");
1653       else
1654       {
1655          int c;
1656          char ext[MAX_EXTENSION];
1657          char symbolModule[MAX_FILENAME];
1658          GetExtension(output, ext);
1659          GetLastDirectory(output, symbolModule);
1660          
1661          SetDefines(&::_defines);
1662          SetImports(&_imports);
1663          SetGlobalData(&globalData);
1664          SetExcludedSymbols(&_excludedSymbols);
1665          SetGlobalContext(theGlobalContext);
1666          SetTopContext(theGlobalContext);
1667          SetCurrentContext(theGlobalContext);
1668          SetTargetPlatform(targetPlatform);
1669
1670          privateModule = __ecere_COM_Initialize(true, 1, null);
1671          SetPrivateModule(privateModule);
1672          mainModule = ModuleImport { };
1673          SetMainModule(mainModule);
1674          _imports.Add(mainModule);
1675
1676          //if(!strcmp(ext, "c"))
1677          {
1678             File potFile = null;
1679             Map<String, String> intlStrings { };
1680             MapIterator<String, String> it { map = intlStrings };
1681
1682             for(c = 1; c<argc; c++)
1683             {
1684                char * file = argv[c];
1685                if(file[0] == '-')
1686                {
1687                   if(!strcmp(file, "-c"))
1688                      c++;
1689                }
1690                else
1691                {
1692                   char ext[MAX_EXTENSION];
1693                   GetExtension(file,ext);
1694                   if(!strcmp(ext, "imp"))
1695                      LoadImports(file);
1696                }
1697             }
1698
1699             // What is this supposed to do?
1700             for(c = 1; c<argc; c++)
1701             {
1702                char * file = argv[c];
1703                if(file[0] == '-')
1704                {
1705                   if(!strcmp(file, "-c"))
1706                      c++;
1707                }
1708             }
1709
1710             for(c = 1; c<argc; c++)
1711             {
1712                char * file = argv[c];
1713                if(file[0] == '-')
1714                {
1715                   // Don't even know what it does here?
1716                   if(!strcmp(file, "-c"))
1717                      c++;
1718                }
1719                else
1720                {
1721                   char ext[MAX_EXTENSION];
1722                   char moduleName[MAX_LOCATION];
1723
1724                   GetExtension(file,ext);
1725
1726                   GetLastDirectory(file, moduleName);
1727                   StripExtension(moduleName);
1728                   strcat(moduleName, ".ec");
1729
1730                   if(fstrcmp(moduleName, symbolModule) && (!strcmp(ext, "sym") || !strcmp(ext, "ec")))
1731                   {
1732                      ImportedModule importedModule;
1733                      ModuleInfo module { };
1734                      char fileName[MAX_FILENAME];
1735                      ::modules.Add(module);
1736
1737                      GetLastDirectory(file, fileName);
1738
1739                      module.name = CopyString(fileName);
1740                      
1741                      StripExtension(module.name);                     
1742
1743                      for(importedModule = ::_defines.first; importedModule; importedModule = importedModule.next)
1744                      {
1745                         if(importedModule.type == moduleDefinition && !strcmpi(importedModule.name, module.name) && !(importedModule.importType == remoteImport))
1746                            break;
1747                      }
1748
1749                      if(importedModule)
1750                         module.globalInstance = importedModule.globalInstance;
1751                      else
1752                      {
1753                         importedModule = ImportedModule
1754                         {
1755                            name = CopyString(module.name),
1756                            type = moduleDefinition,
1757                            importType = normalImport
1758                         };
1759                         ::_defines.AddName(importedModule);
1760
1761                         module.globalInstance = LoadSymbols(file, normalImport, false);
1762                         CheckDataRedefinitions();
1763                      }
1764
1765                      // I18n code
1766                      {
1767                         File f;
1768                         ChangeExtension(file, "bowl", fileName);
1769                         f = FileOpen(fileName, read);
1770                         if(f)
1771                         {
1772                            if(!potFile)
1773                            {
1774                               char potFileName[MAX_LOCATION];
1775                               strcpy(potFileName, output);
1776                               StripExtension(potFileName);
1777                               ChangeExtension(potFileName, "pot", potFileName);
1778                               potFile = FileOpen(potFileName, write);
1779                            }
1780                            potFile.Printf("# %s\n", moduleName);
1781                            while(!f.Eof())
1782                            {
1783                               String comment = null, msgid = null, msgstr = null;
1784                               int c;
1785                               for(c = 0; c < 4; c++)
1786                               {
1787                                  static char line[65536];
1788                                  if(f.GetLine(line, sizeof(line)))
1789                                  {
1790                                     if(c == 0) comment = CopyString(line);
1791                                     else if(c == 1) msgid = CopyString(line);
1792                                     else if(c == 2) msgstr = CopyString(line);
1793                                  }
1794                               }
1795                               if(msgid && !it.Index(msgid, false))
1796                               {
1797                                  i18n = true;
1798                                  intlStrings[msgid] = comment;
1799                                  potFile.Puts(comment); potFile.Puts("\n");
1800                                  potFile.Puts(msgid); potFile.Puts("\n");
1801                                  potFile.Puts(msgstr); potFile.Puts("\n");
1802                                  potFile.Puts("\n");
1803                                  delete msgstr;
1804                                  // delete comment;
1805                               }
1806                            }
1807                            delete f;
1808                            potFile.Puts("\n");
1809                         }
1810                      }
1811                   }
1812                }
1813             }
1814
1815             ComputeModuleClasses(privateModule);
1816
1817             if(!isDynamicLibrary)
1818             {
1819                // applicationClass = eSystem_FindClass(privateModule, "Application");
1820                /*
1821                thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, true);
1822                if(!thisAppClass)
1823                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, true);
1824                if(!thisAppClass)
1825                   thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, false);
1826                if(!thisAppClass)
1827                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, false);
1828                */
1829                thisAppClass = SearchAppClass_Module(privateModule);
1830             }
1831             WriteMain(output);
1832
1833             intlStrings.Free();
1834             delete intlStrings;
1835             if(potFile)
1836                delete potFile;
1837          }
1838
1839          FreeContext(theGlobalContext);
1840          FreeExcludedSymbols(_excludedSymbols);
1841
1842          ::_defines.Free(FreeModuleDefine);
1843          _imports.Free(FreeModuleImport);
1844
1845          //precompDefines.Free(FreeDefinition);   
1846
1847          FreeTypeData(privateModule);
1848          FreeIncludeFiles();
1849          FreeGlobalData(globalData);
1850
1851          delete privateModule;
1852       }
1853
1854       SetSymbolsDir(null); // Free symbols dir
1855
1856       /*
1857       for(c = 0; c<argc; c++)
1858          delete argv[c];
1859       delete argv;
1860       */
1861
1862 #ifdef _DEBUG
1863       getch();
1864 #endif
1865    }
1866 }