ecere/com: Fixed 32 bit cross-compiling issues in EDASQLite
[sdk] / compiler / libec / src / loadSymbols.ec
1 import "ecdefs"
2
3 extern int yychar;
4
5 NameSpace * globalData;
6 public void SetGlobalData(NameSpace * nameSpace) { globalData = nameSpace; }
7
8 OldList dataRedefinitions;
9
10 // #define MAX_INCLUDE_DEPTH 30
11
12 extern char sourceFileStack[MAX_INCLUDE_DEPTH][MAX_LOCATION];
13 extern int include_stack_ptr;
14
15 static int numIncludes;
16 static char ** includes;
17
18 bool inIDE = false;
19 public void SetInIDE(bool b) { inIDE = b; }
20 List<String> sourceDirs;
21
22 public void SetSourceDirs(List<String> list) { sourceDirs = list; }
23
24 OldList * includeDirs, * sysIncludeDirs;
25
26 public void SetIncludeDirs(OldList * list) { includeDirs = list; }
27 public void SetSysIncludeDirs(OldList * list) { sysIncludeDirs = list; }
28
29 // TOFIX: Declaration reordering error if right before above functions
30 // OldList * includeDirs, * sysIncludeDirs;
31
32 bool ecereImported;
33 public void SetEcereImported(bool b) { ecereImported = b; } public bool GetEcereImported() { return ecereImported; }
34 bool inPreCompiler = false;
35 public void SetInPreCompiler(bool b) {inPreCompiler = b; }
36 bool inSymbolGen = false;
37 public void SetInSymbolGen(bool b) {inSymbolGen = b; }
38 OldList * precompDefines;
39 public void SetPrecompDefines(OldList * list) { precompDefines = list; }
40
41 public bool DummyMethod()
42 {
43    return true;
44 }
45
46 static void ReadDataMembers(Class regClass, DataMember member, File f)
47 {
48    char line[1024];
49    char name[1024];
50    int size = 0, bitPos = -1;
51    AccessMode memberAccess = publicAccess;
52
53    for(;;)
54    {
55       if(!f.GetLine(line, sizeof(line))) break;
56       TrimLSpaces(line, line);
57       if(!strcmp(line, ".")) break;
58       if(line[0] == '[')
59       {
60          if(!strcmp(line, "[Size]"))
61          {
62             f.GetLine(line, sizeof(line));
63             TrimLSpaces(line, line);
64             size = strtol(line, null, 0);
65          }
66          else if(!strcmp(line, "[Pos]"))
67          {
68             f.GetLine(line, sizeof(line));
69             TrimLSpaces(line, line);
70             bitPos = strtol(line, null, 0);
71          }
72          else if(!strcmp(line, "[Public]"))
73             memberAccess = publicAccess;
74          else if(!strcmp(line, "[Private]"))
75             memberAccess = privateAccess;
76          else if(!strcmp(line, "[Type]"))
77          {
78             f.GetLine(line, sizeof(line));
79             TrimLSpaces(line, line);
80
81             if(member)
82             {
83                if(!eMember_AddDataMember(member, name, line[0] ? line : 0, 0, 0 /*size *//*type->size*/, memberAccess))
84                   ;//Compiler_Error($"Member with same name already exists %s in member %s\n", name, member->name);
85             }
86             else if(regClass && regClass.type == bitClass)
87             {
88                //eClass_AddBitMember(regClass, name, line[0] ? line : 0, size, bitPos);
89                BitMember member = eClass_AddBitMember(regClass, name, line[0] ? line : 0, 0, 0, memberAccess);
90                member.size = size;
91                member.pos = bitPos;
92             }
93             else if(regClass)
94             {
95                if(!eClass_AddDataMember(regClass, name, line[0] ? line : 0, 0, 0 /*size *//*type->size*/, memberAccess))
96                   ;//Compiler_Error($"Member with same name already exists %s in class %s\n", name, regClass.fullName);
97             }
98          }
99          else if(!strcmp(line, "[Struct]") || !strcmp(line, "[Union]"))
100          {
101             DataMember dataMember = (regClass || member) ? eMember_New((!strcmp(line, "[Union]")) ? unionMember : structMember, memberAccess) : null;
102             ReadDataMembers(null, dataMember, f);
103             if(member)
104             {
105                if(!eMember_AddMember(member, dataMember))
106                   ;//Compiler_Error($"Member with same name already exists %s in member %s\n", name, member->name);
107             }
108             else if(regClass)
109             {
110                if(!eClass_AddMember(regClass, dataMember))
111                   ;//Compiler_Error($"Member with same name already exists %s in class %s\n", name, regClass.name);
112             }
113          }
114       }
115       else
116       {
117          size = 0;
118          bitPos = -1;
119          strcpy(name, line);
120          memberAccess = publicAccess;
121       }
122    }
123 }
124
125 // This should register the stuff only...
126 // But also call ImportModule
127 public bool LoadSymbols(char * fileName, ImportType importType, bool loadDllOnly)
128 {
129    File f = FileOpenBuffered(fileName, read);
130    bool globalInstance = false;
131    if(f)
132    {
133       bool ecereCOMModule = false;
134       char moduleName[MAX_LOCATION];
135       GetLastDirectory(fileName, moduleName);
136       // TEMP: UNTIL WE CAN HAVE PER SOURCE FILE PREPROCESSOR DEFINITIONS...
137       if(
138          !(strcmpi(moduleName, "instance.sym") && strcmpi(moduleName, "BinaryTree.sym") &&
139          strcmpi(moduleName, "dataTypes.sym") && strcmpi(moduleName, "OldList.sym") &&
140          strcmpi(moduleName, "String.sym") && strcmpi(moduleName, "BTNode.sym") &&
141          strcmpi(moduleName, "Array.sym") && strcmpi(moduleName, "AVLTree.sym") &&
142          strcmpi(moduleName, "BuiltInContainer.sym") && strcmpi(moduleName, "Container.sym") &&
143          strcmpi(moduleName, "CustomAVLTree.sym") && strcmpi(moduleName, "LinkList.sym") &&
144          strcmpi(moduleName, "List.sym") && strcmpi(moduleName, "Map.sym") &&
145          strcmpi(moduleName, "Mutex.sym")))
146          ecereCOMModule = true;
147
148       for(;;)
149       {
150          char line[1024];
151          if(!f.GetLine(line, sizeof(line))) break;
152          TrimLSpaces(line, line);
153
154          if(line[0] == '[')
155          {
156
157             if(!strcmp(line, "[Global Instance]"))
158                globalInstance = true;
159             else if(!strcmp(line, "[Defined Classes]"))
160             {
161                Class regClass = null;
162                char name[1024];
163                bool isRemote = false;
164                bool isStatic = false;
165                bool isWatchable = false;
166                ClassType classType = normalClass;
167                bool fixed = false;
168                bool noExpansion = false;
169                AccessMode inheritanceAccess = publicAccess;
170                for(;;)
171                {
172                   if(!f.GetLine(line, sizeof(line))) break;
173                   TrimLSpaces(line, line);
174                   if(!strcmp(line, ".")) break;
175
176                   if(line[0] == '[')
177                   {
178                      if(!strcmp(line, "[Remote]"))
179                         isRemote = true;
180                      else if(!strcmp(line, "[Static]"))
181                         isStatic = true;
182                      else if(!strcmp(line, "[Fixed]"))
183                         fixed = true;
184                      else if(!strcmp(line, "[No Expansion]"))
185                         noExpansion = true;
186                      else if(!strcmp(line, "[Watchable]"))
187                         isWatchable = true;
188                      else if(!strcmp(line, "[Enum]"))
189                         classType = enumClass;
190                      else if(!strcmp(line, "[Bit]"))
191                         classType = bitClass;
192                      else if(!strcmp(line, "[Struct]"))
193                         classType = structClass;
194                      else if(!strcmp(line, "[Unit]"))
195                         classType = unitClass;
196                      else if(!strcmp(line, "[NoHead]"))
197                         classType = noHeadClass;
198                      else if(!strcmp(line, "[Base]") || !strcmp(line, "[Private Base]"))
199                      {
200                         if(!strcmp(line, "[Private Base]"))
201                            inheritanceAccess = privateAccess;
202
203                         f.GetLine(line, sizeof(line));
204                         TrimLSpaces(line, line);
205
206                         if(importType == preDeclImport)
207                            DeclClass(0, name);
208                         if(isStatic || loadDllOnly || importType == preDeclImport || importType == comCheckImport)
209                           regClass = null;
210                         else if(regClass = eSystem_FindClass(privateModule, name), !regClass || regClass.internalDecl || regClass.isRemote)
211                         {
212                            Symbol existingClass = FindClass(name);
213                            char * baseName = (classType == normalClass && importType == remoteImport && isRemote) ? "DCOMClientObject" : (!strcmp(line, "[None]") ? null : line);
214                            //Symbol baseSymbol = baseName ? FindClass(baseName) : null;
215                            //if(baseSymbol && !baseSymbol->registered)
216                            /*if(classType != unitClass && classType != bitClass && classType != enumClass && baseName && !eSystem_FindClass(privateModule, baseName))
217                            {
218                               Compiler_Error($"Base class %s undefined\n", baseName);
219                               DeclClass(0, name);
220                               regClass = null;
221                               continue;
222                            }
223                            */
224
225                            if(!isRemote || (importType != remoteImport) || (!sourceFile || !strstr(sourceFile, ".main.ec")))
226                            {
227                               if(!regClass || regClass.internalDecl)
228                                  regClass = eSystem_RegisterClass(classType, name, isRemote ? null : baseName, 0, 0, null, null, privateModule, ecereCOMModule ? baseSystemAccess : publicAccess, inheritanceAccess);
229                               if(/*importType == Remote && */regClass && isRemote)
230                                  regClass.isRemote = (importType == remoteImport) ? 1 : 2;
231
232                               if(isRemote)
233                               {
234                                  if(importType == remoteImport)
235                                  {
236                                     char className[1024] = "DCOMClient_";
237                                     strcat(className, name);
238                                     if(!existingClass)
239                                        existingClass = DeclClass(0, name);
240                                     regClass = eSystem_RegisterClass(classType, className, baseName, 0, 0, null, null, privateModule, ecereCOMModule ? baseSystemAccess : publicAccess, inheritanceAccess);
241                                  }
242                                  if(regClass)
243                                     regClass.isRemote = (importType == remoteImport) ? 1 : 3;
244                               }
245
246                               // Update templated classes
247                               if(existingClass)
248                               {
249                                  OldLink link;
250                                  for(link = existingClass.templatedClasses.first; link; link = link.next)
251                                  {
252                                     Symbol symbol = link.data;
253                                     symbol.registered = eSystem_FindClass(privateModule, symbol.string);
254                                  }
255                               }
256
257                               if(fixed)
258                                  regClass.fixed = true;
259                               if(noExpansion)
260                                  regClass.noExpansion = true;
261
262                               if(isWatchable)
263                               {
264                                  eClass_DestructionWatchable(regClass);
265                                  regClass.structSize = regClass.offset;    // THIS COULD PROBABLY BENEFIT FROM SOME EXPLANATIONS...
266                               }
267
268                               // Added this
269                               if(regClass && existingClass)
270                               {
271                                  existingClass.registered = regClass;
272                                  regClass.symbol = existingClass; // TESTING THIS
273                                  existingClass.id = MAXINT;
274                                  existingClass.idCode = MAXINT;
275                                  existingClass.imported = true;
276                                  if(regClass.module)
277                                     existingClass.module = FindModule(regClass.module);
278                                  else
279                                     existingClass.module = mainModule;
280                               }
281                            }
282                            else
283                               regClass = null;
284                         }
285                         else
286                            regClass = null;
287                         isRemote = false;
288                         isWatchable = false;
289                         fixed = false;
290                         isStatic = false;
291                      }
292                      else if(!strcmp(line, "[Enum Values]"))
293                      {
294                         for(;;)
295                         {
296                            char * equal;
297                            
298                            if(!f.GetLine(line, sizeof(line))) break;
299                            TrimLSpaces(line, line);
300                            if(!strcmp(line, ".")) break;
301
302                            if(regClass)
303                            {
304                               equal = strchr(line, '=');
305                               if(equal)
306                               {
307                                  char name[1024];
308                                  memcpy(name, line, (int)(equal - line));
309                                  name[equal - line] = '\0';
310                                  TrimLSpaces(name, name);
311                                  TrimRSpaces(name, name);
312                                  eEnum_AddFixedValue(regClass, name, atoi(equal + 1));
313                               }
314                               else
315                               {
316                                  eEnum_AddValue(regClass, line);
317                               }
318                            }
319                         }
320                      }
321                      else if(!strcmp(line, "[Defined Methods]"))
322                      {
323                         char name[1024];
324                         bool isVirtual = false;
325                         AccessMode memberAccess = publicAccess;
326                         for(;;)
327                         {
328                            if(!f.GetLine(line, sizeof(line))) break;
329                            TrimLSpaces(line, line);
330                            if(!strcmp(line, ".")) break;
331                            if(line[0] == '[')
332                            {
333                               if(!strcmp(line, "[Type]"))
334                               {
335                                  f.GetLine(line, sizeof(line));
336                                  if(regClass)
337                                  {
338                                     TrimLSpaces(line, line);
339                                     if(isVirtual)
340                                        eClass_AddVirtualMethod(regClass, name, line[0] ? line : 0, DummyMethod, memberAccess);
341                                     else
342                                        eClass_AddMethod(regClass, name, line[0] ? line : 0, DummyMethod, memberAccess);
343                                  }
344                               }
345                               else if(!strcmp(line, "[Virtual]"))
346                                  isVirtual = true;
347                               else if(!strcmp(line, "[Public]"))
348                                  memberAccess = publicAccess;
349                               else if(!strcmp(line, "[Private]"))
350                                  memberAccess = privateAccess;
351                            }
352                            else
353                            {
354                               strcpy(name, line);                              
355                               isVirtual = false;
356                               memberAccess = publicAccess;
357                            }
358                         }
359                      }
360                      else if(!strcmp(line, "[Defined Properties]"))
361                      {
362                         char name[1024];
363                         bool setStmt = false, getStmt = false, isVirtual = false, conversion = false;
364                         bool isWatchable = false;
365                         AccessMode memberAccess = publicAccess;
366                         for(;;)
367                         {
368                            if(!f.GetLine(line, sizeof(line))) break;
369                            TrimLSpaces(line, line);
370                            if(!strcmp(line, ".")) break;
371                            if(line[0] == '[')
372                            {
373                               if(!strcmp(line, "[Type]"))
374                               {
375                                  // Set type , set , get
376                                  f.GetLine(line, sizeof(line));
377                                  TrimLSpaces(line, line);
378                                  if(regClass)
379                                  {
380                                     Property prop = eClass_AddProperty(regClass, conversion ? null : name, line[0] ? line : 0, (void *)setStmt, (void *)getStmt, memberAccess);
381                                     if(prop)
382                                     {
383                                        prop.compiled = false;
384                                        if(isWatchable)
385                                        {
386                                           eProperty_Watchable(prop);
387                                           regClass.structSize = regClass.offset; // THIS COULD PROBABLY BENEFIT FROM SOME EXPLANATIONS
388                                        }
389                                     }
390                                  }
391                               }
392                               else if(!strcmp(line, "[Set]"))
393                                  setStmt = true;
394                               else if(!strcmp(line, "[Get]"))
395                                  getStmt = true;
396                               else if(!strcmp(line, "[Watchable]"))
397                                  isWatchable = true;
398                               else if(!strcmp(line, "[Public]"))
399                                  memberAccess = publicAccess;
400                               else if(!strcmp(line, "[Private]"))
401                                  memberAccess = privateAccess;
402                               else if(!strcmp(line, "[Conversion]"))
403                               {
404                                  conversion = true;
405                                  setStmt = getStmt = isVirtual = isWatchable = false;
406                               }
407                            }
408                            else
409                            {
410                               strcpy(name, line);
411                               setStmt = getStmt = isVirtual = conversion = isWatchable = false;
412                               memberAccess = publicAccess;
413                            }
414                         }
415                      }
416                      else if(!strcmp(line, "[Defined Class Properties]"))
417                      {
418                         char name[1024];
419                         bool setStmt = false, getStmt = false;
420                         for(;;)
421                         {
422                            if(!f.GetLine(line, sizeof(line))) break;
423                            TrimLSpaces(line, line);
424                            if(!strcmp(line, ".")) break;
425                            if(line[0] == '[')
426                            {
427                               if(!strcmp(line, "[Type]"))
428                               {
429                                  // Set type , set , get
430                                  f.GetLine(line, sizeof(line));
431                                  TrimLSpaces(line, line);
432                                  if(regClass)
433                                  {
434                                     eClass_AddClassProperty(regClass, name, line, (void *)setStmt, (void *)getStmt);
435                                  }
436                               }
437                               else if(!strcmp(line, "[Set]"))
438                                  setStmt = true;
439                               else if(!strcmp(line, "[Get]"))
440                                  getStmt = true;
441                            }
442                            else
443                            {
444                               strcpy(name, line);
445                               setStmt = getStmt = false;
446                            }
447                         }
448                      }
449                      else if(!strcmp(line, "[Defined Data Members]"))
450                      {
451                         ReadDataMembers(regClass, null, f);
452                      }
453                      else if(!strcmp(line, "[Template Parameters]"))
454                      {
455                         while(!f.Eof())
456                         {
457                            char name[1024];
458                            TemplateParameterType type = TemplateParameterType::type;
459                            ClassTemplateArgument defaultArg { };
460                            void * info = null;
461
462                            f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
463                            if(line[0] == '.') break;
464                            strcpy(name, line);
465
466                            f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
467                            if(!strcmp(line, "[Expression]")) type = expression;
468                            else if(!strcmp(line, "[Identifier]")) type = identifier;
469
470                            //printf("Inside template parameters\n");
471                            switch(type)
472                            {
473                               case TemplateParameterType::type:
474                                  f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
475                                  if(regClass && strcmp(line, "[None]"))
476                                  {
477                                     info = CopyString(line);      // FIXME: MEMORY LEAK
478                                  }
479
480                                  f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
481                                  // printf("%s\n", line);
482
483                                  if(regClass && strcmp(line, "[None]"))
484                                  {
485                                     defaultArg.dataTypeString = CopyString(line);   // FIXME: MEMORY LEAK
486                                  }
487                                  break;
488                               case expression:
489                                  f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
490                                  // Data type string (reusing base)
491                                  if(regClass && strcmp(line, "[None]"))
492                                  {
493                                     info = CopyString(line);   // FIXME: MEMORY LEAK
494                                  }
495
496                                  f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
497                                  if(regClass && strcmp(line, "[None]"))
498                                  {
499                                     Operand op;
500                                     Expression exp;
501                                     Location oldLocation = yylloc;
502
503                                     File backFileInput = fileInput;
504                                     declMode = 0;
505                                     resetScanner();
506
507                                     exp = ParseExpressionString(line);
508                                     if(info)
509                                        exp.destType = ProcessTypeString(info, false);
510                                     ProcessExpressionType(exp);
511                                     ComputeExpression(exp);
512                                     op = GetOperand(exp);
513                                     defaultArg.expression.ui64 = op.ui64;
514                                     FreeExpression(exp);
515
516                                     // TESTING THIS SCANNER RESUME STUFF
517                                     resetScanner();
518                                     yylloc = oldLocation;
519                                     fileInput = backFileInput;
520                                     if(fileInput)
521                                     {
522                                        fileInput.Seek(yylloc.start.pos, start); 
523                                        resetScannerPos(&yylloc.start);
524                                        yychar = -2;
525                                     }
526                                  }
527                                  break;
528                               case identifier:
529                                  f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
530                                  if(!strcmp(line, "[Data member]")) info = (void *)TemplateMemberType::dataMember;
531                                  else if(!strcmp(line, "[Method]")) info = (void *)TemplateMemberType::method;
532                                  else if(!strcmp(line, "[Property]")) info = (void *)TemplateMemberType::prop;
533
534                                  f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
535                                  if(regClass && strcmp(line, "[None]"))
536                                  {
537                                     defaultArg.memberString = CopyString(line);
538                                  }
539                                  break;
540                            }
541                            if(regClass)
542                               eClass_AddTemplateParameter(regClass, name, type, info, defaultArg);
543                            if(type == TemplateParameterType::type || type == TemplateParameterType::expression)
544                               delete info;
545                            if(type == TemplateParameterType::type || type == TemplateParameterType::identifier)
546                               delete defaultArg.dataTypeString;                           
547                         }
548                         if(regClass)
549                            eClass_DoneAddingTemplateParameters(regClass);
550                      }
551                   }
552                   else
553                   {
554                      inheritanceAccess = publicAccess;
555                      classType = normalClass;
556                      isRemote = false;
557                      strcpy(name, line);
558                      regClass = null;
559                   }
560                }
561             }
562             else if(!strcmp(line, "[Defined Expressions]"))
563             {
564                char name[1024];
565                for(;;)
566                {
567                   if(!f.GetLine(line, sizeof(line))) break;
568                   TrimLSpaces(line, line);
569                   if(!strcmp(line, ".")) break;
570                   if(!strcmp(line, "[Value]")) 
571                   {
572                      f.GetLine(line, sizeof(line));
573                      TrimLSpaces(line, line);
574                      if(!loadDllOnly && importType != preDeclImport && importType != comCheckImport)
575                         eSystem_RegisterDefine(name, line, privateModule, ecereCOMModule ? baseSystemAccess : publicAccess);
576                   }
577                   else if(line[0] != '[')
578                   {
579                      strcpy(name, line);
580                   }
581                }
582             }
583             else if(!strcmp(line, "[Defined Functions]"))
584             {
585                char name[1024];
586                for(;;)
587                {
588                   if(!f.GetLine(line, sizeof(line))) break;
589                   TrimLSpaces(line, line);
590                   if(!strcmp(line, ".")) break;
591                   if(!strcmp(line, "[Type]")) 
592                   {
593                      f.GetLine(line, sizeof(line));
594                      TrimLSpaces(line, line);
595                      if(!loadDllOnly && importType != preDeclImport && importType != comCheckImport)
596                         eSystem_RegisterFunction(name, line, null, privateModule, ecereCOMModule ? baseSystemAccess : publicAccess);
597                   }
598                   else if(line[0] != '[')
599                   {
600                      strcpy(name, line);
601                   }
602                }
603             }
604             else if(!strcmp(line, "[Defined Data]"))
605             {
606                char name[1024];
607                for(;;)
608                {
609                   if(!f.GetLine(line, sizeof(line))) break;
610                   TrimLSpaces(line, line);
611                   if(!strcmp(line, ".")) break;
612                   if(!strcmp(line, "[Type]")) 
613                   {
614                      f.GetLine(line, sizeof(line));
615                      TrimLSpaces(line, line);
616
617                      if(!loadDllOnly && importType != preDeclImport && importType != comCheckImport)
618                      {
619                         int start = 0, c;
620                         NameSpace * nameSpace = globalData;
621                         GlobalData data;
622
623                         // Register Global Data
624                         for(c = 0; name[c]; c++)
625                         {
626                            if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
627                            {
628                               NameSpace * newSpace;
629
630                               char * spaceName = new char[c - start + 1];
631                               strncpy(spaceName, name + start, c - start);
632                               spaceName[c-start] = '\0';
633
634                               newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
635                               if(!newSpace)
636                               {
637                                  newSpace = new0 NameSpace[1];
638                                  newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
639                                  newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
640                                  newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
641                                  newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
642                                  newSpace->name = spaceName;
643                                  newSpace->parent = nameSpace;
644                                  nameSpace->nameSpaces.Add((BTNode)newSpace);
645                               }
646                               else
647                                  delete spaceName;
648                               nameSpace = newSpace;
649                               if(name[c] == ':') c++;
650                               start = c+1;         
651                            }
652                         }
653                         if(c - start)
654                         {
655                            // TOFIX:
656                            //if(!(data = (GlobalData)nameSpace->functions.FindString(name)))
657                            data = (GlobalData)nameSpace->functions.FindString(name + start);
658                            if(!data)
659                            {
660                               data = GlobalData
661                               {
662                                  fullName = CopyString(name),
663                                  dataTypeString = CopyString(line),
664                                  module = privateModule
665                               };
666                               data.key = (uintptr)(data.fullName + start);
667                               // Reusing functions here...
668                               nameSpace->functions.Add((BTNode)data);
669                            }
670                            else if(strcmp(data.dataTypeString, line))
671                            {
672                               DataRedefinition redefinition { };
673                               strcpy(redefinition.name, name);
674                               strcpy(redefinition.type1, data.dataTypeString);
675                               strcpy(redefinition.type2, line);
676                               dataRedefinitions.Add(redefinition);
677                            }
678                         }
679                      }
680                   }
681                   else if(line[0] != '[')
682                   {
683                      strcpy(name, line);
684                   }
685                }
686             }
687             else if(!strcmp(line, "[Imported Modules]"))
688             {
689                ImportType moduleImportType = normalImport;
690                AccessMode importAccess = publicAccess;
691                for(;;)
692                {
693                   if(!f.GetLine(line, sizeof(line))) break;
694                   TrimLSpaces(line, line);
695                   if(!strcmp(line, ".")) break;
696                   if(!strcmp(line, "[Static]")) moduleImportType = staticImport;
697                   else if(!strcmp(line, "[Remote]")) moduleImportType = remoteImport;
698                   else if(!strcmp(line, "[Private]")) importAccess = privateAccess;
699                   else if(line[0] != '[')
700                   {
701                      if(importType != preDeclImport && importType != comCheckImport)
702                         ImportModule(line, moduleImportType, importAccess, loadDllOnly);
703                      else
704                         ImportModule(line, comCheckImport, importAccess, loadDllOnly);
705                      if(!strcmp(line, "ecere"))
706                         ecereImported = true;
707                      moduleImportType = normalImport;
708                      importAccess = publicAccess;
709                   }
710                }
711             }
712          }
713       }
714       delete f;
715    }
716    else if(importType != comCheckImport)
717    {
718       Compiler_Error($"Couldn't open %s\n", fileName);
719    }
720    return globalInstance;
721 }
722
723 Map<String, List<Module> > loadedModules { };
724
725 // (Same function as in actual compiler)
726 public void ImportModule(char * name, ImportType importType, AccessMode importAccess, bool loadDllOnly)
727 {
728    ImportedModule module = null;
729    char moduleName[MAX_FILENAME];
730
731    strncpy(moduleName, name, MAX_FILENAME-1);
732    moduleName[MAX_FILENAME-1] = 0;
733    StripExtension(moduleName);
734
735    for(module = defines->first; module; module = module.next)
736    {
737       if(module.type == moduleDefinition && !strcmpi(module.name, moduleName))
738          break;
739    }
740    if((!module || (module.dllOnly && !loadDllOnly)) && strlen(name) < MAX_FILENAME)
741    {
742       char ext[MAX_EXTENSION];
743       Module loadedModule = null;
744       char symFile[MAX_LOCATION];
745       symFile[0] = '\0';
746
747       GetExtension(name, ext);
748
749       strcpy(symFile, symbolsDir ? symbolsDir : "");
750       PathCat(symFile, name);
751       ChangeExtension(symFile, "sym", symFile);
752
753       if(!strcmp(ext, "dll") || !strcmp(ext, "dll") || !ext[0])
754       {
755          if(importType != comCheckImport)
756          {
757             if(!module)
758             {
759                if(precompDefines)
760                {
761                   module = ImportedModule
762                   {
763                      name = CopyString(moduleName),
764                      type = moduleDefinition,
765                      importType = importType,
766                      importAccess = importAccess
767                   };
768                   precompDefines->Add(module);
769                }
770                module = ImportedModule
771                {
772                   name = CopyString(moduleName),
773                   type = moduleDefinition,
774                   importType = importType,
775                   importAccess = importAccess
776                };
777                defines->AddName(module);
778             }
779             module.dllOnly = loadDllOnly;
780
781             if(ext[0] || !FileExists(symFile))
782             {
783                bool skipLoad = false;
784                List<Module> list = null;
785
786                char file[MAX_FILENAME];
787                strcpy(file, name);
788                StripExtension(file);
789
790                // Load an extra instance of any shared module to ensure freeing up a 
791                // module loaded in another file will not invalidate our objects.
792                if(!inCompiler && !inPreCompiler && !inSymbolGen)
793                {
794                   MapIterator<String, List<Module> > it { map = loadedModules };
795                   if(!it.Index(file, false))
796                   {
797                      Module firstModule = eModule_LoadStrict(__thisModule, file, importAccess);
798                      if(firstModule)
799                      {
800                         list = { };
801                         list.Add(firstModule);
802                         loadedModules[file] = list;
803                      }
804                      else
805                         skipLoad = true;
806                   }
807                   else
808                      list = it.data;
809                }
810
811                if(!skipLoad)
812                {
813                   loadedModule = eModule_LoadStrict(privateModule, file, importAccess);
814                   if(loadedModule)
815                   {
816                      loadedModule.importType = importType;
817                      module.dllOnly = false;    // If this is truly a dll, no need to reload it again...
818                      if(list) list.Add(loadedModule);
819                   }
820                }
821             }
822          }
823       }
824       if(!loadedModule && (!strcmp(ext, "ec") || !strcmp(ext, "sym") || !ext[0]))
825       {
826          //if(symbolsDir)
827          {
828             if(!module)
829             {
830                if(precompDefines)
831                {
832                   module = ImportedModule
833                   {
834                      name = CopyString(moduleName),
835                      type = moduleDefinition,
836                      importType = importType,
837                      importAccess = importAccess
838                   };
839                   precompDefines->Add(module);
840                }
841                module = ImportedModule
842                {
843                   name = CopyString(moduleName),
844                   type = moduleDefinition,
845                   importType = importType,
846                   importAccess = importAccess
847                };
848                defines->AddName(module);
849             }
850             module.dllOnly = loadDllOnly;
851
852             if(inPreCompiler)
853                return;
854
855             if(inIDE && !FileExists(symFile) && sourceDirs /*ide.workspace*/ /*ide.projectView*/)
856             {
857                for(dir : sourceDirs)
858                {
859                   char configDir[MAX_FILENAME];
860                   strcpy(symFile, dir);
861                   // PathCat(symFile, "Debug");
862                   PathCat(symFile, "obj");
863                   sprintf(configDir, "debug.%s", (GetRuntimePlatform() == win32) ? "win32" : "linux");
864                   PathCat(symFile, configDir);
865
866                   PathCat(symFile, name);
867                   ChangeExtension(symFile, "sym", symFile);
868                   if(FileExists(symFile))
869                      break;
870                }
871             }
872
873             // ADDED THIS HERE TO HELP FINDING SYMBOLS IN DOCUMENTOR... HURTS ANYTHING?
874             if(!FileExists(symFile))
875             {
876                char fileName[MAX_FILENAME];
877                GetLastDirectory(symFile, fileName);
878                strcpy(symFile, symbolsDir ? symbolsDir : "");
879                PathCat(symFile, fileName);
880             }
881
882             module.globalInstance = LoadSymbols(symFile, importType, loadDllOnly);
883          }
884       }
885    }
886 }
887
888 int FindIncludeFileID(char * includeFile)
889 {
890    int c;
891    for(c = 0; c<numIncludes; c++)
892       if(!fstrcmp(includes[c], includeFile))
893          return c + 1;
894    return 0;
895 }
896
897 int GetIncludeFileID(char * includeFile)
898 {
899    int found = FindIncludeFileID(includeFile);
900    if(found) 
901       return found;
902
903    includes = renew includes char *[numIncludes+1];
904    includes[numIncludes++] = CopyString(includeFile);
905    return numIncludes;
906 }
907
908 char * GetIncludeFileFromID(int id)
909 {
910    return includes[id-1];
911 }
912
913 // TODO: Add parameter to check system dirs before project dirs
914 File OpenIncludeFile(char * includeFile)
915 {
916    File file;
917    char location[MAX_FILENAME];
918    StripLastDirectory(sourceFileStack[(include_stack_ptr >= 0) ? include_stack_ptr : 0], location);
919    PathCat(location, includeFile);
920    file = FileOpen(location, read);
921    if(file)
922    {
923       strcpy(sourceFileStack[include_stack_ptr + 1], location);
924    }
925    else if(inIDE)
926    {
927       // TODO: Add support for project dirs as well as system dirs
928       NamedItem includeDir;
929       if(includeDirs)
930       {
931          for(includeDir = includeDirs->first; includeDir; includeDir = includeDir.next)
932          {
933             strcpy(location, includeDir.name);
934             PathCat(location, includeFile);
935             file = FileOpen(location, read);
936             if(file)
937                break;
938          }
939       }
940       if(sysIncludeDirs)
941       {
942          for(includeDir = sysIncludeDirs->first; includeDir; includeDir = includeDir.next)
943          {
944             strcpy(location, includeDir.name);
945             PathCat(location, includeFile);
946             file = FileOpen(location, read);
947             if(file)
948                break;
949          }
950       }
951    }
952    return file;
953 }
954
955 public void FreeIncludeFiles()
956 {
957    int c;
958    for(c = 0; c<numIncludes; c++)
959       delete includes[c];
960    delete includes;
961    numIncludes = 0;
962 }
963
964 public void FreeGlobalData(NameSpace globalDataList)
965 {
966    NameSpace * ns;
967    GlobalData data;
968    // Unload functions
969    for(;(ns = (NameSpace *)globalDataList.nameSpaces.root);)
970    {
971       FreeGlobalData(ns);
972       globalDataList.nameSpaces.Remove((BTNode)ns);
973       delete ns->name;
974       delete ns;
975    }
976    for(;(data = (GlobalData)globalDataList.functions.root);)
977    {
978       globalDataList.functions.Remove(data);
979       if(data.symbol)
980          FreeSymbol(data.symbol);
981       FreeType(data.dataType);
982       delete data.fullName;
983       delete data.dataTypeString;
984       delete data;
985    }
986 }
987
988 public void CheckDataRedefinitions()
989 {
990    // Delaying this because conflict with main parser...
991    DataRedefinition redefinition;
992    for(redefinition = dataRedefinitions.first; redefinition; redefinition = redefinition.next)
993    {
994       // Added this check to resolve namespaces...
995       Type type1 = ProcessTypeString(redefinition.type1, false);
996       Type type2 = ProcessTypeString(redefinition.type2, false);
997       char type1String[1024] = "";
998       char type2String[1024] = "";
999       PrintType(type1, type1String, false, true);
1000       PrintType(type2, type2String, false, true);
1001       if(strcmp(type1String, type2String))
1002          Compiler_Warning($"Redefinition of %s (defining as %s, already defined as %s)\n", redefinition.name, type1String, type2String);
1003       FreeType(type1);
1004       FreeType(type2);
1005    }
1006    dataRedefinitions.Free(null);
1007 }