compiler: Added (u)intsize to map to size_t; Updated C prototypes to use it; Fixed...
[sdk] / compiler / ecc / ecc.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
10 //#include <stdarg.h>
11
12 static Context globalContext { };
13 static Module privateModule;
14 static ModuleImport mainModule;
15 static OldList _excludedSymbols { offset = (uint)&((Symbol)0).left }; 
16 static OldList defines, imports;
17 static NameSpace globalData
18 {
19    classes.CompareKey = (void *)BinaryTree::CompareString;
20    defines.CompareKey = (void *)BinaryTree::CompareString;
21    functions.CompareKey = (void *)BinaryTree::CompareString;
22    nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
23 };
24 static OldList _precompDefines;
25
26 static void OutputImports(char * fileName)
27 {
28    File f = FileOpen(fileName, write);
29    if(f)
30    {
31       if(imports.first)
32       {
33          ModuleImport module;
34          f.Printf("[Imported Modules]\n");
35          for(module = imports.first; module; module = module.next)
36          {
37             ClassImport _class;
38             FunctionImport function;
39
40             if(module.name)
41                f.Printf("   %s\n", module.name);
42             else
43                f.Printf("   [This]\n");
44             if(module.importType == staticImport)
45                f.Printf("      [Static]\n");
46             else if(module.importType == remoteImport)
47                f.Printf("      [Remote]\n");
48
49             if(module.importAccess == privateAccess)
50                f.Printf("      [Private]\n");
51             else
52                f.Printf("      [Public]\n");
53
54             if(module.classes.first)
55             {
56                f.Printf("      [Imported Classes]\n");
57                for(_class = module.classes.first; _class; _class = _class.next)
58                {
59                   f.Printf("         %s\n", _class.name);
60                   if(_class.itself)
61                   {
62                      f.Printf("            [Instantiated]\n");
63                   }
64                   if(_class.isRemote)
65                   {
66                      f.Printf("            [Remote]\n");
67                   }
68
69                   if(_class.methods.first)
70                   {
71                      MethodImport method;
72                      f.Printf("            [Imported Methods]\n");
73                      for(method = _class.methods.first; method; method = method.next)
74                      {
75                         f.Printf("               %s\n", method.name);
76                         if(method.isVirtual)
77                            f.Printf("                  [Virtual]\n");
78
79                      }
80                      f.Printf("               .\n");
81                   }
82
83                   if(_class.properties.first)
84                   {
85                      PropertyImport prop;
86                      f.Printf("            [Imported Properties]\n");
87                      for(prop = _class.properties.first; prop; prop = prop.next)
88                      {
89                         f.Printf("               %s\n", prop.name);
90                         if(prop.isVirtual)
91                            f.Printf("                  [Virtual]\n");
92                         if(prop.hasSet)
93                            f.Printf("                  [Set]\n");
94                         if(prop.hasGet)
95                            f.Printf("                  [Get]\n");
96                      }
97                      f.Printf("               .\n");
98                   }
99                }
100                f.Printf("        .\n");
101             }
102             if(module.functions.first)
103             {
104                f.Printf("      [Imported Functions]\n");
105                for(function = module.functions.first; function; function = function.next)
106                {
107                   f.Printf("         %s\n", function.name);
108                }
109                f.Printf("        .\n");
110             }
111          }
112          f.Printf("   .\n");
113       }
114    }
115    delete f;
116 }
117
118 class CompilerApp : Application
119 {
120    void Main()
121    {
122       char * cppCommand = null;
123       char * cppOptions = null;
124       int cppOptionsLen = 0;
125       /*char ** argv = null;
126       int argc = 0;*/
127       int c;
128       bool valid = true;
129       char defaultOutputFile[MAX_LOCATION];
130       bool buildingBootStrap = false;
131
132       Platform targetPlatform = GetRuntimePlatform();
133       int targetBits = GetHostBits();
134
135       SetSymbolsDir("");
136
137       /*for(c = 0; c<this.argc; c++)
138       {
139          char * arg = this.argv[c];
140          int argLen = strlen(arg);
141
142          argv = renew argv char *[argc + 1];
143          argv[argc] = new char[argLen+1];
144          strcpy(argv[argc], arg);
145
146          while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
147          {
148             int len;
149
150             c++;
151             arg = this.argv[c];
152             len = strlen(arg);
153             argv[argc] = renew argv[argc] char[argLen + len + 1];
154
155             argv[argc][argLen-1] = ' ';
156             strcpy(argv[argc] + argLen, arg);
157             argLen += len;
158          }
159          argc++;
160       }*/
161
162       for(c = 1; c<argc; c++)
163       {
164          char * arg = argv[c];
165          if(arg[0] == '-')
166          {
167             if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64"))
168             {
169                int argLen = strlen(arg);
170                int newLen = cppOptionsLen + 1 + argLen;
171                cppOptions = renew cppOptions char[newLen + 1];
172                cppOptions[cppOptionsLen] = ' ';
173                strcpy(cppOptions + cppOptionsLen + 1, arg);
174                cppOptionsLen = newLen;
175                targetBits = !strcmp(arg + 1, "m32") ? 32 : 64;
176             }
177             else if(arg[1] == 'D')
178             {
179                int argLen = strlen(arg);
180                int newLen = cppOptionsLen + 1 + argLen;
181                cppOptions = renew cppOptions char[newLen + 1];
182                cppOptions[cppOptionsLen] = ' ';
183                strcpy(cppOptions + cppOptionsLen + 1, arg); 
184                cppOptionsLen = newLen;
185                if(!strcmp(arg, "-DBUILDING_ECERE_COM"))
186                   SetBuildingEcereCom(true);
187                else if(!strcmp(arg, "-DECERE_COM_MODULE"))
188                   SetBuildingEcereComModule(true);
189                else if(!strcmp(arg, "-DECERE_BOOTSTRAP"))
190                   buildingBootStrap = true;
191             }
192             else if(arg[1] == 'I')
193             {
194                int argLen = strlen(arg);
195                int newLen = cppOptionsLen + argLen + 3;
196                cppOptions = renew cppOptions char[newLen + 1];
197                cppOptions[cppOptionsLen] = ' ';
198                cppOptions[cppOptionsLen+1] = '-';
199                cppOptions[cppOptionsLen+2] = 'I';
200                cppOptions[cppOptionsLen+3] = '"';
201                strcpy(cppOptions + cppOptionsLen + 4, arg+2); 
202                cppOptions[newLen-1] = '\"';
203                cppOptions[newLen] = '\0';
204                cppOptionsLen = newLen;
205             }
206             else if(!strcmp(arg+1, "t"))
207             {
208                if(++c < argc)
209                   targetPlatform = argv[c];
210                else
211                   valid = false;
212             }
213             else if(!strcmp(arg+1, "cpp"))
214             {
215                if(++c < argc)
216                   cppCommand = CopyString(argv[c]);
217                else
218                   valid = false;
219             }
220             else if(!strcmp(arg+1, "o"))
221             {
222                if(!GetOutputFile() && c + 1 < argc)
223                {
224                   SetOutputFile(argv[c+1]);
225                   c++;
226                }
227                else
228                   valid = false;
229             }
230             else if(!strcmp(arg+1, "c"))
231             {
232                if(!GetSourceFile() && c + 1 < argc)
233                {
234                   SetSourceFile(argv[c+1]);
235                   c++;
236                }
237                else
238                   valid = false;
239             }
240             else if(!strcmp(arg+1, "isystem") || !strcmp(arg+1, "isysroot"))
241             {
242                if(c + 1 < argc)
243                {
244                   int argLen = strlen(arg);
245                   int arg1Len = strlen(argv[c+1]);
246                   int newLen = cppOptionsLen + argLen + arg1Len + 4;
247                   cppOptions = renew cppOptions char[newLen + 1];
248                   cppOptions[cppOptionsLen] = ' ';
249                   strcpy(cppOptions + cppOptionsLen + 1, arg); 
250                   cppOptions[cppOptionsLen+argLen+1] = ' ';
251                   cppOptions[cppOptionsLen+argLen+2] = '"';
252                   arg = argv[++c];
253                   strcpy(cppOptions + cppOptionsLen + argLen + 3, arg); 
254                   cppOptions[newLen-1] = '\"';
255                   cppOptions[newLen] = '\0';
256                   cppOptionsLen = newLen;
257                }
258                else
259                   valid = false;
260             }
261             else if(!strcmp(arg+1, "symbols"))
262             {
263                if(c + 1 < argc)
264                {
265                   SetSymbolsDir(argv[c+1]);
266                   c++;
267                }
268                else
269                   valid = false;
270             }
271             else if(!strcmp(arg+1, "memguard"))
272             {
273                SetMemoryGuard(true);
274             }
275             else if(!strcmp(arg+1, "defaultns"))
276             {
277                if(c + 1 < argc)
278                {
279                   SetDefaultNameSpace(argv[c+1]);
280                   //defaultNameSpaceLen = strlen(defaultNameSpace);
281                   c++;
282                }
283                else
284                   valid = false;
285             }
286             else if(!strcmp(arg+1, "strictns"))
287             {
288                SetStrictNameSpaces(true);
289             }
290             else if(!strcmp(arg+1, "nolinenumbers"))
291             {
292                SetOutputLineNumbers(false);
293             }
294          }
295          else
296             valid = false;
297       }
298       if(valid)
299       {
300          if(!cppCommand)
301             cppCommand = CopyString("gcc");
302          if(!GetSourceFile())
303             valid = false;
304          else if(!GetOutputFile())
305          {
306             strcpy(defaultOutputFile, "");
307             PathCat(defaultOutputFile, GetSourceFile());
308             ChangeExtension(defaultOutputFile, "c", defaultOutputFile);
309             SetOutputFile(defaultOutputFile);
310          }
311       }
312
313       if(!valid)
314          printf($"Syntax:\n   ecc [-t <target platform>] [-cpp <c preprocessor>] [-o <output>] [-symbols <outputdir>] [-I<includedir>]* [-isystem <sysincludedir>]* [-D<definition>]* -c <input>\n");
315       else
316       {
317          DualPipe cppOutput;
318          // TODO: Improve this
319          char command[MAX_F_STRING*3];
320          SetGlobalData(&globalData);
321          SetExcludedSymbols(&_excludedSymbols);
322          SetGlobalContext(globalContext);
323          SetCurrentContext(globalContext);
324          SetTopContext(globalContext);
325          SetDefines(&::defines);
326          SetImports(&imports);
327          SetInCompiler(true);
328          SetTargetPlatform(targetPlatform);
329          SetTargetBits(targetBits);
330          SetEchoOn(false);
331
332          privateModule = (Module)__ecere_COM_Initialize(true | (targetBits == sizeof(uintptr)*8 ? 0 : targetBits == 64 ? 2 : targetBits==32 ? 4 : 0) | 8, 1, null);
333          SetPrivateModule(privateModule);
334
335          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint"), type = ProcessTypeString("unsigned int", false) });
336          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint64"), type = ProcessTypeString("unsigned int64", false) });
337          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint32"), type = ProcessTypeString("unsigned int", false) });
338          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint16"), type = ProcessTypeString("unsigned short", false) });
339          globalContext.types.Add((BTNode)Symbol { string = CopyString("byte"), type = ProcessTypeString("unsigned char", false) });
340          if(buildingBootStrap)
341          {
342             // Do not define this when we pre-include stdint.h or the eC compiler will be confused when parsing these types (External prioritization in pass15.ec will fail)
343             globalContext.types.Add((BTNode)Symbol { string = CopyString("intptr_t"), type = ProcessTypeString("intptr", false) });
344             globalContext.types.Add((BTNode)Symbol { string = CopyString("uintptr_t"), type = ProcessTypeString("uintptr", false) });
345             globalContext.types.Add((BTNode)Symbol { string = CopyString("ssize_t"), type = ProcessTypeString("intsize", false) });
346             globalContext.types.Add((BTNode)Symbol { string = CopyString("size_t"), type = ProcessTypeString("uintsize", false) });
347          }
348
349          {
350             GlobalData data { fullName = CopyString("__thisModule"), dataTypeString = CopyString("Module"), module = privateModule };
351             data.key = (uintptr)data.fullName;
352             globalData.functions.Add((BTNode)data);
353          }
354
355          snprintf(command, sizeof(command), "%s%s -x c -E %s\"%s\"", cppCommand, cppOptions ? cppOptions : "", buildingBootStrap ? "" : "-include stdint.h -include sys/types.h ", GetSourceFile());
356          command[sizeof(command)-1] = 0;
357          if((cppOutput = DualPipeOpen({ output = true }, command)))
358          {
359             char impFile[MAX_LOCATION];
360             ImportedModule module;
361             char mainModuleName[MAX_FILENAME];
362             int exitCode;
363             OldList * ast;
364
365             TempFile fileInput { };
366             SetFileInput(fileInput);
367
368             imports.Add((mainModule = ModuleImport { }));
369             SetMainModule(mainModule);
370
371             GetLastDirectory(GetSourceFile(), mainModuleName);
372
373 #if 0
374             // TEMP: UNTIL WE CAN HAVE PER SOURCE FILE PREPROCESSOR DEFINITIONS...
375             if(GetBuildingEcereCom() && 
376                !(strcmpi(mainModuleName, "instance.ec") && strcmpi(mainModuleName, "BinaryTree.ec") &&
377                strcmpi(mainModuleName, "dataTypes.ec") && strcmpi(mainModuleName, "OldList.ec") &&
378                strcmpi(mainModuleName, "String.ec") && strcmpi(mainModuleName, "BTNode.ec") &&
379                strcmpi(mainModuleName, "Array.ec") && strcmpi(mainModuleName, "AVLTree.ec") &&
380                strcmpi(mainModuleName, "BuiltInContainer.ec") && strcmpi(mainModuleName, "Container.ec") &&
381                strcmpi(mainModuleName, "CustomAVLTree.ec") && strcmpi(mainModuleName, "LinkList.ec") &&
382                strcmpi(mainModuleName, "List.ec") && strcmpi(mainModuleName, "Map.ec") &&
383                strcmpi(mainModuleName, "Mutex.ec")))
384                SetBuildingEcereComModule(true);
385             if(GetBuildingEcereCom() && 
386                !(strcmpi(mainModuleName, "instance.ec") && strcmpi(mainModuleName, "BinaryTree.ec") &&
387                /*strcmpi(mainModuleName, "dataTypes.ec") && strcmpi(mainModuleName, "OldList.ec") &&*/
388                /*strcmpi(mainModuleName, "String.ec") && */strcmpi(mainModuleName, "BTNode.ec") &&
389                strcmpi(mainModuleName, "Mutex.ec") && strcmpi(mainModuleName, "Thread.ec")))
390             //if(GetBuildingEcereCom() && !strcmpi(mainModuleName, "instance.ec"))
391                SetMemoryGuard(false);
392 #endif            
393
394             StripExtension(mainModuleName);
395             module = ImportedModule { name = CopyString(mainModuleName), type = moduleDefinition };
396             ::defines.AddName(module);
397
398             resetScanner();
399             while(!cppOutput.Eof())
400             {
401                char junk[4096];
402                int count = cppOutput.Read(junk, 1, 4096);
403                fileInput.Write(junk, 1, count);
404             }
405             exitCode = cppOutput.GetExitCode();
406             delete cppOutput;
407
408             fileInput.Seek(0, start);
409
410    #ifdef _DEBUG
411             // SetYydebug(true);
412    #endif
413
414             // Predeclare all classes
415             {
416                char symFile[MAX_FILENAME];
417                char symLocation[MAX_LOCATION];
418                ImportedModule module, next;
419
420                GetLastDirectory(GetSourceFile(), symFile);
421                ChangeExtension(symFile, "sym", symFile);
422
423                strcpy(symLocation, GetSymbolsDir());
424                PathCat(symLocation, symFile);
425                
426                // LoadSymbols(symLocation, normalImport, true);
427                LoadSymbols(symLocation, preDeclImport, false);
428                
429                for(module = ::defines.first; module; module = next)
430                {
431                   next = module.next;
432                   if(module.type == moduleDefinition && strcmpi(module.name, mainModuleName))
433                   {
434                      delete module.name;
435                      ::defines.Delete(module);
436                   }
437                }
438
439                if(!GetEcereImported() && !GetBuildingEcereCom())
440                   eModule_LoadStrict(privateModule, "ecereCOM", publicAccess /*privateAccess*/);
441             }
442
443             ParseEc();
444
445             CheckDataRedefinitions();
446
447             SetYydebug(false);
448             SetCurrentNameSpace(null);
449             SetDefaultNameSpace(null);
450             SetDeclMode(privateAccess);
451
452             delete fileInput;
453             SetFileInput(null);
454
455             ast = GetAST();
456
457             if(/*ast /*&& !parseError*/ /*&& */!exitCode)
458             {
459                ProcessDBTableDefinitions();
460
461                // *** PASS 0 - Register all classes, methods, properties and members ***
462                // ***          Build the constructors, destructors, properties as    ***
463                // ***          class functions                                       ***
464                PrePreProcessClassDefinitions();
465                ComputeModuleClasses(privateModule);
466                PreProcessClassDefinitions();
467
468                // For classes defined in this module...
469                ComputeModuleClasses(privateModule);
470
471                
472                // *** PASS 1 - Turn the class functions into functions               ***
473                // *** Write the RegisterModule (Register classes)                    ***
474                ProcessClassDefinitions();
475
476                // *** PASS 1.5 - Replace members by this.member, figure out types, do type checking / conversions
477                ComputeDataTypes();
478
479                // *** PASS 1.6 - Replace instantiations
480                ProcessInstantiations();
481
482                // *** PASS 2 - Replace Member Access ***
483                ProcessMemberAccess();
484
485                // *** PASS 3 - Replace pointers to objects by "Instance *" ***
486                ProcessInstanceDeclarations();
487
488                strcpy(impFile, GetSymbolsDir());
489                {
490                   char fileName[MAX_FILENAME];
491                   GetLastDirectory(GetSourceFile(), fileName);
492                   PathCat(impFile, fileName);
493                   ChangeExtension(impFile, "imp", impFile);
494                }
495                if(imports.first)
496                   OutputImports(impFile);
497                // For now use precomp to generate sym file only...
498
499                if(/*!strcmp(targetExt, "c") && */!this.exitCode)
500                {
501                   File output = FileOpen(GetOutputFile(), write);
502                   if(output)
503                   {
504                      output.Printf("#if defined(__GNUC__)\n");
505                         output.Printf("typedef long long int64;\n");
506                         output.Printf("typedef unsigned long long uint64;\n");
507                         output.Printf("#ifndef _WIN32\n");
508                            output.Printf("#define __declspec(x)\n");
509                         output.Printf("#endif\n");
510                      output.Printf("#elif defined(__TINYC__)\n");
511                         output.Printf("#include <stdarg.h>\n");
512                         output.Printf("#define __builtin_va_list va_list\n");
513                         output.Printf("#define __builtin_va_start va_start\n");
514                         output.Printf("#define __builtin_va_end va_end\n");
515                         output.Printf("#ifdef _WIN32\n");
516                            output.Printf("#define strcasecmp stricmp\n");
517                            output.Printf("#define strncasecmp strnicmp\n");
518                            output.Printf("#define __declspec(x) __attribute__((x))\n");
519                         output.Printf("#else\n");
520                            output.Printf("#define __declspec(x)\n");
521                         output.Printf("#endif\n");
522                         output.Printf("typedef long long int64;\n");
523                         output.Printf("typedef unsigned long long uint64;\n");
524                      output.Printf("#else\n");
525                         output.Printf("typedef __int64 int64;\n");
526                         output.Printf("typedef unsigned __int64 uint64;\n");
527                      output.Printf("#endif\n");
528                      output.Printf("#ifdef __BIG_ENDIAN__\n");
529                         output.Printf("#define __ENDIAN_PAD(x) (8 - (x))\n");
530                      output.Printf("#else\n");
531                         output.Printf("#define __ENDIAN_PAD(x) 0\n");
532                      output.Printf("#endif\n");
533                      if(buildingBootStrap)
534                      {
535                         //output.Printf("#ifdef __MINGW32__\n");
536                         //output.Printf("#ifdef _WIN64\n");
537                         /*
538                         output.Printf("#if defined(_WIN64) || WORDSIZE == 64\n");
539                         output.Printf("typedef unsigned long long int uintptr_t;\n");
540                         output.Printf("typedef long long int intptr_t;\n");
541                         output.Printf("#else\n");
542                         output.Printf("typedef unsigned int uintptr_t;\n");
543                         output.Printf("typedef int intptr_t;\n");
544                         output.Printf("#endif\n");
545                         */
546                         //output.Printf("#else\n");
547                         output.Printf("#include <stdint.h>\n");
548                         output.Printf("#include <sys/types.h>\n");
549                         //output.Printf("#endif\n");
550                      }
551
552                      // NOTE: If anything is changed up there, the start outputLine must be updated in libec's output.c or Debugging lines will be wrong
553
554                      if(ast)
555                         OutputTree(ast, output);
556                      delete output;
557                   }
558                }
559                /*
560                else if(!strcmp(targetExt, "o"))
561                {
562                   // Compile right away
563                   File output = FileOpen(GetOutputFile(), Write);
564                   output.Printf("#include <ecereCOM.h>\n\n");
565                   OutputTree(ast, output);
566                   delete output;
567                }*/
568             }
569             else
570                this.exitCode = exitCode;
571
572             if(ast)
573             {
574                FreeASTTree(ast);
575             }
576          }
577
578          FreeContext(globalContext);
579          FreeExcludedSymbols(_excludedSymbols);
580
581          ::defines.Free(FreeModuleDefine);
582          imports.Free(FreeModuleImport);
583
584          FreeTypeData(privateModule);
585          FreeIncludeFiles();
586          FreeGlobalData(globalData);
587
588          delete privateModule;
589       }
590
591       delete cppCommand;
592       delete cppOptions;
593
594       /*for(c = 0; c<argc; c++)
595          delete argv[c];
596       delete argv;
597       */
598       SetSymbolsDir(null); // Free symbols dir
599
600       OutputIntlStrings();
601
602 #if defined(_DEBUG) && defined(__WIN32__)
603       if(exitCode || GetNumWarnings())
604          getch();
605 #endif
606    }
607 }