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