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