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