Initial git commit -- Transition from CodeGuard repository
[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 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);
656                            if(!data)
657                            {
658                               data = GlobalData
659                               {
660                                  fullName = CopyString(name),
661                                  dataTypeString = CopyString(line),
662                                  module = privateModule
663                               };
664                               data.key = (uint)(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 // (Same function as in actual compiler)
722 public void ImportModule(char * name, ImportType importType, AccessMode importAccess, bool loadDllOnly)
723 {
724    ImportedModule module = null;
725    char moduleName[MAX_FILENAME];
726
727    strncpy(moduleName, name, MAX_FILENAME-1);
728    moduleName[MAX_FILENAME-1] = 0;
729    StripExtension(moduleName);
730
731    for(module = defines->first; module; module = module.next)
732    {
733       if(module.type == moduleDefinition && !strcmpi(module.name, moduleName))
734          break;
735    }
736    if((!module || (module.dllOnly && !loadDllOnly)) && strlen(name) < MAX_FILENAME)
737    {
738       char ext[MAX_EXTENSION];
739       Module loadedModule = null;
740       char symFile[MAX_LOCATION];
741       symFile[0] = '\0';
742
743       GetExtension(name, ext);
744
745       strcpy(symFile, symbolsDir ? symbolsDir : "");
746       PathCat(symFile, name);
747       ChangeExtension(symFile, "sym", symFile);
748
749       if(!strcmp(ext, "dll") || !strcmp(ext, "dll") || !ext[0])
750       {
751          if(importType != comCheckImport)
752          {
753             if(!module)
754             {
755                if(precompDefines)
756                {
757                   module = ImportedModule
758                   {
759                      name = CopyString(moduleName),
760                      type = moduleDefinition,
761                      importType = importType,
762                      importAccess = importAccess
763                   };
764                   precompDefines->Add(module);
765                }
766                module = ImportedModule
767                {
768                   name = CopyString(moduleName),
769                   type = moduleDefinition,
770                   importType = importType,
771                   importAccess = importAccess
772                };
773                defines->AddName(module);
774             }
775             module.dllOnly = loadDllOnly;
776
777             if(ext[0] || !FileExists(symFile))
778             {
779                char file[MAX_FILENAME];
780                strcpy(file, name);
781                StripExtension(file);
782
783                loadedModule = eModule_LoadStrict(privateModule, file, importAccess);
784                if(loadedModule)
785                {
786                   loadedModule.importType = importType;
787                   module.dllOnly = false;    // If this is truly a dll, no need to reload it again...
788                }
789             }
790          }
791       }
792       if(!loadedModule && (!strcmp(ext, "ec") || !strcmp(ext, "sym") || !ext[0]))
793       {
794          //if(symbolsDir)
795          {
796             if(!module)
797             {
798                if(precompDefines)
799                {
800                   module = ImportedModule
801                   {
802                      name = CopyString(moduleName),
803                      type = moduleDefinition,
804                      importType = importType,
805                      importAccess = importAccess
806                   };
807                   precompDefines->Add(module);
808                }
809                module = ImportedModule
810                {
811                   name = CopyString(moduleName),
812                   type = moduleDefinition,
813                   importType = importType,
814                   importAccess = importAccess
815                };
816                defines->AddName(module);
817             }
818             module.dllOnly = loadDllOnly;
819
820             if(inPreCompiler)
821                return;
822
823             if(inIDE && !FileExists(symFile) && sourceDirs /*ide.workspace*/ /*ide.projectView*/)
824             {
825                for(dir : sourceDirs)
826                {
827                   strcpy(symFile, dir);
828                   PathCat(symFile, "Debug");
829                   PathCat(symFile, name);
830                   ChangeExtension(symFile, "sym", symFile);
831                   if(FileExists(symFile))
832                      break;
833                }
834             }
835
836             // ADDED THIS HERE TO HELP FINDING SYMBOLS IN DOCUMENTOR... HURTS ANYTHING?
837             if(!FileExists(symFile))
838             {
839                char fileName[MAX_FILENAME];
840                GetLastDirectory(symFile, fileName);
841                strcpy(symFile, symbolsDir ? symbolsDir : "");
842                PathCat(symFile, fileName);
843             }
844
845             module.globalInstance = LoadSymbols(symFile, importType, loadDllOnly);
846          }
847       }
848    }
849 }
850
851 int FindIncludeFileID(char * includeFile)
852 {
853    int c;
854    for(c = 0; c<numIncludes; c++)
855       if(!fstrcmp(includes[c], includeFile))
856          return c + 1;
857    return 0;
858 }
859
860 int GetIncludeFileID(char * includeFile)
861 {
862    int found = FindIncludeFileID(includeFile);
863    if(found) 
864       return found;
865
866    includes = renew includes char *[numIncludes+1];
867    includes[numIncludes++] = CopyString(includeFile);
868    return numIncludes;
869 }
870
871 char * GetIncludeFileFromID(int id)
872 {
873    return includes[id-1];
874 }
875
876 // TODO: Add parameter to check system dirs before project dirs
877 File OpenIncludeFile(char * includeFile)
878 {
879    File file;
880    char location[MAX_FILENAME];
881    StripLastDirectory(sourceFileStack[(include_stack_ptr >= 0) ? include_stack_ptr : 0], location);
882    PathCat(location, includeFile);
883    file = FileOpen(location, read);
884    if(file)
885    {
886       strcpy(sourceFileStack[include_stack_ptr + 1], location);
887    }
888    else if(inIDE)
889    {
890       // TODO: Add support for project dirs as well as system dirs
891       NamedItem includeDir;
892       if(includeDirs)
893       {
894          for(includeDir = includeDirs->first; includeDir; includeDir = includeDir.next)
895          {
896             strcpy(location, includeDir.name);
897             PathCat(location, includeFile);
898             file = FileOpen(location, read);
899             if(file)
900                break;
901          }
902       }
903       if(sysIncludeDirs)
904       {
905          for(includeDir = sysIncludeDirs->first; includeDir; includeDir = includeDir.next)
906          {
907             strcpy(location, includeDir.name);
908             PathCat(location, includeFile);
909             file = FileOpen(location, read);
910             if(file)
911                break;
912          }
913       }
914    }
915    return file;
916 }
917
918 public void FreeIncludeFiles()
919 {
920    int c;
921    for(c = 0; c<numIncludes; c++)
922       delete includes[c];
923    delete includes;
924    numIncludes = 0;
925 }
926
927 public void FreeGlobalData(NameSpace globalDataList)
928 {
929    NameSpace * ns;
930    GlobalData data;
931    // Unload functions
932    for(;(ns = (NameSpace *)globalDataList.nameSpaces.root);)
933    {
934       FreeGlobalData(ns);
935       globalDataList.nameSpaces.Remove((BTNode)ns);
936       delete ns->name;
937       delete ns;
938    }
939    for(;(data = (GlobalData)globalDataList.functions.root);)
940    {
941       globalDataList.functions.Remove(data);
942       if(data.symbol)
943          FreeSymbol(data.symbol);
944       FreeType(data.dataType);
945       delete data.fullName;
946       delete data.dataTypeString;
947       delete data;
948    }
949 }
950
951 public void CheckDataRedefinitions()
952 {
953    // Delaying this because conflict with main parser...
954    DataRedefinition redefinition;
955    for(redefinition = dataRedefinitions.first; redefinition; redefinition = redefinition.next)
956    {
957       // Added this check to resolve namespaces...
958       Type type1 = ProcessTypeString(redefinition.type1, false);
959       Type type2 = ProcessTypeString(redefinition.type2, false);
960       char type1String[1024] = "";
961       char type2String[1024] = "";
962       PrintType(type1, type1String, false, true);
963       PrintType(type2, type2String, false, true);
964       if(strcmp(type1String, type2String))
965          Compiler_Warning("Redefinition of %s (defining as %s, already defined as %s)\n", redefinition.name, type1String, type2String);
966       FreeType(type1);
967       FreeType(type2);
968    }
969    dataRedefinitions.Free(null);
970 }