ecere: Fixed up i18n Support; Started Chinese translation integration
[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    Class _class;
1217    for(_class = privateModule.classes.first; _class; _class = _class.next)
1218    {
1219       if(_class.isRemote == 3) //)
1220          break;
1221    }
1222
1223    if(_class)
1224    {
1225       File f;
1226       if(!dcomSymbols) dcomSymbols = TempFile { };
1227       f = dcomSymbols;
1228
1229       DeclareClass(FindClass("ecere::net::DCOMServerObject"), "__ecereClass___ecereNameSpace__ecere__net__DCOMServerObject");
1230
1231       // SERVER BINDINGS
1232       for(_class = privateModule.classes.first; _class; _class = _class.next)
1233       {
1234          if(_class.isRemote == 3) //2 && !strncmp(_class.fullName, "DCOMServer_", strlen("DCOMServer_")))
1235          {
1236             Method method;
1237             int id = 0;
1238             int vid;
1239
1240             f.Printf("class DCOM%s : ecere::net::DCOMServerObject\n", _class.fullName);
1241             // f.Printf("class DCOM%s\n", _class.fullName);
1242             f.Printf("{\n");
1243             /*
1244             f.Printf("   %s instance;\n", _class.fullName);
1245             f.Printf("   unsigned int id;\n");
1246             f.Printf("   SerialBuffer buffer { };\n");
1247             */
1248
1249             /*
1250             f.Printf("   DCOM%s()\n", _class.fullName);
1251             f.Printf("   {\n");
1252             f.Printf("      instance = eInstance_New(class(%s));\n", _class.fullName);
1253             f.Printf("   }\n");
1254             */
1255             // f.Printf("\n");
1256             f.Printf("   virtual void CallMethod(uint __ecereMethodID, SerialBuffer __ecereBuffer)\n");
1257             f.Printf("   {\n");
1258             f.Printf("      switch(__ecereMethodID)\n");
1259             f.Printf("      {\n");
1260
1261             for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
1262             {
1263                Type param;
1264                method.dataType = ProcessTypeString(method.dataTypeString, false);
1265                if(method.dataType && method.dataType.name)
1266                {
1267                   f.Printf("         case %d:\n", id++);
1268                   f.Printf("         {\n");
1269
1270                   {
1271                      if(method.dataType.returnType.kind != voidType)
1272                      {
1273                         TypeName resultType;
1274                         OldList * specs = MkList();
1275                         Declarator decl;
1276                         char type[1024] = "";
1277                         char className[1024];
1278                         Symbol classSym;
1279
1280                         if(method.dataType.returnType.kind == classType)
1281                            classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1282                         else
1283                         {
1284                            PrintType(method.dataType.returnType, type, false, true);
1285                            classSym = FindClass(type);
1286                            type[0] = 0;
1287                         }
1288                         strcpy(className, "__ecereClass_");
1289                         FullClassNameCat(className, classSym.string, true);
1290                         MangleClassName(className);
1291                         DeclareClass(classSym, className);
1292
1293                         PrintType(method.dataType.returnType, type, true, true);
1294
1295                         decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1296                         resultType = MkTypeName(specs, decl);
1297
1298                         f.Printf("            ");
1299                         OutputTypeName(resultType, f);
1300                         f.Printf(";\n");
1301                      }
1302
1303                      for(param = method.dataType.params.first; param; param = param.next)
1304                      {
1305                         if(param.kind == classType && !strcmp(param._class.string, "String"))
1306                         {
1307                            // Hardcode 1024 chars max string for now
1308                            f.Printf("            char %s[1024];\n", param.name);
1309                            DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1310                            DeclareClass(FindClass("String"), "__ecereClass_String");
1311                         }
1312                         else
1313                         {
1314                            TypeName paramTypeName;
1315                            OldList * specs = MkList();
1316                            Declarator decl;
1317                            char type[1024] = "";
1318                            char className[1024];
1319                            Symbol classSym;
1320
1321                            if(param.kind == classType)
1322                               classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1323                            else
1324                            {
1325                               PrintType(param, type, false, true);
1326                               classSym = FindClass(type);
1327                               type[0] = 0;
1328                            }
1329
1330                            strcpy(className, "__ecereClass_");
1331                            FullClassNameCat(className, classSym.string, true);
1332                            MangleClassName(className);
1333                            DeclareClass(classSym, className);
1334
1335                            PrintType(param, type, true, true);
1336
1337                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier(param.name /*"__ecereResult"*/)));
1338                            paramTypeName = MkTypeName(specs, decl);
1339
1340                            f.Printf("            ");
1341                            OutputTypeName(paramTypeName, f);
1342
1343                            f.Printf(";\n");
1344                         }
1345                      }
1346                      f.Printf("\n");
1347
1348                      for(param = method.dataType.params.first; param; param = param.next)
1349                      {
1350                         f.Printf("            __ecereBuffer.Unserialize(");
1351                         if(param.kind == classType && !strcmp(param._class.string, "String"))
1352                         {
1353                            DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1354                            f.Printf("(StaticString)");
1355                         }
1356                         f.Puts(param.name);
1357                         f.Printf(");\n");
1358                      }
1359
1360                      f.Printf("            ");
1361                      if(method.dataType.returnType.kind != voidType)
1362                         f.Printf("__ecereResult = ");
1363
1364                      // f.Printf("this.instance.%s(", method.name);
1365                      f.Printf("((%s)instance).%s(", _class.fullName, method.name);
1366                      
1367                      for(param = method.dataType.params.first; param; param = param.next)
1368                      {
1369                         if(param.prev)
1370                            f.Printf(", ");
1371                         f.Printf("%s", param.name);
1372                      }
1373
1374                      f.Printf(");\n");
1375
1376                      for(param = method.dataType.params.first; param; param = param.next)
1377                      {
1378                         if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1379                         {
1380                            if(!strcmp(param._class.string, "String"))
1381                            {
1382                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1383                               f.Printf("            __ecereBuffer.Serialize((StaticString)%s);\n", param.name);
1384                            }
1385                            else
1386                               f.Printf("            __ecereBuffer.Serialize(%s);\n", param.name);
1387                         }
1388                      }
1389                      if(method.dataType.returnType.kind != voidType)
1390                      {
1391                         f.Printf("            __ecereBuffer.Serialize(__ecereResult);\n");
1392                      }
1393
1394                      for(param = method.dataType.params.first; param; param = param.next)
1395                      {
1396                         if(param.kind == classType && strcmp(param._class.string, "String") && param._class.registered && 
1397                            (param._class.registered.type == normalClass || param._class.registered.type == noHeadClass))
1398                         {
1399                            f.Printf("            delete %s;\n", param.name);
1400                         }
1401                      }
1402                      if(method.dataType.returnType.kind == classType && strcmp(method.dataType.returnType._class.string, "String") && method.dataType.returnType._class.registered && 
1403                            (method.dataType.returnType._class.registered.type == normalClass || method.dataType.returnType._class.registered.type == noHeadClass))
1404                      {
1405                         f.Printf("            delete __ecereResult;\n");
1406                      }
1407                   }
1408
1409                   f.Printf("            break;\n");
1410                   f.Printf("         }\n");
1411                }
1412             }
1413             f.Printf("      }\n");
1414             f.Printf("   }\n");
1415
1416             // *** VIRTUAL FUNCTIONS BINDINGS ***
1417             for(vid = _class.base.vTblSize; vid < _class.vTblSize; vid++)
1418             {
1419                Method method;
1420                Type param;
1421
1422                for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
1423                   if(method.type == virtualMethod && method._class == _class && method.vid == vid)
1424                      break;
1425                if(method)
1426                {
1427                   f.Printf("\n");
1428                   if(!method.dataType)
1429                      method.dataType = ProcessTypeString(method.dataTypeString, false);
1430
1431                   if(method.dataType.name)
1432                   {
1433                      f.Printf("   virtual %s\n", method.dataTypeString);
1434                      f.Printf("   {\n");
1435
1436                      if(method.dataType)
1437                      {
1438                         f.Printf("      DCOM%s __ecereObject = (void *)_vTbl[-1];\n", _class.fullName);
1439                         if(method.dataType.returnType.kind != voidType)
1440                         {
1441                            TypeName resultType;
1442                            OldList * specs = MkList();
1443                            Declarator decl;
1444                            char type[1024] = "";
1445                            char className[1024];
1446                            Symbol classSym;
1447
1448                            if(method.dataType.returnType.kind == classType)
1449                               classSym = method.dataType.returnType._class; // VERIFY THIS FindClass(method.dataType.returnType._class.string);
1450                            else
1451                            {
1452                               PrintType(method.dataType.returnType, type, false, true);
1453                               classSym = FindClass(type);
1454                               type[0] = 0;
1455                            }
1456
1457                            strcpy(className, "__ecereClass_");
1458                            FullClassNameCat(className, classSym.string, true);
1459                            MangleClassName(className);
1460                            DeclareClass(classSym, className);
1461
1462                            PrintType(method.dataType.returnType, type, true, true);
1463
1464                            decl = SpecDeclFromString(type, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereResult")));
1465                            resultType = MkTypeName(specs, decl);
1466
1467                            f.Printf("      ");
1468                            OutputTypeName(resultType, f);
1469                            if(method.dataType.returnType.kind == structType)
1470                               f.Printf(" = { 0 }");
1471                            else if(method.dataType.returnType.kind == classType && method.dataType.returnType._class.registered && method.dataType.returnType._class.registered.type == structClass)
1472                               f.Printf(" { }");
1473                            else
1474                               f.Printf(" = 0");
1475                            f.Printf(";\n\n");
1476                         }
1477                         //f.Printf("      incref this;\n");
1478                         for(param = method.dataType.params.first; param; param = param.next)
1479                         {
1480                            char type[1024] = "";
1481                            char className[1024];
1482                            Symbol classSym;
1483
1484                            if(param.kind == classType)
1485                               classSym = param._class; // VERIFY THIS FindClass(param._class.string);
1486                            else
1487                            {
1488                               PrintType(param, type, false, true);
1489                               classSym = FindClass(type);
1490                               type[0] = 0;
1491                            }
1492                            strcpy(className, "__ecereClass_");
1493                            FullClassNameCat(className, classSym.string, true);
1494                            MangleClassName(className);
1495                            DeclareClass(classSym, className);
1496
1497                            if(param.kind == classType && !strcmp(param._class.string, "String"))
1498                            {
1499                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1500                               f.Printf("      __ecereObject.virtualsBuffer.Serialize((StaticString)%s);\n", param.name);
1501                            }
1502                            else
1503                               f.Printf("      __ecereObject.virtualsBuffer.Serialize(%s);\n", param.name);
1504                         }
1505
1506                         DeclareMethod(
1507                            eClass_FindMethod(
1508                               eSystem_FindClass(privateModule, "ecere::net::DCOMServerObject"), "CallVirtualMethod", privateModule), 
1509                            "__ecereMethod___ecereNameSpace__ecere__net__DCOMServerObject_CallVirutalMethod");
1510
1511                         f.Printf("      if(__ecereObject.CallVirtualMethod(%d))\n", vid - _class.base.vTblSize);
1512                         f.Printf("      {\n");
1513                         for(param = method.dataType.params.first; param; param = param.next)
1514                         {
1515                            if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
1516                            {
1517                               if(!strcmp(param._class.string, "String"))
1518                               {
1519                                  DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1520                                  f.Printf("         __ecereObject.virtualsBuffer.Unserialize((StaticString)%s);\n", param.name);
1521                               }
1522                               else
1523                                  f.Printf("         __ecereObject.virtualsBuffer.Unserialize(%s);\n", param.name);
1524                            }
1525                         }
1526                         if(method.dataType.returnType.kind != voidType)
1527                         {
1528                            if(method.dataType.returnType.kind == classType && !strcmp(method.dataType.returnType._class.string, "String"))
1529                            {
1530                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
1531                               f.Printf("         __ecereObject.virtualsBuffer.Unserialize((StaticString)__ecereResult);\n");
1532                            }
1533                            else
1534                               f.Printf("         __ecereObject.virtualsBuffer.Unserialize(__ecereResult);\n");
1535                         }
1536                         f.Printf("      }\n");
1537                         f.Printf("      else\n");
1538                         f.Printf("         ((%s)this).%s::%s(", _class.fullName, _class.fullName, method.name);
1539                         for(param = method.dataType.params.first; param; param = param.next)
1540                         {
1541                            f.Printf("%s", param.name);
1542                            if(param.next) f.Printf(", ");
1543                         }
1544                         f.Printf(");\n");
1545
1546                         f.Printf("      __ecereObject.virtualsBuffer.Free();\n");
1547                         //f.Printf("      delete this;\n");
1548                         if(method.dataType.returnType.kind != voidType)
1549                         {
1550                            f.Printf("      return __ecereResult;\n");
1551                         }
1552                      }
1553
1554                      f.Printf("   }\n");
1555                      /*if(vid < _class.vTblSize) 
1556                         f.Printf("\n");*/
1557                   }
1558                }
1559             }
1560             f.Printf("}\n");
1561          }
1562       }
1563    }
1564 }
1565
1566 class SymbolgenApp : Application
1567 {
1568    void Main()
1569    {
1570       /*
1571       char ** argv = null;
1572       int argc = 0;
1573       */
1574       int c;
1575       bool valid = true;
1576       char * output = null;
1577
1578       targetPlatform = GetRuntimePlatform();
1579
1580       /*
1581       for(c = 0; c<this.argc; c++)
1582       {
1583          char * arg = this.argv[c];
1584          int argLen = strlen(arg);
1585
1586          argv = renew argv char *[argc + 1];
1587          argv[argc] = new char[argLen+1];
1588          strcpy(argv[argc], arg);
1589
1590          while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
1591          {
1592             int len;
1593
1594             c++;
1595             arg = this.argv[c];
1596             len = strlen(arg);
1597             argv[argc] = renew argv[argc] char[argLen + len + 1];
1598
1599             argv[argc][argLen-1] = ' ';
1600             strcpy(argv[argc] + argLen, arg);
1601             argLen += len;
1602          }
1603          argc++;
1604       }
1605       */
1606
1607       for(c = 1; c<argc; c++)
1608       {
1609          char * arg = argv[c];
1610          if(arg[0] == '-')
1611          {
1612             if(!strcmp(arg+1, "o"))
1613             {
1614                if(!output && c + 1 < argc)
1615                {
1616                   output = argv[c+1];
1617                   c++;
1618                }
1619                else
1620                   valid = false;
1621             }
1622             else if(!strcmp(arg, "-name"))
1623             {
1624                if(c + 1 < argc)
1625                {
1626                   strcpy(projectName, argv[c+1]);
1627                   c++;
1628                }
1629                else
1630                   valid = false;
1631             }
1632             else if(!strcmp(arg, "-t"))
1633             {
1634                if(++c < argc)
1635                   targetPlatform = argv[c];
1636                else
1637                   valid = false;
1638             }
1639             else if(!strcmp(arg, "-console"))
1640                isConsole = true;
1641             else if(!strcmp(arg, "-dynamiclib"))
1642                isDynamicLibrary = true;
1643             else if(!strcmp(arg, "-staticlib"))
1644             {
1645                isDynamicLibrary = true;   // TOFIX: unmixup
1646                isStaticLibrary = true;
1647             }
1648             else if(!strcmp(arg, "-symbols"))
1649             {
1650                if(c + 1 < argc)
1651                {
1652                   SetSymbolsDir(argv[c+1]);
1653                   c++;
1654                }
1655                else
1656                   valid = false;
1657             }
1658          }
1659       }
1660       if(!output)
1661          valid = false;
1662      
1663       if(!valid)
1664          printf("Syntax:\n   ecs [-t <target platform>] <input>[, <input>]* -o <output>\n");
1665       else
1666       {
1667          int c;
1668          char ext[MAX_EXTENSION];
1669          char symbolModule[MAX_FILENAME];
1670          GetExtension(output, ext);
1671          GetLastDirectory(output, symbolModule);
1672          
1673          SetDefines(&::_defines);
1674          SetImports(&_imports);
1675          SetGlobalData(&globalData);
1676          SetExcludedSymbols(&_excludedSymbols);
1677          SetGlobalContext(theGlobalContext);
1678          SetTopContext(theGlobalContext);
1679          SetCurrentContext(theGlobalContext);
1680          SetTargetPlatform(targetPlatform);
1681
1682          privateModule = __ecere_COM_Initialize(true, 1, null);
1683          SetPrivateModule(privateModule);
1684          mainModule = ModuleImport { };
1685          SetMainModule(mainModule);
1686          _imports.Add(mainModule);
1687
1688          //if(!strcmp(ext, "c"))
1689          {
1690             File potFile = null;
1691             Map<String, String> intlStrings { };
1692             MapIterator<String, String> it { map = intlStrings };
1693
1694             for(c = 1; c<argc; c++)
1695             {
1696                char * file = argv[c];
1697                if(file[0] == '-')
1698                {
1699                   if(!strcmp(file, "-c"))
1700                      c++;
1701                }
1702                else
1703                {
1704                   char ext[MAX_EXTENSION];
1705                   GetExtension(file,ext);
1706                   if(!strcmp(ext, "imp"))
1707                      LoadImports(file);
1708                }
1709             }
1710
1711             // What is this supposed to do?
1712             for(c = 1; c<argc; c++)
1713             {
1714                char * file = argv[c];
1715                if(file[0] == '-')
1716                {
1717                   if(!strcmp(file, "-c"))
1718                      c++;
1719                }
1720             }
1721
1722             for(c = 1; c<argc; c++)
1723             {
1724                char * file = argv[c];
1725                if(file[0] == '-')
1726                {
1727                   // Don't even know what it does here?
1728                   if(!strcmp(file, "-c"))
1729                      c++;
1730                }
1731                else
1732                {
1733                   char ext[MAX_EXTENSION];
1734                   char moduleName[MAX_LOCATION];
1735
1736                   GetExtension(file,ext);
1737
1738                   GetLastDirectory(file, moduleName);
1739                   StripExtension(moduleName);
1740                   strcat(moduleName, ".ec");
1741
1742                   if(fstrcmp(moduleName, symbolModule) && (!strcmp(ext, "sym") || !strcmp(ext, "ec")))
1743                   {
1744                      ImportedModule importedModule;
1745                      ModuleInfo module { };
1746                      char fileName[MAX_FILENAME];
1747                      ::modules.Add(module);
1748
1749                      GetLastDirectory(file, fileName);
1750
1751                      module.name = CopyString(fileName);
1752                      
1753                      StripExtension(module.name);                     
1754
1755                      for(importedModule = ::_defines.first; importedModule; importedModule = importedModule.next)
1756                      {
1757                         if(importedModule.type == moduleDefinition && !strcmpi(importedModule.name, module.name) && !(importedModule.importType == remoteImport))
1758                            break;
1759                      }
1760
1761                      if(importedModule)
1762                         module.globalInstance = importedModule.globalInstance;
1763                      else
1764                      {
1765                         importedModule = ImportedModule
1766                         {
1767                            name = CopyString(module.name),
1768                            type = moduleDefinition,
1769                            importType = normalImport
1770                         };
1771                         ::_defines.AddName(importedModule);
1772
1773                         module.globalInstance = LoadSymbols(file, normalImport, false);
1774                         CheckDataRedefinitions();
1775                      }
1776
1777                      // I18n code
1778                      {
1779                         File f;
1780                         ChangeExtension(file, "bowl", fileName);
1781                         f = FileOpen(fileName, read);
1782                         if(f)
1783                         {
1784                            if(!potFile)
1785                            {
1786                               char potFileName[MAX_LOCATION];
1787                               strcpy(potFileName, output);
1788                               StripExtension(potFileName);
1789                               ChangeExtension(potFileName, "pot", potFileName);
1790                               potFile = FileOpen(potFileName, write);
1791                            }
1792                            potFile.Printf("# %s\n", moduleName);
1793                            while(!f.Eof())
1794                            {
1795                               String comment = null, msgid = null, msgstr = null;
1796                               int c;
1797                               for(c = 0; c < 4; c++)
1798                               {
1799                                  static char line[65536];
1800                                  if(f.GetLine(line, sizeof(line)))
1801                                  {
1802                                     if(c == 0) comment = CopyString(line);
1803                                     else if(c == 1) msgid = CopyString(line);
1804                                     else if(c == 2) msgstr = CopyString(line);
1805                                  }
1806                               }
1807                               if(msgid && !it.Index(msgid, false))
1808                               {
1809                                  i18n = true;
1810                                  intlStrings[msgid] = comment;
1811                                  potFile.Puts(comment); potFile.Puts("\n");
1812                                  potFile.Puts(msgid); potFile.Puts("\n");
1813                                  potFile.Puts(msgstr); potFile.Puts("\n");
1814                                  potFile.Puts("\n");
1815                                  delete msgstr;
1816                                  // delete comment;
1817                               }
1818                            }
1819                            delete f;
1820                            potFile.Puts("\n");
1821                         }
1822                      }
1823                   }
1824                }
1825             }
1826
1827             ComputeModuleClasses(privateModule);
1828
1829             if(!isDynamicLibrary)
1830             {
1831                // applicationClass = eSystem_FindClass(privateModule, "Application");
1832                /*
1833                thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, true);
1834                if(!thisAppClass)
1835                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, true);
1836                if(!thisAppClass)
1837                   thisAppClass = FindAppClass(&privateModule.application.publicNameSpace, false);
1838                if(!thisAppClass)
1839                   thisAppClass = FindAppClass(&privateModule.application.privateNameSpace, false);
1840                */
1841                thisAppClass = SearchAppClass_Module(privateModule);
1842             }
1843             WriteMain(output);
1844
1845             intlStrings.Free();
1846             delete intlStrings;
1847             if(potFile)
1848                delete potFile;
1849          }
1850
1851          FreeContext(theGlobalContext);
1852          FreeExcludedSymbols(_excludedSymbols);
1853
1854          ::_defines.Free(FreeModuleDefine);
1855          _imports.Free(FreeModuleImport);
1856
1857          //precompDefines.Free(FreeDefinition);   
1858
1859          FreeTypeData(privateModule);
1860          FreeIncludeFiles();
1861          FreeGlobalData(globalData);
1862
1863          delete privateModule;
1864       }
1865
1866       SetSymbolsDir(null); // Free symbols dir
1867
1868       /*
1869       for(c = 0; c<argc; c++)
1870          delete argv[c];
1871       delete argv;
1872       */
1873
1874 #ifdef _DEBUG
1875       getch();
1876 #endif
1877    }
1878 }