ide/FindInFiles: Fixed buffer underrun on go to found location
[sdk] / compiler / ecp / ecp.ec
1 #ifdef ECERE_STATIC
2 import static "ecere"
3 import static "ec"
4 #else
5 import "ecere"
6 import "ec"
7 #endif
8
9 #define YYLTYPE Location
10 #include "../libec/src/grammar.h"
11
12 // UNTIL IMPLEMENTED IN GRAMMAR
13 #define ACCESS_CLASSDATA(_class, baseClass) \
14    (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
15
16 // #include <stdarg.h>
17
18 // WARNING: PropertyDefine, ClassDefine and DataMemberDefine must remain compatible
19 struct ClassDefine : Definition
20 {
21    char * base;
22    OldList propertiesAndMembers;
23    OldList classProperties;
24    OldList methods;
25    bool isRemote;
26    bool isWatchable;
27    bool fixed;
28    bool isStatic;
29    bool noExpansion;
30 };
31
32 struct Define : Definition
33 {
34    Expression exp;
35 };
36
37 struct FunctionDefine : Definition
38 {
39    char * dataType;
40 };
41
42 struct DataDefine : Definition
43 {
44    char * dataType;
45 };
46
47 class MethodDefine : struct
48 {
49    MethodDefine prev, next;
50    char * name;
51    AccessMode memberAccess;
52    char * type;
53    bool isVirtual;
54 };
55
56 // WARNING: PropertyDefine, ClassDefine and DataMemberDefine must remain compatible
57 class PropertyDefine : struct
58 {
59    PropertyDefine prev, next;
60    char * name;
61    MemberType isProperty;
62    char * type;
63
64    bool isWatchable;
65    AccessMode memberAccess;
66    bool isVirtual;
67    bool hasSet, hasGet;
68 };
69
70 // WARNING: PropertyDefine, ClassDefine and DataMemberDefine must remain compatible
71 class DataMemberDefine : struct
72 {
73    DataMemberDefine prev, next;
74    char * name;
75    MemberType isProperty;
76    char * type;
77    OldList dataMembers;
78    OldList classProperties;   // For binary compatibility with ClassDefine
79
80    AccessMode memberAccess;
81    DataMemberType memberType;
82    int size, bitPos;
83 };
84
85 void FreeMethodDefine(MethodDefine method)
86 {
87    delete method.name;
88    delete method.type;
89 }
90
91 void FreeDataMemberDefine(DataMemberDefine dataMember)
92 {
93    delete dataMember.name;
94    delete dataMember.type;
95 }
96
97 void FreeDataDefine(DataDefine data)
98 {
99    delete data.name;
100    delete data.dataType;
101 }
102
103 void FreeDefinition(Definition definition)
104 {
105    delete definition.name;
106    switch(definition.type)
107    {
108       case classDefinition:
109       {
110          ClassDefine classDefine = (ClassDefine)definition;
111          delete classDefine.base;
112          classDefine.methods.Free(FreeMethodDefine);
113          classDefine.propertiesAndMembers.Free(FreeDataMemberDefine);
114          break;
115       }
116       case functionDefinition:
117          delete ((FunctionDefine)definition).dataType;
118          break;
119       case dataDefinition:
120          delete ((DataDefine)definition).dataType;
121          break;
122       case defineDefinition:
123          break;
124    }
125 }
126
127 /////////////////////////////////////
128 static bool globalInstance = false;
129 static Context globalContext { };
130 static OldList defines, imports, precompDefines;
131 static Module privateModule;
132 static OldList _excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left };
133 static NameSpace globalData
134 {
135    classes.CompareKey = (void *)BinaryTree::CompareString;
136    defines.CompareKey = (void *)BinaryTree::CompareString;
137    functions.CompareKey = (void *)BinaryTree::CompareString;
138    nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
139 };
140
141 static void AddDefinitions(ClassDefine classDefine, DataMemberDefine parentMemberDefine, Class regClass, DataMember member, OldList definitions)
142 {
143    if(definitions != null)
144    {
145       ClassDef def;
146       for(def = definitions.first; def; def = def.next)
147       {
148          if(def.type == declarationClassDef)
149          {
150             Declaration decl = def.decl;
151             DataMember dataMember;
152             Type dataType;
153             DataMemberDefine dataMemberDefine;
154
155             if(decl.type == structDeclaration)
156             {
157                Declarator d;
158
159                if(decl.declarators)
160                {
161                   for(d = decl.declarators->first; d; d = d.next)
162                   {
163                      Identifier declId = GetDeclId(d);
164                      //if(d.type != DeclaratorFunction)
165                      if(declId)
166                      {
167                         dataMemberDefine = DataMemberDefine
168                         {
169                            isProperty = MemberType::dataMember;
170                            memberType = normalMember;
171                            name = CopyString(declId.string);
172                         };
173                         parentMemberDefine.dataMembers.Add(dataMemberDefine);
174                         if(regClass && regClass.type == bitClass)
175                         {
176                            Expression sizeExp = d.structDecl.exp, posExp = d.structDecl.posExp;
177                            int bitSize = 0, bitPos = -1;
178                            char dataTypeString[1024];
179                            dataTypeString[0] = '\0';
180
181                            if(sizeExp)
182                            {
183                               ProcessExpressionType(sizeExp);
184                               ComputeExpression(sizeExp);
185                               if(sizeExp.isConstant)
186                                  bitSize = strtol(sizeExp.constant, null, 0);
187                               FreeExpression(sizeExp);
188                            }
189
190                            if(posExp)
191                            {
192                               ProcessExpressionType(posExp);
193                               ComputeExpression(posExp);
194                               if(posExp.isConstant)
195                                  bitPos = strtol(posExp.constant, null, 0);
196                               FreeExpression(posExp);
197
198                            }
199
200                            d.structDecl.exp = null;
201                            d.structDecl.posExp = null;
202
203                            dataType = ProcessType(decl.specifiers, d);
204                            PrintType(dataType, dataTypeString, false, true);
205
206                            //if(!eClass_FindDataMember(regClass, declId.string))
207                            {
208                               BitMember member = eClass_AddBitMember(regClass, declId.string, dataTypeString, 0, 0, def.memberAccess);
209                               if(member)
210                               {
211                                  member.size = bitSize;
212                                  member.pos = bitPos;
213                               }
214                               dataMember = (DataMember)member;
215                            }
216                            if(dataMember)
217                               dataMember.dataType = dataType;
218
219                            dataMemberDefine.size = bitSize;
220                            dataMemberDefine.bitPos = bitPos;
221
222                            dataMemberDefine.type = CopyString(dataTypeString);
223                         }
224                         else
225                         {
226                            //if(!eClass_FindDataMember(regClass, declId.string))
227                            {
228                               char typeString[1024];
229                               typeString[0] = '\0';
230                               dataType = ProcessType(decl.specifiers, d);
231                               PrintType(dataType, typeString, false, true);
232
233                               if(member)
234                                  dataMember = eMember_AddDataMember(member, declId.string,
235                                     typeString, /*ComputeTypeSize(dataType)*/ 0, 0, def.memberAccess);
236                               else
237                                  dataMember = eClass_AddDataMember(regClass, declId.string,
238                                     typeString, /*ComputeTypeSize(dataType)*/ 0, 0, def.memberAccess);
239                               if(dataMember)
240                                  dataMember.dataType = dataType;
241
242                               dataMemberDefine.type = CopyString(typeString);
243                            }
244                         }
245                         dataMemberDefine.memberAccess = def.memberAccess; //(!isMember && regClass.type == structClass) ? true : false;
246                      }
247                   }
248                }
249                else if(decl.specifiers)
250                {
251                   Specifier spec;
252                   // Unnamed struct/union
253                   for(spec = decl.specifiers->first; spec; spec = spec.next)
254                   {
255                      if(spec.type == structSpecifier || spec.type == unionSpecifier)
256                      {
257                         if(spec.definitions && !spec.id)
258                         {
259                            DataMember dataMember = eMember_New((spec.type == unionSpecifier) ? unionMember : structMember, def.memberAccess);
260
261                            dataMemberDefine = DataMemberDefine
262                            {
263                               isProperty = MemberType::dataMember;
264                               memberType = (spec.type == SpecifierType::unionSpecifier) ? unionMember : structMember;
265                            };
266                            parentMemberDefine.dataMembers.Add(dataMemberDefine);
267
268                            AddDefinitions(null, dataMemberDefine, null, dataMember, spec.definitions);
269
270                            if(member)
271                               eMember_AddMember(member, dataMember);
272                            else
273                               eClass_AddMember(regClass, dataMember);
274                         }
275                         else if(spec.definitions && spec.id && spec.definitions->count)
276                         {
277                            //if(isMember || !eClass_FindDataMember(regClass, spec.id.string))
278                            {
279                               Identifier id = spec.id;
280                               char typeString[1024];
281                               typeString[0] = '\0';
282
283                               spec.id = null;
284                               decl.declarators = MkListOne(MkDeclaratorIdentifier(id));
285
286                               dataType = ProcessType(decl.specifiers, null);
287                               PrintType(dataType, typeString, false, true);
288
289                               if(member)
290                                  dataMember = eMember_AddDataMember(member, id.string,
291                                     typeString, /*ComputeTypeSize(dataType)*/ 0, 0, def.memberAccess);
292                               else
293                                  dataMember = eClass_AddDataMember(regClass, id.string,
294                                     typeString, /*ComputeTypeSize(dataType)*/ 0, 0, def.memberAccess);
295
296                               //delete dataTypeString;
297                               if(dataMember)
298                                  dataMember.dataType = dataType;
299                            }
300                         }
301                      }
302                   }
303                }
304             }
305             else if(decl.type == instDeclaration)
306             {
307                Instantiation inst = decl.inst;
308                Expression exp = inst.exp;
309                if(exp)
310                {
311                   // Add data member to the class
312                   //if(!redefinition)
313                   {
314                      char * string = exp.identifier.string;
315                      //if(!eClass_FindDataMember(regClass, string))
316                      {
317                         Type dataType = Type
318                         {
319                            kind = classType;
320                            _class = inst._class.symbol; // FindClass(inst._class.name);
321                            refCount = 1;
322                         };
323                         if(member)
324                            dataMember = eMember_AddDataMember(member, string, inst._class.name, /*ComputeTypeSize(dataType)*/ 0, 0, def.memberAccess);
325                         else
326                            dataMember = eClass_AddDataMember(regClass, string, inst._class.name, /*ComputeTypeSize(dataType)*/ 0, 0, def.memberAccess);
327                         if(dataMember)
328                            dataMember.dataType = dataType;
329                      }
330
331                      dataMemberDefine = DataMemberDefine
332                      {
333                         isProperty = MemberType::dataMember;
334                         memberType = normalMember;
335                         name = CopyString(string);
336                         type = CopyString(inst._class.name);
337                      };
338                      parentMemberDefine.dataMembers.Add(dataMemberDefine);
339                   }
340                }
341             }
342          }
343          else if(def.type == propertyClassDef && def.propertyDef)
344          {
345             PropertyDef propertyDef = def.propertyDef;
346
347             //if(propertyDef.id && (propertyDef.hasGet || propertyDef.hasSet))
348             {
349                Property prop;
350                PropertyDefine propDefine;
351
352                // Register the property in the list
353                {
354                   char * dataTypeString = StringFromSpecDecl(propertyDef.specifiers, propertyDef.declarator);
355                   prop = eClass_AddProperty(regClass, propertyDef.conversion ? null : propertyDef.id.string, dataTypeString, propertyDef.setStmt, propertyDef.getStmt, def.memberAccess);
356                   if(prop)
357                   {
358                      prop.IsSet = (void *)propertyDef.issetStmt;
359                      prop.compiled = false;
360                   }
361                   delete dataTypeString;
362                }
363                //prop.symbol = propertyDef.symbol;
364
365                //method.symbol = func.declarator.symbol;
366
367                if(prop)
368                {
369                   prop.symbol = Symbol
370                   {
371                      string = CopyString(propertyDef.symbol.string);
372                      type = propertyDef.symbol.type;
373                   };
374                   if(propertyDef.symbol.type)
375                      propertyDef.symbol.type.refCount++;
376
377                   //((Symbol)method.symbol).method = method;
378
379
380                   propDefine = PropertyDefine
381                   {
382                      isProperty = propertyMember;
383                      name = prop.conversion ? null : CopyString(prop.name);
384                      type = CopyString(prop.dataTypeString);
385                      isVirtual = false; // No virtual properties for now...
386                      memberAccess = def.memberAccess;
387                      hasSet = propertyDef.setStmt ? true : false;
388                      hasGet = propertyDef.getStmt ? true : false;
389                      isWatchable = propertyDef.isWatchable;
390                   };
391                   classDefine.propertiesAndMembers.Add(propDefine);
392                }
393             }
394          }
395          else if(def.type == classPropertyClassDef && def.propertyDef)
396          {
397             PropertyDef propertyDef = def.propertyDef;
398
399             //if(propertyDef.id && (propertyDef.hasGet || propertyDef.hasSet))
400             {
401                ClassProperty prop;
402                PropertyDefine propDefine;
403                // Register the property in the list
404                {
405                   char * dataTypeString = StringFromSpecDecl(propertyDef.specifiers, propertyDef.declarator);
406                   prop = eClass_AddClassProperty(regClass, propertyDef.id.string, dataTypeString, propertyDef.setStmt, propertyDef.getStmt);
407                   delete dataTypeString;
408                }
409                if(prop)
410                {
411                   propDefine = PropertyDefine
412                   {
413                      name = CopyString(prop.name);
414                      type = CopyString(prop.dataTypeString);
415                      hasSet = propertyDef.setStmt ? true : false;
416                      hasGet = propertyDef.getStmt ? true : false;
417                   };
418                   classDefine.classProperties.Add(propDefine);
419                }
420             }
421          }
422          else if(def.type == classFixedClassDef)
423          {
424             if(classDefine)
425                classDefine.fixed = true;
426          }
427          else if(def.type == classNoExpansionClassDef)
428          {
429             if(classDefine)
430                classDefine.noExpansion = true;
431          }
432          else if(def.type == accessOverrideClassDef)
433          {
434             DataMember member;
435             Property prop;
436             if((prop = eClass_FindProperty(regClass, def.id.string, privateModule)))
437             {
438                PropertyDefine propDefine;
439
440                prop = eClass_AddProperty(regClass, def.id.string, null, null, null, def.memberAccess);
441                if(prop)
442                {
443                   propDefine = PropertyDefine
444                   {
445                      isProperty = propertyMember;
446                      name = CopyString(prop.name);
447                      memberAccess = def.memberAccess;
448                   };
449                   classDefine.propertiesAndMembers.Add(propDefine);
450                }
451             }
452             else if((member = eClass_FindDataMember(regClass, def.id.string, privateModule, null, null)))
453             {
454                DataMemberDefine dataMemberDefine;
455
456                member = eClass_AddDataMember(regClass, def.id.string, null, 0, 0, def.memberAccess);
457
458                dataMemberDefine = DataMemberDefine
459                {
460                   isProperty = dataMember;
461                   memberType = normalMember;
462                   name = CopyString(def.id.string);
463                   memberAccess = def.memberAccess;
464                };
465                parentMemberDefine.dataMembers.Add(dataMemberDefine);
466             }
467          }
468       }
469    }
470 }
471
472 static void ProcessClass(ClassType classType, OldList definitions, Symbol symbol, OldList baseSpecs, OldList enumValues, bool isWatchable, AccessMode declMode)
473 {
474    Class regClass;
475    ClassDef def;
476    ClassDefine classDefine;
477    char baseName[1024];
478    bool unitType = false;
479    bool wouldBeEnum = false;
480    AccessMode inheritanceAccess = publicAccess;
481    baseName[0] = '\0';
482
483    if(baseSpecs != null)
484    {
485       Type baseType = ProcessType(baseSpecs, null);
486       PrintType(baseType, baseName, false, true);
487       if(baseType.kind == TypeKind::classType)
488       {
489          if(baseType._class.registered && classType == normalClass)
490          {
491             if(baseType._class.registered.type == unitClass)
492                classType = unitClass;
493             else if(baseType._class.registered.type == bitClass)
494                classType = bitClass;
495             else if(baseType._class.registered.type == noHeadClass)
496                classType = noHeadClass;
497             else if(baseType._class.registered.type == enumClass)
498             {
499                wouldBeEnum = true;
500                // classType = enumClass;
501             }
502          }
503       }
504       else if(baseType.kind == structType || baseType.kind == unionType)
505       {
506          classType = noHeadClass;
507          baseName[0] = '\0';
508       }
509       else
510          unitType = true;
511       FreeType(baseType);
512
513       if(((Specifier)baseSpecs.first).type == baseSpecifier && ((Specifier)baseSpecs.first).specifier == PRIVATE)
514          inheritanceAccess = privateAccess;
515    }
516
517    // Eventually compute size with declarations for optional constant size offset...
518
519    // If there's any struct declaration in a unit data type, it means this is a bit class
520    if(classType == normalClass)
521    {
522       if(unitType) classType = unitClass;
523       if(definitions != null)
524       {
525          for(def = definitions.first; def; def = def.next)
526          {
527             if(def.type == declarationClassDef)
528             {
529                Declaration decl = def.decl;
530                if(decl.type == structDeclaration)
531                {
532                   if(unitType)
533                   {
534                      classType = bitClass;
535                      break;
536                   }
537                   if(decl.declarators)
538                   {
539                      Declarator d;
540
541                      for(d = decl.declarators->first; d; d = d.next)
542                      {
543                         if(d.structDecl.exp)
544                         {
545                            classType = bitClass;
546                            break;
547                         }
548                      }
549                      if(d) break;
550                   }
551                }
552             }
553          }
554       }
555    }
556    if(classType == normalClass && wouldBeEnum) classType = enumClass;
557
558    regClass = symbol.registered = eSystem_RegisterClass((classType == unionClass) ? structClass : classType, symbol.string, baseName[0] ? baseName : null, 0, 0, null, null, privateModule, publicAccess, inheritanceAccess);
559    if(regClass)
560       regClass.symbol = symbol;
561
562    classDefine = ClassDefine
563    {
564       type = classDefinition;
565       name = CopyString(symbol.string);
566       base = baseName[0] ? CopyString(baseName) : null;
567       isStatic = declMode == staticAccess;
568       isRemote = symbol.isRemote;
569       isWatchable = isWatchable;
570    };
571    precompDefines.Add(classDefine);
572
573    if(classType == unionClass)
574    {
575       DataMember unionMember = eMember_New(DataMemberType::unionMember, publicAccess);
576       DataMemberDefine unionDefine;
577
578       unionDefine = DataMemberDefine
579       {
580          isProperty = dataMember;
581          memberType = DataMemberType::unionMember;
582       };
583       classDefine.propertiesAndMembers.Add(unionDefine);
584
585       AddDefinitions(classDefine, unionDefine, regClass, unionMember, definitions);
586       eClass_AddMember(regClass, unionMember);
587    }
588    else if(regClass)
589       AddDefinitions(classDefine, (DataMemberDefine)classDefine, regClass, null, definitions);
590
591    // Do the functions
592    if(definitions != null)
593    {
594       for(def = definitions.first; def; def = def.next)
595       {
596          if(def.type == functionClassDef)
597          {
598             ClassFunction func = def.function;
599             // Add ecereMethod_[class]_ to the declarator
600             if(!func.dontMangle && func.declarator)
601             {
602                Identifier id = GetDeclId(func.declarator);
603                Method method;
604                MethodDefine methodDefine;
605
606                {
607                   char * dataTypeString  = StringFromSpecDecl(func.specifiers, func.declarator);
608                   if(func.isVirtual)
609                      method = eClass_AddVirtualMethod(regClass, id.string, dataTypeString, func.declarator.symbol, def.memberAccess);
610                   else
611                      method = eClass_AddMethod(regClass, id.string, dataTypeString, func.declarator.symbol, def.memberAccess);
612                   delete dataTypeString;
613                }
614
615                // Should we make a copy here? We make a copy in pass0.c ...
616                //method.symbol = func.declarator.symbol;
617
618                if(method)
619                {
620                   method.symbol = Symbol
621                   {
622                      string = CopyString(func.declarator.symbol.string);
623                      type = func.declarator.symbol.type;
624                   };
625                   if(func.declarator.symbol.type)
626                      func.declarator.symbol.type.refCount++;
627
628                   ((Symbol)method.symbol).method = method;
629
630
631                   func.declarator.symbol = null;
632
633                   if(method.type != virtualMethod || method._class == regClass)
634                   {
635                      methodDefine = MethodDefine
636                      {
637                         name = CopyString(method.name);
638                         type = CopyString(method.dataTypeString);
639                         memberAccess = def.memberAccess;
640                         isVirtual = method.type == virtualMethod;
641                      };
642                      classDefine.methods.Add(methodDefine);
643                   }
644                }
645             }
646          }
647          else if(def.type == accessOverrideClassDef)
648          {
649             Method method;
650             if((method = eClass_FindMethod(regClass, def.id.string, privateModule)))
651             {
652                MethodDefine methodDefine;
653
654                method = eClass_AddMethod(regClass, def.id.string, null, null, def.memberAccess);
655
656                methodDefine = MethodDefine
657                {
658                   name = CopyString(method.name);
659                   memberAccess = def.memberAccess;
660                };
661                classDefine.methods.Add(methodDefine);
662             }
663          }
664       }
665    }
666    if(regClass && symbol.templateParams)
667    {
668       TemplateParameter param;
669       // Add template parameters here
670       for(param = symbol.templateParams->first; param; param = param.next)
671       {
672          ClassTemplateArgument defaultArg { };
673          if(param.defaultArgument)
674          {
675             switch(param.type)
676             {
677                case type:
678                   defaultArg.dataTypeString =
679                      StringFromSpecDecl(param.defaultArgument.templateDatatype.specifiers, param.defaultArgument.templateDatatype.decl);
680                   break;
681                case identifier:
682                {
683                   char memberString[1024];
684                   memberString[0] = '\0';
685
686                   if(param.defaultArgument.identifier._class && param.defaultArgument.identifier._class.name)
687                   {
688                      if(param.defaultArgument.identifier._class.type == templateTypeSpecifier)
689                         strcpy(memberString, param.defaultArgument.identifier._class.templateParameter.identifier.string);
690                      else
691                         strcpy(memberString, param.defaultArgument.identifier._class.name);
692                   }
693
694                   if(memberString[0])
695                   {
696                      strcat(memberString, "::");
697                   }
698                   strcat(memberString, param.defaultArgument.identifier.string);
699                   defaultArg.memberString = CopyString(memberString);
700                   break;
701                }
702 /*                  switch(param.memberType)
703                   {
704                      case dataMember:
705                         defaultArg.member = eClass_FindDataMember(regClass, param.defaultArgument.identifier.string, regClass.module, null, null);
706                         break;
707                      case method:
708                         defaultArg.method = eClass_FindMethod(regClass, param.defaultArgument.identifier.string, regClass.module);
709                         break;
710                      case prop:
711                         defaultArg.prop = eClass_FindProperty(regClass, param.defaultArgument.identifier.string, regClass.module);
712                         break;
713                   }
714                   break;*/
715                case expression:
716                {
717                   Operand op;
718                   ProcessExpressionType(param.defaultArgument.expression);
719                   ComputeExpression(param.defaultArgument.expression);
720                   op = GetOperand(param.defaultArgument.expression);
721                   defaultArg.expression.ui64 = op.ui64;
722                   break;
723                }
724             }
725          }
726          if(param.type == identifier)
727          {
728             eClass_AddTemplateParameter(regClass, param.identifier.string, param.type, (void *)(uintptr)param.memberType, defaultArg);
729          }
730          else
731          {
732             char * typeString = param.dataType ? StringFromSpecDecl(param.dataType.specifiers, param.dataType.decl) : null;
733             eClass_AddTemplateParameter(regClass, param.identifier.string, param.type, typeString, defaultArg);
734
735             /*eClass_AddTemplateParameter(regClass, param.identifier.string, param.type,
736                (param.type == type) ? eSystem_FindClass(regClass.module, typeString) : CopyString(typeString), defaultArg);*/
737             // delete typeString;
738          }
739
740       }
741    }
742 }
743
744 static void ProcessClassEnumValues(ClassType classType, OldList definitions, Symbol symbol, OldList baseSpecs, OldList enumValues)
745 {
746    Class regClass = symbol.registered;
747    if(regClass && enumValues)
748    {
749       Enumerator e;
750       for(e = enumValues.first; e; e = e.next)
751       {
752          if(e.exp)
753          {
754             Type destType
755             {
756                kind = int64Type;
757                refCount = 1;
758             };
759             e.exp.destType = destType;
760
761             // Set parsingType to avoid producing errors
762             SetParsingType(true);
763             ProcessExpressionType(e.exp);
764             SetParsingType(false);
765
766             if(!e.exp.expType)
767             {
768                destType.kind = TypeKind::classType;
769                destType._class = symbol;
770                ProcessExpressionType(e.exp);
771             }
772             if(e.exp.isConstant)
773             {
774                if(e.exp.type == identifierExp && e.exp.expType && e.exp.identifier && e.exp.identifier.string && e.exp.expType.kind == enumType)
775                {
776                   // Resolve enums here
777                   NamedLink64 l;
778                   char * string = e.exp.identifier.string;
779                   for(l = e.exp.expType.members.first; l; l = l.next)
780                   {
781                      if(!strcmp(l.name, string))
782                      {
783                         if(l.data)
784                         {
785                            FreeExpContents(e.exp);
786                            e.exp.type = constantExp;
787                            e.exp.constant = PrintInt64(l.data);
788                            FreeType(e.exp.expType);
789                            e.exp.expType = ProcessTypeString("int64", false);
790                         }
791                         break;
792                      }
793                   }
794                }
795                else
796                   ComputeExpression(e.exp);
797             }
798             if(e.exp.isConstant && e.exp.type == constantExp)
799             {
800                Operand op = GetOperand(e.exp);
801                int64 value;
802                //value = strtol(e.exp.string, null, 0);
803                switch(op.kind)
804                {
805                   case charType:
806                      value = op.type.isSigned ? (int64)op.c : (int64)op.uc;
807                      break;
808                   case shortType:
809                      value = op.type.isSigned ? (int64)op.s : (int64)op.us;
810                      break;
811                   case int64Type:
812                      value = op.type.isSigned ? (int64)op.i64 : (int64)op.ui64;
813                      break;
814                   case intType:
815                   default:
816                      value = op.type.isSigned ? (int64)op.i : (int)op.ui;
817                }
818                eEnum_AddFixedValue(regClass, e.id.string, value);
819             }
820             else
821             {
822                char expString[8192];
823                expString[0] = 0;
824                PrintExpression(e.exp, expString);
825                printf($"error: could not resolve value %s for enum %s in precompiler\n", expString, regClass.name);
826                ((PrecompApp)__thisModule).exitCode = 1;
827                eEnum_AddValue(regClass, e.id.string);
828             }
829          }
830          else
831             eEnum_AddValue(regClass, e.id.string);
832       }
833    }
834 }
835
836 void PreCompPreProcessClassDefinitions()
837 {
838    OldList * ast = GetAST();
839    External external, next;
840    for(external = ast->first; external; external = next)
841    {
842       next = external.next;
843       if(external.type == classExternal)
844       {
845          ClassDefinition _class = external._class;
846          if(_class.declMode == publicAccess || _class.declMode == privateAccess || _class.declMode == staticAccess)
847          {
848             if(_class.definitions)
849             {
850                ProcessClass(normalClass, _class.definitions, _class.symbol, _class.baseSpecs, null, _class.deleteWatchable, _class.declMode);
851             }
852          }
853       }
854       else if(external.type == declarationExternal)
855       {
856          Declaration declaration = external.declaration;
857
858          if(declaration.type == initDeclaration)
859          {
860             if(external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess || external.declaration.declMode == staticAccess)
861             {
862                if(declaration.specifiers)
863                {
864                   Specifier specifier;
865                   for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
866                   {
867                      if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string &&
868                         (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
869                      {
870                         Symbol symbol = FindClass(specifier.id.string);
871                         if(symbol)
872                         {
873                            ClassType classType;
874
875                            if(specifier.type == enumSpecifier)
876                               classType = enumClass;
877                            else if(specifier.type == unionSpecifier)
878                               classType = unionClass;
879                            else
880                               classType = structClass;
881                            ProcessClass(classType, specifier.definitions, symbol, specifier.baseSpecs, specifier.list, false, external.declaration.declMode);
882                         }
883                      }
884                   }
885                }
886                if(external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess)
887                {
888                   if(declaration.declarators)
889                   {
890                      InitDeclarator d;
891                      for(d = declaration.declarators->first; d; d = d.next)
892                      {
893                         if(d.declarator)
894                         {
895                            Symbol symbol = d.declarator.symbol;
896                            if(symbol)
897                            {
898                               DataDefine dataDefine;
899                               char typeString[1024];
900                               typeString[0] = '\0';
901                               PrintType(symbol.type, typeString, false, true);
902                               dataDefine = DataDefine
903                               {
904                                  type = dataDefinition;
905                                  name = CopyString(symbol.string);
906                                  dataType = CopyString(typeString);
907                               };
908                               precompDefines.Add(dataDefine);
909                            }
910                         }
911                      }
912                   }
913                }
914             }
915          }
916          else if(declaration.type == instDeclaration)
917          {
918             if(external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess)
919             {
920                Symbol symbol = declaration.inst.symbol;
921                if(symbol)
922                {
923                   DataDefine dataDefine;
924                   char typeString[1024];
925                   typeString[0] = '\0';
926                   PrintType(symbol.type, typeString, false, true);
927                   dataDefine = DataDefine
928                   {
929                      type = dataDefinition;
930                      name = CopyString(symbol.string);
931                      dataType = CopyString(typeString);
932                   };
933                   precompDefines.Add(dataDefine);
934                }
935             }
936             globalInstance = true;
937          }
938          else if(declaration.type == defineDeclaration)
939          {
940             if(external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess)
941             {
942                Define definition
943                {
944                   type = defineDefinition;
945                   name = CopyString(declaration.id.string);
946                   exp = declaration.exp;
947                };
948                precompDefines.Add(definition);
949             }
950          }
951       }
952       else if(external.type == functionExternal && (external.function.declMode == publicAccess || external.function.declMode == privateAccess))
953       {
954          FunctionDefinition function = external.function;
955          FunctionDefine functionDefine;
956          char typeString[1024];
957          typeString[0] = '\0';
958          PrintType(function.declarator.symbol.type, typeString, true, true);
959          functionDefine = FunctionDefine
960          {
961             type = functionDefinition;
962             name = CopyString(function.declarator.symbol.string);
963             dataType = CopyString(typeString);
964          };
965          precompDefines.Add(functionDefine);
966       }
967       else if(external.type == nameSpaceExternal)
968       {
969          SetCurrentNameSpace(external.id.string); //currentNameSpace = external.id.string;
970          //currentNameSpaceLen = currentNameSpace ? strlen(currentNameSpace) : 0;
971       }
972    }
973
974    ComputeModuleClasses(privateModule);
975
976    // Second pass for enumeration values
977    for(external = ast->first; external; external = next)
978    {
979       next = external.next;
980       if(external.type == declarationExternal && (external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess))
981       {
982          Declaration declaration = external.declaration;
983
984          if(declaration.type == initDeclaration)
985          {
986             if(declaration.specifiers)
987             {
988                Specifier specifier;
989                for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
990                {
991                   if((specifier.type == enumSpecifier) && specifier.id && specifier.id.string &&
992                      (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
993                   {
994                      Symbol symbol = FindClass(specifier.id.string);
995                      if(symbol)
996                      {
997                         ProcessClassEnumValues(enumClass, specifier.definitions, symbol, specifier.baseSpecs, specifier.list);
998                      }
999                   }
1000                }
1001             }
1002          }
1003       }
1004    }
1005 }
1006
1007 static void OutputDataMembers(ClassDefine classDefine, Class _class, File f)
1008 {
1009    if(classDefine.propertiesAndMembers.first)
1010    {
1011       DataMemberDefine member = classDefine.propertiesAndMembers.first;
1012       MemberType last = unresolvedMember;
1013
1014       for(member = classDefine.propertiesAndMembers.first; member; member = member.next)
1015       {
1016          if(member.isProperty == propertyMember)
1017          {
1018             PropertyDefine prop = (PropertyDefine)member;
1019             if(last != propertyMember)
1020             {
1021                if(last)
1022                   f.Printf("         .\n");
1023                f.Printf("      [Defined Properties]\n");
1024             }
1025
1026             if(prop.name)
1027                f.Printf("         %s\n", prop.name);
1028             else
1029                f.Printf("         [Conversion]\n");
1030             if(prop.memberAccess == publicAccess)
1031                f.Printf("            [Public]\n");
1032             else
1033                f.Printf("            [Private]\n");
1034             if(prop.isVirtual)
1035                f.Printf("            [Virtual]\n");
1036             if(prop.hasSet)
1037                f.Printf("            [Set]\n");
1038             if(prop.hasGet)
1039                f.Printf("            [Get]\n");
1040             if(prop.isWatchable)
1041                f.Printf("            [Watchable]\n");
1042             f.Printf("            [Type]\n");
1043             f.Printf("               %s\n", prop.type ? prop.type : "");
1044          }
1045          else
1046          {
1047             if(last != dataMember)
1048             {
1049                if(last)
1050                   f.Printf("         .\n");
1051                f.Printf("      [Defined Data Members]\n");
1052             }
1053             if(member.memberType == normalMember)
1054             {
1055                f.Printf("         %s\n", member.name);
1056                if(member.memberAccess == publicAccess)
1057                   f.Printf("            [Public]\n");
1058                else
1059                   f.Printf("            [Private]\n");
1060                if(_class && _class.type == bitClass)
1061                {
1062                   if(member.size)
1063                   {
1064                      f.Printf("            [Size]\n");
1065                      f.Printf("               %d\n", member.size);
1066                   }
1067                   if(member.bitPos != -1)
1068                   {
1069                      f.Printf("            [Pos]\n");
1070                      f.Printf("               %d\n", member.bitPos);
1071                   }
1072                }
1073                f.Printf("            [Type]\n");
1074                f.Printf("               %s\n", member.type ? member.type : "");
1075             }
1076             else
1077             {
1078                if(member.memberAccess == publicAccess)
1079                   f.Printf("            [Public]\n");
1080                else
1081                   f.Printf("            [Private]\n");
1082                f.Printf((member.memberType == unionMember) ? "      [Union]\n" : "      [Struct]\n");
1083                OutputDataMembers((ClassDefine)member, null, f);
1084             }
1085          }
1086          last = member.isProperty;
1087       }
1088       f.Printf("         .\n");
1089    }
1090
1091    if(classDefine.classProperties.first)
1092    {
1093       PropertyDefine prop = classDefine.propertiesAndMembers.first;
1094       f.Printf("      [Defined Class Properties]\n");
1095       for(prop = classDefine.classProperties.first; prop; prop = prop.next)
1096       {
1097          if(prop.name)
1098             f.Printf("         %s\n", prop.name);
1099          if(prop.hasSet)
1100             f.Printf("            [Set]\n");
1101          if(prop.hasGet)
1102             f.Printf("            [Get]\n");
1103          f.Printf("            [Type]\n");
1104          f.Printf("               %s\n", prop.type ? prop.type : "");
1105       }
1106       f.Printf("         .\n");
1107    }
1108 }
1109
1110 static void OutputSymbols(const char * fileName)
1111 {
1112    File f = FileOpen(fileName, write);
1113    if(f)
1114    {
1115       DefinitionType lastType = (DefinitionType)-1;
1116       Definition definition;
1117
1118       if(globalInstance)
1119          f.Printf("[Global Instance]\n");
1120
1121       for(definition = precompDefines.first; definition; definition = definition.next)
1122       {
1123          if(definition.type != lastType)
1124          {
1125             if(lastType != (DefinitionType)-1)
1126                f.Printf("   .\n");
1127             if(definition.type == moduleDefinition)
1128                f.Printf("[Imported Modules]\n");
1129             else if(definition.type == classDefinition)
1130                f.Printf("[Defined Classes]\n");
1131             else if(definition.type == defineDefinition)
1132                f.Printf("[Defined Expressions]\n");
1133             else if(definition.type == functionDefinition)
1134                f.Printf("[Defined Functions]\n");
1135             else if(definition.type == dataDefinition)
1136                f.Printf("[Defined Data]\n");
1137             lastType = definition.type;
1138          }
1139          if(definition.type == moduleDefinition)
1140          {
1141             ImportedModule module = (ImportedModule) definition;
1142
1143             if(module.importType == staticImport)
1144                f.Printf("   [Static]\n");
1145             else if(module.importType == remoteImport)
1146                f.Printf("   [Remote]\n");
1147             if(module.importAccess == privateAccess)
1148                f.Printf("   [Private]\n");
1149             f.Printf("   %s\n", module.name);
1150          }
1151          else if(definition.type == classDefinition)
1152          {
1153             // Can we do this? Or should we fill up the definition?
1154             Class _class = eSystem_FindClass(privateModule, definition.name);
1155             ClassDefine classDefine = (ClassDefine) definition;
1156
1157             f.Printf("   %s\n", definition.name);
1158             if(classDefine.isStatic)
1159                f.Printf("      [Static]\n");
1160             if(classDefine.fixed)
1161                f.Printf("      [Fixed]\n");
1162             if(classDefine.noExpansion)
1163                f.Printf("      [No Expansion]\n");
1164             if(classDefine.isRemote)
1165                f.Printf("      [Remote]\n");
1166             if(classDefine.isWatchable)
1167                f.Printf("      [Watchable]\n");
1168             if(_class.type == enumClass)
1169                f.Printf("      [Enum]\n");
1170             else if(_class.type == bitClass)
1171                f.Printf("      [Bit]\n");
1172             else if(_class.type == structClass)
1173                f.Printf("      [Struct]\n");
1174             else if(_class.type == unitClass)
1175                f.Printf("      [Unit]\n");
1176             else if(_class.type == noHeadClass)
1177                f.Printf("      [NoHead]\n");
1178
1179             if(_class.inheritanceAccess == privateAccess)
1180                f.Printf("      [Private Base]\n");
1181             else
1182                f.Printf("      [Base]\n");
1183             if(classDefine.base)
1184                f.Printf("         %s\n", classDefine.base);
1185             else
1186                f.Printf("         [None]\n");
1187
1188             if(_class.templateParams.count)
1189             {
1190                ClassTemplateParameter param;
1191                TemplateParameter tp;
1192
1193                f.Printf("         [Template Parameters]\n");
1194
1195                for(tp = ((Symbol)_class.symbol).templateParams->first, param = _class.templateParams.first; param && tp; param = param.next, tp = tp.next)
1196                {
1197                   f.Printf("               %s\n", param.name);
1198                   switch(param.type)
1199                   {
1200                      case type:
1201                         f.Printf("               [Type]\n");
1202                         f.Printf("               %s\n", param.dataTypeString ? param.dataTypeString : "[None]");
1203                         f.Printf("               %s\n", param.defaultArg.dataTypeString ? param.defaultArg.dataTypeString : "[None]");
1204                         break;
1205                      case expression:
1206                         f.Printf("               [Expression]\n");
1207                         f.Printf("               %s\n", param.dataTypeString ? param.dataTypeString : "[None]");
1208                         if(tp.defaultArgument && tp.defaultArgument.expression)
1209                         {
1210                            char temp[8192];
1211                            temp[0] = 0;
1212                            PrintExpression(tp.defaultArgument.expression, temp);
1213                            ChangeCh(temp, '\n', ' ');
1214                            f.Printf("               ");
1215                            f.Puts(temp);
1216                            f.Puts("\n");
1217                         }
1218                         else
1219                            f.Printf("               [None]\n");
1220                         break;
1221                      case identifier:
1222                         f.Printf("               [Identifier]\n");
1223                         f.Printf("               %s\n", (param.memberType == dataMember) ? "[Data member]" : ((param.memberType == method) ? "[Method]" : "[Property]"));
1224                         if(tp.defaultArgument && tp.defaultArgument.identifier)
1225                         {
1226                            f.Printf("               ");
1227                            if(tp.defaultArgument.identifier._class && tp.defaultArgument.identifier._class.type == nameSpecifier &&
1228                               tp.defaultArgument.identifier._class.name)
1229                            {
1230                               f.Printf("%s::", tp.defaultArgument.identifier._class.name);
1231                            }
1232                            else if(tp.defaultArgument.identifier._class && tp.defaultArgument.identifier._class.type == templateTypeSpecifier &&
1233                               tp.defaultArgument.identifier._class.templateParameter.identifier)
1234                            {
1235                               f.Printf("%s::", tp.defaultArgument.identifier._class.templateParameter.identifier.string);
1236                            }
1237                            f.Printf("%s\n", tp.defaultArgument.identifier.string);
1238                         }
1239                         else
1240                         {
1241                            f.Printf("               [None]\n");
1242                         }
1243                         break;
1244                   }
1245                }
1246                f.Printf("         .\n");
1247             }
1248
1249             if(!classDefine.isStatic)
1250             {
1251                if(classDefine.methods.first)
1252                {
1253                   MethodDefine method;
1254
1255                   f.Printf("      [Defined Methods]\n");
1256                   for(method = classDefine.methods.first; method; method = method.next)
1257                   {
1258                      f.Printf("         %s\n", method.name);
1259                      if(method.memberAccess == publicAccess)
1260                         f.Printf("            [Public]\n");
1261                      else
1262                         f.Printf("            [Private]\n");
1263                      if(method.isVirtual)
1264                         f.Printf("            [Virtual]\n");
1265                      f.Printf("            [Type]\n");
1266                      f.Printf("               %s\n", method.type ? method.type : "");
1267                   }
1268                   f.Printf("         .\n");
1269                }
1270
1271                OutputDataMembers(classDefine, _class, f);
1272
1273                if(_class.type == enumClass)
1274                {
1275                   NamedLink64 value;
1276                   Class enumClass = eSystem_FindClass(privateModule, "enum");
1277                   EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
1278
1279                   f.Printf("      [Enum Values]\n");
1280                   for(value = e.values.first; value; value = value.next)
1281                   {
1282                      f.Printf("         %s = ", value.name);
1283                      // We can have a null _class.dataTypeString here if the enum uses a base defined in another module yet to be precompiled
1284                      if(_class.dataTypeString && !strcmp(_class.dataTypeString, "uint64") && *(uint64 *)&value.data > MAXINT64)
1285                         f.Printf(FORMAT64HEX, *(uint64 *)&value.data);
1286                      else
1287                         f.Printf(FORMAT64D, value.data);
1288                      f.Printf("\n");
1289                   }
1290                   f.Printf("         .\n");
1291                }
1292             }
1293          }
1294          else if(definition.type == defineDefinition)
1295          {
1296             Define defineDefine = (Define) definition;
1297             f.Printf("   %s\n", definition.name);
1298             f.Printf("      [Value]\n");
1299             f.Printf("         ");
1300             OutputExpression(defineDefine.exp, f);
1301             f.Printf("\n");
1302          }
1303          else if(definition.type == functionDefinition)
1304          {
1305             FunctionDefine functionDefine = (FunctionDefine) definition;
1306             f.Printf("   %s\n", functionDefine.name);
1307             f.Printf("      [Type]\n");
1308             f.Printf("         %s\n", functionDefine.dataType);
1309          }
1310          else if(definition.type == dataDefinition)
1311          {
1312             DataDefine dataDefine = (DataDefine) definition;
1313             f.Printf("   %s\n", dataDefine.name);
1314             f.Printf("      [Type]\n");
1315             f.Printf("         %s\n", dataDefine.dataType);
1316          }
1317       }
1318       f.Printf("   .\n");
1319       delete f;
1320    }
1321 }
1322
1323 class PrecompApp : Application
1324 {
1325    void Main()
1326    {
1327       int c;
1328       bool valid = true;
1329       char defaultSymFile[MAX_LOCATION];
1330       char * cppCommand = null;
1331       char * cppOptions = null;
1332       int cppOptionsLen = 0;
1333       /*char ** argv = null;
1334       int argc = 0;*/
1335
1336       Platform targetPlatform = __runtimePlatform;
1337       int targetBits = GetHostBits();
1338       /*
1339       for(c = 0; c<this.argc; c++)
1340       {
1341          char * arg = this.argv[c];
1342          int argLen = strlen(arg);
1343
1344          argv = renew argv char *[argc + 1];
1345          argv[argc] = new char[argLen+1];
1346          strcpy(argv[argc], arg);
1347
1348          while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
1349          {
1350             int len;
1351
1352             c++;
1353             arg = this.argv[c];
1354             len = strlen(arg);
1355             argv[argc] = renew argv[argc] char[argLen + len + 1];
1356
1357             argv[argc][argLen-1] = ' ';
1358             strcpy(argv[argc] + argLen, arg);
1359             argLen += len;
1360          }
1361          argc++;
1362       }*/
1363
1364 #if 0 //def _DEBUG
1365       printf("\nArguments given:\n");
1366       for(c=1; c<argc; c++)
1367          printf(" %s", argv[c]);
1368       printf("\n\n");
1369       for(c=1; c<argc; c++)
1370          PrintLn("Arg", c, ": ", argv[c]);
1371       printf("\n");
1372       //getch();
1373 #endif
1374
1375       for(c = 1; c<argc; c++)
1376       {
1377          const char * arg = argv[c];
1378          if(arg[0] == '-')
1379          {
1380             if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64"))
1381             {
1382                int newLen = cppOptionsLen + 1 + strlen(arg);
1383                cppOptions = renew cppOptions char[newLen + 1];
1384                cppOptions[cppOptionsLen] = ' ';
1385                strcpy(cppOptions + cppOptionsLen + 1, arg);
1386                cppOptionsLen = newLen;
1387                targetBits = !strcmp(arg + 1, "m32") ? 32 : 64;
1388             }
1389             else if(!strcmp(arg + 1, "t32") || !strcmp(arg + 1, "t64"))
1390             {
1391                targetBits = !strcmp(arg + 1, "t32") ? 32 : 64;
1392             }
1393             else if(arg[1] == 'D' || arg[1] == 'I')
1394             {
1395                char * buf;
1396                int size = cppOptionsLen + 1 + strlen(arg) * 2 + 1;
1397                cppOptions = renew cppOptions char[size];
1398                buf = cppOptions + cppOptionsLen;
1399                *buf++ = ' ';
1400                PassArg(buf, arg);
1401                cppOptionsLen = cppOptionsLen + 1 + strlen(buf);
1402             }
1403             else if(!strcmp(arg+1, "t"))
1404             {
1405                if(++c < argc)
1406                   targetPlatform = argv[c];
1407                else
1408                   valid = false;
1409             }
1410             else if(!strcmp(arg+1, "cpp"))
1411             {
1412                if(++c < argc)
1413                   cppCommand = CopyString(argv[c]);
1414                else
1415                   valid = false;
1416             }
1417             else if(!strcmp(arg+1, "o"))
1418             {
1419                if(!GetOutputFile() && c + 1 < argc)
1420                {
1421                   SetOutputFile(argv[c+1]);
1422                   c++;
1423                }
1424                else
1425                   valid = false;
1426             }
1427             else if(!strcmp(arg+1, "c"))
1428             {
1429                if(!GetSourceFile() && c + 1 < argc)
1430                {
1431                   SetSourceFile(argv[c+1]);
1432                   c++;
1433                }
1434                else
1435                   valid = false;
1436             }
1437             else if(!strcmp(arg+1, "isystem") || !strcmp(arg+1, "isysroot") || !strcmp(arg+1, "s"))
1438             {
1439                if(c + 1 < argc)
1440                {
1441                   char * buf;
1442                   const char * arg1 = argv[++c];
1443                   int size = cppOptionsLen + 1 + strlen(arg) * 2 + strlen(arg1) * 2 + 1;
1444                   cppOptions = renew cppOptions char[size];
1445                   buf = cppOptions + cppOptionsLen;
1446                   *buf++ = ' ';
1447                   buf = PassArg(buf, arg);
1448                   *buf++ = ' ';
1449                   buf = PassArg(buf, arg1);
1450                   cppOptionsLen = buf - cppOptions;
1451                }
1452                else
1453                   valid = false;
1454             }
1455             else if(!strcmp(arg+1, "fno-diagnostics-show-caret"))
1456             {
1457                char * buf;
1458                int size = cppOptionsLen + 1 + strlen(arg) * 2 + 1;
1459                cppOptions = renew cppOptions char[size];
1460                buf = cppOptions + cppOptionsLen;
1461                *buf++ = ' ';
1462                PassArg(buf, arg);
1463                cppOptionsLen = cppOptionsLen + 1 + strlen(buf);
1464             }
1465             else if(!strcmp(arg+1, "symbols"))
1466             {
1467                if(c + 1 < argc)
1468                {
1469                   SetSymbolsDir(argv[c+1]);
1470                   c++;
1471                }
1472                else
1473                   valid = false;
1474             }
1475             else if(!strcmp(arg+1, "defaultns"))
1476             {
1477                if(c + 1 < argc)
1478                {
1479                   SetDefaultNameSpace(argv[c+1]);
1480                   //defaultNameSpaceLen = strlen(argv[c+1]);
1481                   c++;
1482                }
1483                else
1484                   valid = false;
1485             }
1486             else if(!strcmp(arg+1, "strictns"))
1487             {
1488                SetStrictNameSpaces(true);
1489             }
1490             else if(!strcmp(arg+1, "module"))
1491             {
1492                if(c + 1 < argc)
1493                {
1494                   SetI18nModuleName(argv[c+1]);
1495                   c++;
1496                }
1497                else
1498                   valid = false;
1499             }
1500          }
1501          else
1502             valid = false;
1503       }
1504       if(valid)
1505       {
1506          if(!cppCommand)
1507             cppCommand = CopyString("gcc");
1508          if(!GetSourceFile())
1509             valid = false;
1510          else if(!GetOutputFile())
1511          {
1512             strcpy(defaultSymFile, GetSymbolsDir());
1513             PathCat(defaultSymFile, GetSourceFile());
1514             ChangeExtension(defaultSymFile, "sym", defaultSymFile);
1515             SetOutputFile(defaultSymFile);
1516          }
1517       }
1518
1519       if(!valid)
1520       {
1521          printf("%s", $"Syntax:\n   ecp [-t <target platform>] [-cpp <c preprocessor>] [-o <output>] [-symbols <outputdir>] [-I<includedir>]* [-isystem <sysincludedir>]* [-D<definition>]* -c <input>\n");
1522       }
1523       else
1524       {
1525          DualPipe cppOutput;
1526          // TODO: Improve this
1527          char command[MAX_F_STRING*3];
1528          SetGlobalData(&globalData);
1529          SetExcludedSymbols(&_excludedSymbols);
1530          SetGlobalContext(globalContext);
1531          SetCurrentContext(globalContext);
1532          SetTopContext(globalContext);
1533          SetDefines(&::defines);
1534          SetImports(&imports);
1535          SetInPreCompiler(true);
1536          SetPrecompDefines(&precompDefines);
1537          SetTargetPlatform(targetPlatform);
1538          SetTargetBits(targetBits);
1539          SetEchoOn(false);
1540
1541          privateModule = (Module)__ecere_COM_Initialize((bool)(true | (targetBits == sizeof(uintptr)*8 ? 0 : targetBits == 64 ? 2 : targetBits==32 ? 4 : 0) | 8), 1, null);
1542          SetPrivateModule(privateModule);
1543
1544          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint"), type = ProcessTypeString("unsigned int", false) });
1545          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint64"), type = ProcessTypeString("unsigned int64", false) });
1546          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint32"), type = ProcessTypeString("unsigned int", false) });
1547          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint16"), type = ProcessTypeString("unsigned short", false) });
1548          globalContext.types.Add((BTNode)Symbol { string = CopyString("byte"), type = ProcessTypeString("unsigned char", false) });
1549          globalContext.types.Add((BTNode)Symbol { string = CopyString("intptr_t"), type = ProcessTypeString("intptr", false) });
1550          globalContext.types.Add((BTNode)Symbol { string = CopyString("uintptr_t"), type = ProcessTypeString("uintptr", false) });
1551          globalContext.types.Add((BTNode)Symbol { string = CopyString("ssize_t"), type = ProcessTypeString("intsize", false) });
1552          globalContext.types.Add((BTNode)Symbol { string = CopyString("size_t"), type = ProcessTypeString("uintsize", false) });
1553
1554          {
1555             const char * outputFilePath = GetOutputFile();
1556             if(FileExists(outputFilePath))
1557                DeleteFile(outputFilePath);
1558          }
1559
1560          snprintf(command, sizeof(command), "%s%s -x c -E \"%s\"", cppCommand, cppOptions ? cppOptions : "", GetSourceFile());
1561          command[sizeof(command)-1] = 0;
1562 #if 0 //def _DEBUG
1563          PrintLn("ECP Executing:");
1564          PrintLn(command);
1565 #endif
1566          if((cppOutput = DualPipeOpen({ output = true }, command)))
1567          {
1568             int exitCode;
1569             OldList * ast;
1570             TempFile fileInput { };
1571             ModuleImport mainModule { };
1572             //fileInput = TempFile { };
1573             SetFileInput(fileInput);
1574
1575             SetMainModule(mainModule);
1576             imports.Add(/*(*/mainModule/* = ModuleImport { })*/);
1577
1578             resetScanner();
1579
1580             for(;!cppOutput.Eof();)
1581             {
1582                char junk[4096];
1583                int count = cppOutput.Read(junk, 1, 4096);
1584                fileInput.Write(junk, 1, count);
1585             }
1586             exitCode = cppOutput.GetExitCode();
1587             delete cppOutput;
1588
1589             fileInput.Seek(0, start);
1590
1591    #ifdef _DEBUG
1592             // SetYydebug(true);
1593    #endif
1594             ParseEc();
1595             SetCurrentNameSpace(null);
1596             SetYydebug(false);
1597             delete fileInput;
1598             SetFileInput(null);
1599
1600             ast = GetAST();
1601             if(!exitCode)
1602             {
1603                if(ast)
1604                {
1605                   ProcessDBTableDefinitions();
1606                   PreCompPreProcessClassDefinitions();
1607                }
1608                if(!this.exitCode)
1609                   OutputSymbols(GetOutputFile());
1610             }
1611             else
1612                this.exitCode = exitCode;
1613
1614             if(ast)
1615             {
1616                FreeASTTree(ast);
1617             }
1618          }
1619
1620          FreeContext(globalContext);
1621          FreeExcludedSymbols(_excludedSymbols);
1622
1623          ::defines.Free(FreeModuleDefine);
1624          imports.Free(FreeModuleImport);
1625
1626          precompDefines.Free(FreeDefinition);
1627
1628          FreeTypeData(privateModule);
1629          FreeIncludeFiles();
1630          FreeGlobalData(globalData);
1631
1632          delete privateModule;
1633       }
1634
1635       delete cppCommand;
1636       delete cppOptions;
1637
1638       /*
1639       for(c = 0; c<argc; c++)
1640          delete argv[c];
1641       delete argv;
1642       */
1643       SetSymbolsDir(null); // Free symbols dir
1644
1645 #if 0 //defined(_DEBUG) && defined(__WIN32__)
1646       // CheckMemory();
1647       PrintLn("Done.");
1648       getch();
1649 #endif
1650    }
1651 }