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
19 classes.CompareKey = (void *)BinaryTree::CompareString;
20 defines.CompareKey = (void *)BinaryTree::CompareString;
21 functions.CompareKey = (void *)BinaryTree::CompareString;
22 nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
24 static OldList _precompDefines;
26 static void OutputImports(char * fileName)
28 File f = FileOpen(fileName, write);
34 f.Printf("[Imported Modules]\n");
35 for(module = imports.first; module; module = module.next)
38 FunctionImport function;
41 f.Printf(" %s\n", module.name);
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");
49 if(module.importAccess == privateAccess)
50 f.Printf(" [Private]\n");
52 f.Printf(" [Public]\n");
54 if(module.classes.first)
56 f.Printf(" [Imported Classes]\n");
57 for(_class = module.classes.first; _class; _class = _class.next)
59 f.Printf(" %s\n", _class.name);
62 f.Printf(" [Instantiated]\n");
66 f.Printf(" [Remote]\n");
69 if(_class.methods.first)
72 f.Printf(" [Imported Methods]\n");
73 for(method = _class.methods.first; method; method = method.next)
75 f.Printf(" %s\n", method.name);
77 f.Printf(" [Virtual]\n");
83 if(_class.properties.first)
86 f.Printf(" [Imported Properties]\n");
87 for(prop = _class.properties.first; prop; prop = prop.next)
89 f.Printf(" %s\n", prop.name);
91 f.Printf(" [Virtual]\n");
102 if(module.functions.first)
104 f.Printf(" [Imported Functions]\n");
105 for(function = module.functions.first; function; function = function.next)
107 f.Printf(" %s\n", function.name);
118 bool TestType(String string, String expected)
121 char typeString[1024] = { 0 };
122 Type type = ProcessTypeString(string, false);
123 PrintType(type, typeString, true, true);
124 if(strcmp(typeString, expected ? expected : string))
126 PrintLn("FAILED: ", string, " -> ", typeString);
134 int succeeded = 0, count = 0;
136 //count++, succeeded += TestType("int (* f[8])[10]", null);
137 count++, succeeded += TestType("void (* signal(int, void (*)(int)))(int)", null);
138 count++, succeeded += TestType("void (* signal(double))()", null);
139 count++, succeeded += TestType("void (* bla)(int)", null);
140 count++, succeeded += TestType("int f(void (*[10])())", null);
141 count++, succeeded += TestType("void (*[10])()", null);
142 count++, succeeded += TestType("void (* converters_table[10])()", null);
143 count++, succeeded += TestType("int (* f[8])[10]", null);
145 count++, succeeded += TestType("int f[8][10]", null);
146 count++, succeeded += TestType("int f[10]", null);
147 count++, succeeded += TestType("void *", null);
148 count++, succeeded += TestType("char * x", "char * x");
149 count++, succeeded += TestType("char * x", null);
150 count++, succeeded += TestType("char (* x[3])()", null);
151 count++, succeeded += TestType("char (*(* x[3])())", "char * (* x[3])()");
152 count++, succeeded += TestType("char (* x())", "char * x()");
153 count++, succeeded += TestType("char (* (* x[3])())[5]", null);
154 count++, succeeded += TestType("char (* f())[5]", null);
155 count++, succeeded += TestType("char * (* f())[5]", null);
156 count++, succeeded += TestType("char * (* * f())[5][2][3]", null);
157 count++, succeeded += TestType("char * (* * (* f)())[5][2][3]", null);
158 count++, succeeded += TestType("char * (* (* * (* f)())[5][2])[3]", null);
159 count++, succeeded += TestType("void (* (* bar)[5])()", null);
160 count++, succeeded += TestType("const int * (* const f)(char[10])", null);
161 count++, succeeded += TestType("const int", null);
162 count++, succeeded += TestType("int * const *", null);
163 count++, succeeded += TestType("int * const", null);
164 count++, succeeded += TestType("const int *", null);
166 count++, succeeded += TestType("char * const (* (* const bar)[5])(int)", null);
167 count++, succeeded += TestType("char * const (* (* (* const bar)[5][6])(int))[2]", null);
168 count++, succeeded += TestType("int * * a", null);
170 count++, succeeded += TestType("char * const (* bar)()", null);
172 count++, succeeded += TestType("char * const (* const (* const bar)[5])(int)", null);
174 count++, succeeded += TestType("char * (* const (* bar)[5])(int)", null);
175 count++, succeeded += TestType("void (* * const bar[5])()", null);
176 count++, succeeded += TestType("void (* * const bar)()", null);
177 count++, succeeded += TestType("void (* const * bar)()", null);
178 count++, succeeded += TestType("const int * * foo", null); // this prevents you from doing: **foo = 0;
179 count++, succeeded += TestType("int * const * bar", null); // this prevents you from doing: *bar = 0;
180 count++, succeeded += TestType("int * * const two", null); // this prevents you from doing: two = 0;
182 count++, succeeded += TestType("dllexport int TestFunction()", null); // this prevents you from doing: two = 0;
183 count++, succeeded += TestType("any_object TestFunction(any_object, typed_object & param)", null); // this prevents you from doing: two = 0;
185 count++, succeeded += TestType("void typed_object::OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)", null);
186 count++, succeeded += TestType("int typed_object::OnCompare(any_object object)", null);
187 count++, succeeded += TestType("void typed_object&::OnCopy(any_object newData)", null);
188 count++, succeeded += TestType("void typed_object::OnFree(void)", null);
189 count++, succeeded += TestType("char * typed_object::OnGetString(char * tempString, void * fieldData, bool * needClass)", null);
190 count++, succeeded += TestType("bool typed_object&::OnGetDataFromString(char * string)", null);
191 count++, succeeded += TestType("Window typed_object::OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)", null);
192 count++, succeeded += TestType("void typed_object::OnSerialize(IOChannel channel)", null);
193 count++, succeeded += TestType("void typed_object&::OnUnserialize(IOChannel channel)", null);
194 count++, succeeded += TestType("bool typed_object&::OnSaveEdit(Window window, void * object)", null);
196 count++, succeeded += TestType("void PrintLn(typed_object object, ...)", null);
197 count++, succeeded += TestType("void PrintLn(typed_object object, ...)", null);
198 count++, succeeded += TestType("thisclass RemoveSwapRight()", null);
199 count++, succeeded += TestType("LinkElement<thisclass> link", null);
200 count++, succeeded += TestType("struct { thisclass prev; thisclass next; }", null);
202 PrintLn("\n", succeeded, " / ", count, " tests succeeded.");
205 class CompilerApp : Application
209 char * cppCommand = null;
210 char * cppOptions = null;
211 int cppOptionsLen = 0;
212 /*char ** argv = null;
216 char defaultOutputFile[MAX_LOCATION];
217 bool buildingBootStrap = false;
219 Platform targetPlatform = GetRuntimePlatform();
220 int targetBits = GetHostBits();
224 /*for(c = 0; c<this.argc; c++)
226 char * arg = this.argv[c];
227 int argLen = strlen(arg);
229 argv = renew argv char *[argc + 1];
230 argv[argc] = new char[argLen+1];
231 strcpy(argv[argc], arg);
233 while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
240 argv[argc] = renew argv[argc] char[argLen + len + 1];
242 argv[argc][argLen-1] = ' ';
243 strcpy(argv[argc] + argLen, arg);
249 for(c = 1; c<argc; c++)
251 char * arg = argv[c];
254 if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64"))
256 int argLen = strlen(arg);
257 int newLen = cppOptionsLen + 1 + argLen;
258 cppOptions = renew cppOptions char[newLen + 1];
259 cppOptions[cppOptionsLen] = ' ';
260 strcpy(cppOptions + cppOptionsLen + 1, arg);
261 cppOptionsLen = newLen;
262 targetBits = !strcmp(arg + 1, "m32") ? 32 : 64;
264 else if(arg[1] == 'D')
266 int argLen = strlen(arg);
267 int newLen = cppOptionsLen + 1 + argLen;
268 cppOptions = renew cppOptions char[newLen + 1];
269 cppOptions[cppOptionsLen] = ' ';
270 strcpy(cppOptions + cppOptionsLen + 1, arg);
271 cppOptionsLen = newLen;
272 if(!strcmp(arg, "-DBUILDING_ECERE_COM"))
273 SetBuildingEcereCom(true);
274 else if(!strcmp(arg, "-DECERE_COM_MODULE"))
275 SetBuildingEcereComModule(true);
276 else if(!strcmp(arg, "-DECERE_BOOTSTRAP"))
277 buildingBootStrap = true;
279 else if(arg[1] == 'I')
281 int argLen = strlen(arg);
282 int newLen = cppOptionsLen + argLen + 3;
283 cppOptions = renew cppOptions char[newLen + 1];
284 cppOptions[cppOptionsLen] = ' ';
285 cppOptions[cppOptionsLen+1] = '-';
286 cppOptions[cppOptionsLen+2] = 'I';
287 cppOptions[cppOptionsLen+3] = '"';
288 strcpy(cppOptions + cppOptionsLen + 4, arg+2);
289 cppOptions[newLen-1] = '\"';
290 cppOptions[newLen] = '\0';
291 cppOptionsLen = newLen;
293 else if(!strcmp(arg+1, "t"))
296 targetPlatform = argv[c];
300 else if(!strcmp(arg+1, "cpp"))
303 cppCommand = CopyString(argv[c]);
307 else if(!strcmp(arg+1, "o"))
309 if(!GetOutputFile() && c + 1 < argc)
311 SetOutputFile(argv[c+1]);
317 else if(!strcmp(arg+1, "c"))
319 if(!GetSourceFile() && c + 1 < argc)
321 SetSourceFile(argv[c+1]);
327 else if(!strcmp(arg+1, "isystem") || !strcmp(arg+1, "isysroot"))
331 int argLen = strlen(arg);
332 int arg1Len = strlen(argv[c+1]);
333 int newLen = cppOptionsLen + argLen + arg1Len + 4;
334 cppOptions = renew cppOptions char[newLen + 1];
335 cppOptions[cppOptionsLen] = ' ';
336 strcpy(cppOptions + cppOptionsLen + 1, arg);
337 cppOptions[cppOptionsLen+argLen+1] = ' ';
338 cppOptions[cppOptionsLen+argLen+2] = '"';
340 strcpy(cppOptions + cppOptionsLen + argLen + 3, arg);
341 cppOptions[newLen-1] = '\"';
342 cppOptions[newLen] = '\0';
343 cppOptionsLen = newLen;
348 else if(!strcmp(arg+1, "symbols"))
352 SetSymbolsDir(argv[c+1]);
358 else if(!strcmp(arg+1, "memguard"))
360 SetMemoryGuard(true);
362 else if(!strcmp(arg+1, "defaultns"))
366 SetDefaultNameSpace(argv[c+1]);
367 //defaultNameSpaceLen = strlen(defaultNameSpace);
373 else if(!strcmp(arg+1, "strictns"))
375 SetStrictNameSpaces(true);
377 else if(!strcmp(arg+1, "nolinenumbers"))
379 SetOutputLineNumbers(false);
388 cppCommand = CopyString("gcc");
391 else if(!GetOutputFile())
393 strcpy(defaultOutputFile, "");
394 PathCat(defaultOutputFile, GetSourceFile());
395 ChangeExtension(defaultOutputFile, "c", defaultOutputFile);
396 SetOutputFile(defaultOutputFile);
401 printf($"Syntax:\n ecc [-t <target platform>] [-cpp <c preprocessor>] [-o <output>] [-symbols <outputdir>] [-I<includedir>]* [-isystem <sysincludedir>]* [-D<definition>]* -c <input>\n");
405 // TODO: Improve this
406 char command[MAX_F_STRING*3];
407 SetGlobalData(&globalData);
408 SetExcludedSymbols(&_excludedSymbols);
409 SetGlobalContext(globalContext);
410 SetCurrentContext(globalContext);
411 SetTopContext(globalContext);
412 SetDefines(&::defines);
413 SetImports(&imports);
415 SetTargetPlatform(targetPlatform);
416 SetTargetBits(targetBits);
423 privateModule = (Module)__ecere_COM_Initialize(true | (targetBits == sizeof(uintptr)*8 ? 0 : targetBits == 64 ? 2 : targetBits==32 ? 4 : 0) | 8, 1, null);
424 SetPrivateModule(privateModule);
426 globalContext.types.Add((BTNode)Symbol { string = CopyString("uint"), type = ProcessTypeString("unsigned int", false) });
427 globalContext.types.Add((BTNode)Symbol { string = CopyString("uint64"), type = ProcessTypeString("unsigned int64", false) });
428 globalContext.types.Add((BTNode)Symbol { string = CopyString("uint32"), type = ProcessTypeString("unsigned int", false) });
429 globalContext.types.Add((BTNode)Symbol { string = CopyString("uint16"), type = ProcessTypeString("unsigned short", false) });
430 globalContext.types.Add((BTNode)Symbol { string = CopyString("byte"), type = ProcessTypeString("unsigned char", false) });
431 if(buildingBootStrap)
433 // 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)
434 globalContext.types.Add((BTNode)Symbol { string = CopyString("intptr_t"), type = ProcessTypeString("intptr", false) });
435 globalContext.types.Add((BTNode)Symbol { string = CopyString("uintptr_t"), type = ProcessTypeString("uintptr", false) });
436 globalContext.types.Add((BTNode)Symbol { string = CopyString("ssize_t"), type = ProcessTypeString("intsize", false) });
437 globalContext.types.Add((BTNode)Symbol { string = CopyString("size_t"), type = ProcessTypeString("uintsize", false) });
441 GlobalData data { fullName = CopyString("__thisModule"), dataTypeString = CopyString("Module"), module = privateModule };
442 data.key = (uintptr)data.fullName;
443 globalData.functions.Add((BTNode)data);
446 snprintf(command, sizeof(command), "%s%s -x c -E %s\"%s\"", cppCommand, cppOptions ? cppOptions : "", buildingBootStrap ? "" : "-include stdint.h -include sys/types.h ", GetSourceFile());
447 command[sizeof(command)-1] = 0;
448 if((cppOutput = DualPipeOpen({ output = true }, command)))
450 char impFile[MAX_LOCATION];
451 ImportedModule module;
452 char mainModuleName[MAX_FILENAME];
456 TempFile fileInput { };
457 SetFileInput(fileInput);
459 imports.Add((mainModule = ModuleImport { }));
460 SetMainModule(mainModule);
462 GetLastDirectory(GetSourceFile(), mainModuleName);
465 // TEMP: UNTIL WE CAN HAVE PER SOURCE FILE PREPROCESSOR DEFINITIONS...
466 if(GetBuildingEcereCom() &&
467 !(strcmpi(mainModuleName, "instance.ec") && strcmpi(mainModuleName, "BinaryTree.ec") &&
468 strcmpi(mainModuleName, "dataTypes.ec") && strcmpi(mainModuleName, "OldList.ec") &&
469 strcmpi(mainModuleName, "String.ec") && strcmpi(mainModuleName, "BTNode.ec") &&
470 strcmpi(mainModuleName, "Array.ec") && strcmpi(mainModuleName, "AVLTree.ec") &&
471 strcmpi(mainModuleName, "BuiltInContainer.ec") && strcmpi(mainModuleName, "Container.ec") &&
472 strcmpi(mainModuleName, "CustomAVLTree.ec") && strcmpi(mainModuleName, "LinkList.ec") &&
473 strcmpi(mainModuleName, "List.ec") && strcmpi(mainModuleName, "Map.ec") &&
474 strcmpi(mainModuleName, "Mutex.ec")))
475 SetBuildingEcereComModule(true);
476 if(GetBuildingEcereCom() &&
477 !(strcmpi(mainModuleName, "instance.ec") && strcmpi(mainModuleName, "BinaryTree.ec") &&
478 /*strcmpi(mainModuleName, "dataTypes.ec") && strcmpi(mainModuleName, "OldList.ec") &&*/
479 /*strcmpi(mainModuleName, "String.ec") && */strcmpi(mainModuleName, "BTNode.ec") &&
480 strcmpi(mainModuleName, "Mutex.ec") && strcmpi(mainModuleName, "Thread.ec")))
481 //if(GetBuildingEcereCom() && !strcmpi(mainModuleName, "instance.ec"))
482 SetMemoryGuard(false);
485 StripExtension(mainModuleName);
486 module = ImportedModule { name = CopyString(mainModuleName), type = moduleDefinition };
487 ::defines.AddName(module);
490 while(!cppOutput.Eof())
493 int count = cppOutput.Read(junk, 1, 4096);
494 fileInput.Write(junk, 1, count);
496 exitCode = cppOutput.GetExitCode();
499 fileInput.Seek(0, start);
505 // Predeclare all classes
507 char symFile[MAX_FILENAME];
508 char symLocation[MAX_LOCATION];
509 ImportedModule module, next;
511 GetLastDirectory(GetSourceFile(), symFile);
512 ChangeExtension(symFile, "sym", symFile);
514 strcpy(symLocation, GetSymbolsDir());
515 PathCat(symLocation, symFile);
517 // LoadSymbols(symLocation, normalImport, true);
518 LoadSymbols(symLocation, preDeclImport, false);
520 for(module = ::defines.first; module; module = next)
523 if(module.type == moduleDefinition && strcmpi(module.name, mainModuleName))
526 ::defines.Delete(module);
530 if(!GetEcereImported() && !GetBuildingEcereCom())
531 eModule_LoadStrict(privateModule, "ecereCOM", publicAccess /*privateAccess*/);
536 CheckDataRedefinitions();
539 SetCurrentNameSpace(null);
540 SetDefaultNameSpace(null);
541 SetDeclMode(privateAccess);
548 if(/*ast /*&& !parseError*/ /*&& */!exitCode)
550 ProcessDBTableDefinitions();
552 // *** PASS 0 - Register all classes, methods, properties and members ***
553 // *** Build the constructors, destructors, properties as ***
554 // *** class functions ***
555 PrePreProcessClassDefinitions();
556 ComputeModuleClasses(privateModule);
557 PreProcessClassDefinitions();
559 // For classes defined in this module...
560 ComputeModuleClasses(privateModule);
563 // *** PASS 1 - Turn the class functions into functions ***
564 // *** Write the RegisterModule (Register classes) ***
565 ProcessClassDefinitions();
567 // *** PASS 1.5 - Replace members by this.member, figure out types, do type checking / conversions
570 // *** PASS 1.6 - Replace instantiations
571 ProcessInstantiations();
573 // *** PASS 2 - Replace Member Access ***
574 ProcessMemberAccess();
576 // *** PASS 3 - Replace pointers to objects by "Instance *" ***
577 ProcessInstanceDeclarations();
579 strcpy(impFile, GetSymbolsDir());
581 char fileName[MAX_FILENAME];
582 GetLastDirectory(GetSourceFile(), fileName);
583 PathCat(impFile, fileName);
584 ChangeExtension(impFile, "imp", impFile);
587 OutputImports(impFile);
588 // For now use precomp to generate sym file only...
590 if(/*!strcmp(targetExt, "c") && */!this.exitCode)
592 File output = FileOpen(GetOutputFile(), write);
595 output.Printf("#if defined(__GNUC__)\n");
596 output.Printf("typedef long long int64;\n");
597 output.Printf("typedef unsigned long long uint64;\n");
598 output.Printf("#ifndef _WIN32\n");
599 output.Printf("#define __declspec(x)\n");
600 output.Printf("#endif\n");
601 output.Printf("#elif defined(__TINYC__)\n");
602 output.Printf("#include <stdarg.h>\n");
603 output.Printf("#define __builtin_va_list va_list\n");
604 output.Printf("#define __builtin_va_start va_start\n");
605 output.Printf("#define __builtin_va_end va_end\n");
606 output.Printf("#ifdef _WIN32\n");
607 output.Printf("#define strcasecmp stricmp\n");
608 output.Printf("#define strncasecmp strnicmp\n");
609 output.Printf("#define __declspec(x) __attribute__((x))\n");
610 output.Printf("#else\n");
611 output.Printf("#define __declspec(x)\n");
612 output.Printf("#endif\n");
613 output.Printf("typedef long long int64;\n");
614 output.Printf("typedef unsigned long long uint64;\n");
615 output.Printf("#else\n");
616 output.Printf("typedef __int64 int64;\n");
617 output.Printf("typedef unsigned __int64 uint64;\n");
618 output.Printf("#endif\n");
619 output.Printf("#ifdef __BIG_ENDIAN__\n");
620 output.Printf("#define __ENDIAN_PAD(x) (8 - (x))\n");
621 output.Printf("#else\n");
622 output.Printf("#define __ENDIAN_PAD(x) 0\n");
623 output.Printf("#endif\n");
624 if(buildingBootStrap)
626 //output.Printf("#ifdef __MINGW32__\n");
627 //output.Printf("#ifdef _WIN64\n");
629 output.Printf("#if defined(_WIN64) || WORDSIZE == 64\n");
630 output.Printf("typedef unsigned long long int uintptr_t;\n");
631 output.Printf("typedef long long int intptr_t;\n");
632 output.Printf("#else\n");
633 output.Printf("typedef unsigned int uintptr_t;\n");
634 output.Printf("typedef int intptr_t;\n");
635 output.Printf("#endif\n");
637 //output.Printf("#else\n");
638 output.Printf("#include <stdint.h>\n");
639 output.Printf("#include <sys/types.h>\n");
640 //output.Printf("#endif\n");
643 // NOTE: If anything is changed up there, the start outputLine must be updated in libec's output.c or Debugging lines will be wrong
646 OutputTree(ast, output);
651 else if(!strcmp(targetExt, "o"))
653 // Compile right away
654 File output = FileOpen(GetOutputFile(), Write);
655 output.Printf("#include <ecereCOM.h>\n\n");
656 OutputTree(ast, output);
661 this.exitCode = exitCode;
669 FreeContext(globalContext);
670 FreeExcludedSymbols(_excludedSymbols);
672 ::defines.Free(FreeModuleDefine);
673 imports.Free(FreeModuleImport);
675 FreeTypeData(privateModule);
677 FreeGlobalData(globalData);
679 delete privateModule;
685 /*for(c = 0; c<argc; c++)
689 SetSymbolsDir(null); // Free symbols dir
693 #if defined(_DEBUG) && defined(__WIN32__)
694 if(exitCode || GetNumWarnings())