7601af65adf78bb6d04ea359c4cb5d619b63e78d
[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(const 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                            const 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, strtoll(equal + 1, null, 0));
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 *)(uintptr)setStmt, (void *)(uintptr)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 *)(uintptr)setStmt, (void *)(uintptr)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                                     skipErrors = true;
505                                     exp = ParseExpressionString(line);
506                                     if(exp)
507                                     {
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                                     skipErrors = false;
517                                     popLexer(backup);
518                                  }
519                                  break;
520                               case identifier:
521                                  f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
522                                  if(!strcmp(line, "[Data member]")) info = (void *)TemplateMemberType::dataMember;
523                                  else if(!strcmp(line, "[Method]")) info = (void *)TemplateMemberType::method;
524                                  else if(!strcmp(line, "[Property]")) info = (void *)TemplateMemberType::prop;
525
526                                  f.GetLine(line, sizeof(line)); TrimLSpaces(line, line);
527                                  if(regClass && strcmp(line, "[None]"))
528                                  {
529                                     defaultArg.memberString = CopyString(line);
530                                  }
531                                  break;
532                            }
533                            if(regClass)
534                               eClass_AddTemplateParameter(regClass, name, type, info, defaultArg);
535                            if(type == TemplateParameterType::type || type == TemplateParameterType::expression)
536                               delete info;
537                            if(type == TemplateParameterType::type || type == TemplateParameterType::identifier)
538                               delete (void *)defaultArg.dataTypeString;
539                         }
540                         if(regClass)
541                            eClass_DoneAddingTemplateParameters(regClass);
542                      }
543                   }
544                   else
545                   {
546                      inheritanceAccess = publicAccess;
547                      classType = normalClass;
548                      isRemote = false;
549                      strcpy(name, line);
550                      regClass = null;
551                   }
552                }
553             }
554             else if(!strcmp(line, "[Defined Expressions]"))
555             {
556                char name[1024];
557                for(;;)
558                {
559                   if(!f.GetLine(line, sizeof(line))) break;
560                   TrimLSpaces(line, line);
561                   if(!strcmp(line, ".")) break;
562                   if(!strcmp(line, "[Value]"))
563                   {
564                      f.GetLine(line, sizeof(line));
565                      TrimLSpaces(line, line);
566                      if(!loadDllOnly && importType != preDeclImport && importType != comCheckImport)
567                         eSystem_RegisterDefine(name, line, privateModule, ecereCOMModule ? baseSystemAccess : publicAccess);
568                   }
569                   else if(line[0] != '[')
570                   {
571                      strcpy(name, line);
572                   }
573                }
574             }
575             else if(!strcmp(line, "[Defined Functions]"))
576             {
577                char name[1024];
578                for(;;)
579                {
580                   if(!f.GetLine(line, sizeof(line))) break;
581                   TrimLSpaces(line, line);
582                   if(!strcmp(line, ".")) break;
583                   if(!strcmp(line, "[Type]"))
584                   {
585                      f.GetLine(line, sizeof(line));
586                      TrimLSpaces(line, line);
587                      if(!loadDllOnly && importType != preDeclImport && importType != comCheckImport)
588                         eSystem_RegisterFunction(name, line, null, privateModule, ecereCOMModule ? baseSystemAccess : publicAccess);
589                   }
590                   else if(line[0] != '[')
591                   {
592                      strcpy(name, line);
593                   }
594                }
595             }
596             else if(!strcmp(line, "[Defined Data]"))
597             {
598                char name[1024];
599                for(;;)
600                {
601                   if(!f.GetLine(line, sizeof(line))) break;
602                   TrimLSpaces(line, line);
603                   if(!strcmp(line, ".")) break;
604                   if(!strcmp(line, "[Type]"))
605                   {
606                      f.GetLine(line, sizeof(line));
607                      TrimLSpaces(line, line);
608
609                      if(!loadDllOnly && importType != preDeclImport && importType != comCheckImport)
610                      {
611                         int start = 0, c;
612                         NameSpace * nameSpace = globalData;
613                         GlobalData data;
614
615                         // Register Global Data
616                         for(c = 0; name[c]; c++)
617                         {
618                            if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
619                            {
620                               NameSpace * newSpace;
621
622                               char * spaceName = new char[c - start + 1];
623                               strncpy(spaceName, name + start, c - start);
624                               spaceName[c-start] = '\0';
625
626                               newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
627                               if(!newSpace)
628                               {
629                                  newSpace = new0 NameSpace[1];
630                                  newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
631                                  newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
632                                  newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
633                                  newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
634                                  newSpace->name = spaceName;
635                                  newSpace->parent = nameSpace;
636                                  nameSpace->nameSpaces.Add((BTNode)newSpace);
637                               }
638                               else
639                                  delete spaceName;
640                               nameSpace = newSpace;
641                               if(name[c] == ':') c++;
642                               start = c+1;
643                            }
644                         }
645                         if(c - start)
646                         {
647                            // TOFIX:
648                            //if(!(data = (GlobalData)nameSpace->functions.FindString(name)))
649                            data = (GlobalData)nameSpace->functions.FindString(name + start);
650                            if(!data)
651                            {
652                               data = GlobalData
653                               {
654                                  fullName = CopyString(name),
655                                  dataTypeString = CopyString(line),
656                                  module = privateModule
657                               };
658                               data.key = (uintptr)(data.fullName + start);
659                               // Reusing functions here...
660                               nameSpace->functions.Add((BTNode)data);
661                            }
662                            else if(strcmp(data.dataTypeString, line))
663                            {
664                               DataRedefinition redefinition { };
665                               strcpy(redefinition.name, name);
666                               strcpy(redefinition.type1, data.dataTypeString);
667                               strcpy(redefinition.type2, line);
668                               dataRedefinitions.Add(redefinition);
669                            }
670                         }
671                      }
672                   }
673                   else if(line[0] != '[')
674                   {
675                      strcpy(name, line);
676                   }
677                }
678             }
679             else if(!strcmp(line, "[Imported Modules]"))
680             {
681                ImportType moduleImportType = normalImport;
682                AccessMode importAccess = publicAccess;
683                for(;;)
684                {
685                   if(!f.GetLine(line, sizeof(line))) break;
686                   TrimLSpaces(line, line);
687                   if(!strcmp(line, ".")) break;
688                   if(!strcmp(line, "[Static]")) moduleImportType = staticImport;
689                   else if(!strcmp(line, "[Remote]")) moduleImportType = remoteImport;
690                   else if(!strcmp(line, "[Private]")) importAccess = privateAccess;
691                   else if(line[0] != '[')
692                   {
693                      if(importType != preDeclImport && importType != comCheckImport)
694                         ImportModule(line, moduleImportType, importAccess, loadDllOnly);
695                      else
696                         ImportModule(line, comCheckImport, importAccess, loadDllOnly);
697                      if(!strcmp(line, "ecere"))
698                         ecereImported = true;
699                      moduleImportType = normalImport;
700                      importAccess = publicAccess;
701                   }
702                }
703             }
704          }
705       }
706       delete f;
707    }
708    else if(importType != comCheckImport)
709    {
710       char sysFileName[MAX_LOCATION];
711       GetSystemPathBuffer(sysFileName, fileName);
712       Compiler_Error($"Couldn't open %s\n", sysFileName);
713    }
714    return globalInstance;
715 }
716
717 Map<String, List<Module> > loadedModules { };
718
719 // (Same function as in actual compiler)
720 public void ImportModule(const char * name, ImportType importType, AccessMode importAccess, bool loadDllOnly)
721 {
722    ImportedModule module = null;
723    char moduleName[MAX_LOCATION];
724
725    strncpy(moduleName, name, MAX_LOCATION-1);
726    moduleName[MAX_LOCATION-1] = 0;
727    StripExtension(moduleName);
728
729    for(module = defines->first; module; module = module.next)
730    {
731       if(module.type == moduleDefinition && !strcmpi(module.name, moduleName))
732          break;
733    }
734    if((!module || (module.dllOnly && !loadDllOnly)) && strlen(name) < MAX_FILENAME)
735    {
736       char ext[MAX_EXTENSION];
737       Module loadedModule = null;
738       char symFile[MAX_LOCATION];
739       symFile[0] = '\0';
740
741       GetExtension(name, ext);
742
743       strcpy(symFile, symbolsDir ? symbolsDir : "");
744       PathCat(symFile, name);
745       ChangeExtension(symFile, "sym", symFile);
746
747       if(!strcmp(ext, "dll") || !strcmp(ext, "so") || !strcmp(ext, "dylib") || !ext[0])
748       {
749          if(importType != comCheckImport)
750          {
751             if(!module)
752             {
753                if(precompDefines)
754                {
755                   module = ImportedModule
756                   {
757                      name = CopyString(moduleName),
758                      type = moduleDefinition,
759                      importType = importType,
760                      importAccess = importAccess
761                   };
762                   precompDefines->Add(module);
763                }
764                module = ImportedModule
765                {
766                   name = CopyString(moduleName),
767                   type = moduleDefinition,
768                   importType = importType,
769                   importAccess = importAccess
770                };
771                defines->AddName(module);
772             }
773             module.dllOnly = loadDllOnly;
774
775             if(ext[0] || !FileExists(symFile))
776             {
777                bool skipLoad = false;
778                List<Module> list = null;
779                /*
780                char file[MAX_LOCATION];
781                strcpy(file, name);
782                StripExtension(file);
783                */
784
785                // Load an extra instance of any shared module to ensure freeing up a
786                // module loaded in another file will not invalidate our objects.
787                if(!inCompiler && !inPreCompiler && !inSymbolGen)
788                {
789                   MapIterator<String, List<Module> > it { map = loadedModules };
790                   if(!it.Index(name /*file*/, false))
791                   {
792                      Module firstModule = eModule_LoadStrict(__thisModule.application, name /*file*/, importAccess);
793                      if(firstModule)
794                      {
795                         list = { };
796                         list.Add(firstModule);
797                         loadedModules[name /*file*/] = list;
798                      }
799                      else
800                         skipLoad = true;
801                   }
802                   else
803                      list = it.data;
804                }
805
806                if(!skipLoad)
807                {
808                   loadedModule = eModule_LoadStrict(privateModule, name /*file*/, importAccess);
809                   if(loadedModule)
810                   {
811                      loadedModule.importType = importType;
812                      module.dllOnly = false;    // If this is truly a dll, no need to reload it again...
813                      if(list) list.Add(loadedModule);
814                   }
815                }
816             }
817          }
818       }
819       if(!loadedModule && (!strcmp(ext, "ec") || !strcmp(ext, "sym") || !ext[0]))
820       {
821          //if(symbolsDir)
822          {
823             if(!module)
824             {
825                if(precompDefines)
826                {
827                   module = ImportedModule
828                   {
829                      name = CopyString(moduleName),
830                      type = moduleDefinition,
831                      importType = importType,
832                      importAccess = importAccess
833                   };
834                   precompDefines->Add(module);
835                }
836                module = ImportedModule
837                {
838                   name = CopyString(moduleName),
839                   type = moduleDefinition,
840                   importType = importType,
841                   importAccess = importAccess
842                };
843                defines->AddName(module);
844             }
845             module.dllOnly = loadDllOnly;
846
847             if(inPreCompiler)
848                return;
849
850             if(inIDE && !FileExists(symFile) && sourceDirs /*ide.workspace*/ /*ide.projectView*/)
851             {
852                for(dir : sourceDirs)
853                {
854                   char configDir[MAX_FILENAME];
855                   strcpy(symFile, dir);
856                   // PathCat(symFile, "Debug");
857                   PathCat(symFile, "obj");
858                   sprintf(configDir, "debug.%s", (GetRuntimePlatform() == win32) ? "win32" : "linux");
859                   PathCat(symFile, configDir);
860
861                   PathCat(symFile, name);
862                   ChangeExtension(symFile, "sym", symFile);
863                   if(FileExists(symFile))
864                      break;
865                }
866             }
867
868             // ADDED THIS HERE TO HELP FINDING SYMBOLS IN DOCUMENTOR... HURTS ANYTHING?
869             if(!FileExists(symFile))
870             {
871                char fileName[MAX_FILENAME];
872                GetLastDirectory(symFile, fileName);
873                strcpy(symFile, symbolsDir ? symbolsDir : "");
874                PathCat(symFile, fileName);
875             }
876
877             module.globalInstance = LoadSymbols(symFile, importType, loadDllOnly);
878          }
879       }
880    }
881 }
882
883 int FindIncludeFileID(char * includeFile)
884 {
885    int c;
886    for(c = 0; c<numIncludes; c++)
887       if(!fstrcmp(includes[c], includeFile))
888          return c + 1;
889    return 0;
890 }
891
892 int GetIncludeFileID(char * includeFile)
893 {
894    int found = FindIncludeFileID(includeFile);
895    if(found)
896       return found;
897
898    includes = renew includes char *[numIncludes+1];
899    includes[numIncludes++] = CopyString(includeFile);
900    return numIncludes;
901 }
902
903 char * GetIncludeFileFromID(int id)
904 {
905    return includes[id-1];
906 }
907
908 // TODO: Add parameter to check system dirs before project dirs
909 File OpenIncludeFile(char * includeFile)
910 {
911    File file;
912    char location[MAX_FILENAME];
913    StripLastDirectory(sourceFileStack[(include_stack_ptr >= 0) ? include_stack_ptr : 0], location);
914    PathCat(location, includeFile);
915    file = FileOpen(location, read);
916    if(file)
917    {
918       strcpy(sourceFileStack[include_stack_ptr + 1], location);
919    }
920    else if(inIDE)
921    {
922       // TODO: Add support for project dirs as well as system dirs
923       NamedItem includeDir;
924       if(includeDirs)
925       {
926          for(includeDir = includeDirs->first; includeDir; includeDir = includeDir.next)
927          {
928             strcpy(location, includeDir.name);
929             PathCat(location, includeFile);
930             file = FileOpen(location, read);
931             if(file)
932                break;
933          }
934       }
935       if(!file && sysIncludeDirs)
936       {
937          for(includeDir = sysIncludeDirs->first; includeDir; includeDir = includeDir.next)
938          {
939             strcpy(location, includeDir.name);
940             PathCat(location, includeFile);
941             file = FileOpen(location, read);
942             if(file)
943                break;
944          }
945       }
946    }
947    return file;
948 }
949
950 public void FreeIncludeFiles()
951 {
952    int c;
953    for(c = 0; c<numIncludes; c++)
954       delete includes[c];
955    delete includes;
956    numIncludes = 0;
957 }
958
959 public void FreeGlobalData(NameSpace globalDataList)
960 {
961    NameSpace * ns;
962    GlobalData data;
963    // Unload functions
964    for(;(ns = (NameSpace *)globalDataList.nameSpaces.root);)
965    {
966       FreeGlobalData(ns);
967       globalDataList.nameSpaces.Remove((BTNode)ns);
968       delete (void *)ns->name;
969       delete ns;
970    }
971    for(;(data = (GlobalData)globalDataList.functions.root);)
972    {
973       globalDataList.functions.Remove(data);
974       if(data.symbol)
975          FreeSymbol(data.symbol);
976       FreeType(data.dataType);
977       delete data.fullName;
978       delete data.dataTypeString;
979       delete data;
980    }
981 }
982
983 public void CheckDataRedefinitions()
984 {
985    // Delaying this because conflict with main parser...
986    DataRedefinition redefinition;
987    for(redefinition = dataRedefinitions.first; redefinition; redefinition = redefinition.next)
988    {
989       // Added this check to resolve namespaces...
990       Type type1 = ProcessTypeString(redefinition.type1, false);
991       Type type2 = ProcessTypeString(redefinition.type2, false);
992       char type1String[1024] = "";
993       char type2String[1024] = "";
994       PrintType(type1, type1String, false, true);
995       PrintType(type2, type2String, false, true);
996       if(strcmp(type1String, type2String))
997          Compiler_Warning($"Redefinition of %s (defining as %s, already defined as %s)\n", redefinition.name, type1String, type2String);
998       FreeType(type1);
999       FreeType(type2);
1000    }
1001    dataRedefinitions.Free(null);
1002 }