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