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