5bf2bbce5d7c0c36dba55fd6c67a09a5bdb0a743
[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.type;
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)&((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             Method method;
435             if((prop = eClass_FindProperty(regClass, def.id.string, privateModule)))
436             {
437                PropertyDefine propDefine;
438
439                prop = eClass_AddProperty(regClass, def.id.string, null, null, null, def.memberAccess);
440                if(prop)
441                {
442                   propDefine = PropertyDefine
443                   {
444                      isProperty = propertyMember;
445                      name = CopyString(prop.name);
446                      memberAccess = def.memberAccess;
447                   };
448                   classDefine.propertiesAndMembers.Add(propDefine);
449                }
450             }
451             else if((member = eClass_FindDataMember(regClass, def.id.string, privateModule, null, null)))
452             {
453                DataMemberDefine dataMemberDefine;
454
455                member = eClass_AddDataMember(regClass, def.id.string, null, 0, 0, def.memberAccess);
456
457                dataMemberDefine = DataMemberDefine
458                {
459                   isProperty = dataMember;
460                   memberType = normalMember;
461                   name = CopyString(def.id.string);
462                   memberAccess = def.memberAccess;
463                };
464                parentMemberDefine.dataMembers.Add(dataMemberDefine);
465             }
466          }
467       }
468    }
469 }
470
471 static void ProcessClass(ClassType classType, OldList definitions, Symbol symbol, OldList baseSpecs, OldList enumValues, bool isWatchable, AccessMode declMode)
472 {
473    Class regClass;
474    ClassDef def;
475    ClassDefine classDefine;
476    char baseName[1024];
477    bool unitType = false;
478    bool wouldBeEnum = false;
479    AccessMode inheritanceAccess = publicAccess;
480    baseName[0] = '\0';
481
482    if(baseSpecs != null)
483    {
484       Type baseType = ProcessType(baseSpecs, null);
485       PrintType(baseType, baseName, false, true);
486       if(baseType.kind == TypeKind::classType)
487       {
488          if(baseType._class.registered && classType == normalClass)
489          {
490             if(baseType._class.registered.type == unitClass)
491                classType = unitClass;
492             else if(baseType._class.registered.type == bitClass)
493                classType = bitClass;
494             else if(baseType._class.registered.type == noHeadClass)
495                classType = noHeadClass;
496             else if(baseType._class.registered.type == enumClass)
497             {
498                wouldBeEnum = true;
499                // classType = enumClass;
500             }
501          }
502       }
503       else if(baseType.kind == structType || baseType.kind == unionType)
504       {
505          classType = noHeadClass;
506          baseName[0] = '\0';
507       }
508       else
509          unitType = true;
510       FreeType(baseType);
511
512       if(((Specifier)baseSpecs.first).type == baseSpecifier && ((Specifier)baseSpecs.first).specifier == PRIVATE)
513          inheritanceAccess = privateAccess;
514    }
515
516    // Eventually compute size with declarations for optional constant size offset...
517
518    // If there's any struct declaration in a unit data type, it means this is a bit class
519    if(classType == normalClass)
520    {
521       if(unitType) classType = unitClass;
522       if(definitions != null)
523       {
524          for(def = definitions.first; def; def = def.next)
525          {
526             if(def.type == declarationClassDef)
527             {
528                Declaration decl = def.decl;
529                if(decl.type == structDeclaration)
530                {
531                   if(unitType)
532                   {
533                      classType = bitClass;
534                      break;
535                   }
536                   if(decl.declarators)
537                   {
538                      Declarator d;
539
540                      for(d = decl.declarators->first; d; d = d.next)
541                      {
542                         if(d.structDecl.exp)
543                         {
544                            classType = bitClass;
545                            break;
546                         }
547                      }
548                      if(d) break;
549                   }
550                }
551             }
552          }
553       }
554    }
555    if(classType == normalClass && wouldBeEnum) classType = enumClass;
556
557    regClass = symbol.registered = eSystem_RegisterClass((classType == unionClass) ? structClass : classType, symbol.string, baseName[0] ? baseName : null, 0, 0, null, null, privateModule, publicAccess, inheritanceAccess);
558    if(regClass)
559       regClass.symbol = symbol;
560
561    classDefine = ClassDefine
562    {
563       type = classDefinition;
564       name = CopyString(symbol.string);
565       base = baseName[0] ? CopyString(baseName) : null;
566       isStatic = declMode == staticAccess;
567       isRemote = symbol.isRemote;
568       isWatchable = isWatchable;
569    };
570    precompDefines.Add(classDefine);
571
572    if(classType == unionClass)
573    {
574       DataMember unionMember = eMember_New(DataMemberType::unionMember, publicAccess);
575       DataMemberDefine unionDefine;
576
577       unionDefine = DataMemberDefine
578       {
579          isProperty = dataMember;
580          memberType = DataMemberType::unionMember;
581       };
582       classDefine.propertiesAndMembers.Add(unionDefine);
583
584       AddDefinitions(classDefine, unionDefine, regClass, unionMember, definitions);
585       eClass_AddMember(regClass, unionMember);
586    }
587    else if(regClass)
588       AddDefinitions(classDefine, (DataMemberDefine)classDefine, regClass, null, definitions);
589
590    // Do the functions
591    if(definitions != null)
592    {
593       for(def = definitions.first; def; def = def.next)
594       {
595          if(def.type == functionClassDef)
596          {
597             ClassFunction func = def.function;
598             // Add ecereMethod_[class]_ to the declarator
599             if(!func.dontMangle && func.declarator)
600             {
601                Identifier id = GetDeclId(func.declarator);
602                Method method;
603                MethodDefine methodDefine;
604
605                {
606                   char * dataTypeString  = StringFromSpecDecl(func.specifiers, func.declarator);
607                   if(func.isVirtual)
608                      method = eClass_AddVirtualMethod(regClass, id.string, dataTypeString, func.declarator.symbol, def.memberAccess);
609                   else
610                      method = eClass_AddMethod(regClass, id.string, dataTypeString, func.declarator.symbol, def.memberAccess);
611                   delete dataTypeString;
612                }
613
614                // Should we make a copy here? We make a copy in pass0.c ...
615                //method.symbol = func.declarator.symbol;
616
617                if(method)
618                {
619                   method.symbol = Symbol
620                   {
621                      string = CopyString(func.declarator.symbol.string);
622                      id = func.declarator.symbol.id;
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 *)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 = intType;
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                   NamedLink 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 = PrintUInt((uint)l.data);
788                            FreeType(e.exp.expType);
789                            e.exp.expType = ProcessTypeString("uint", 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                int value;
802                //value = strtol(e.exp.string, null, 0);
803                switch(op.kind)
804                {
805                   case charType:
806                      value = op.type.isSigned ? (int)op.c : (int)op.uc;
807                      break;
808                   case shortType:
809                      value = op.type.isSigned ? (int)op.s : (int) op.us;
810                      break;
811                   default:
812                      value = op.i;
813                }
814                eEnum_AddFixedValue(regClass, e.id.string, value);
815             }
816             else
817             {
818                char expString[8192];
819                expString[0] = 0;
820                PrintExpression(e.exp, expString);
821                printf($"error: could not resolve value %s for enum %s in precompiler\n", expString, regClass.name);
822                ((PrecompApp)__thisModule).exitCode = 1;
823                eEnum_AddValue(regClass, e.id.string);
824             }
825          }
826          else
827             eEnum_AddValue(regClass, e.id.string);
828       }
829    }
830 }
831
832 void PreCompPreProcessClassDefinitions()
833 {
834    OldList * ast = GetAST();
835    External external, next;
836    for(external = ast->first; external; external = next)
837    {
838       next = external.next;
839       if(external.type == classExternal)
840       {
841          ClassDefinition _class = external._class;
842          if(_class.declMode == publicAccess || _class.declMode == privateAccess || _class.declMode == staticAccess)
843          {
844             if(_class.definitions)
845             {
846                ProcessClass(normalClass, _class.definitions, _class.symbol, _class.baseSpecs, null, _class.deleteWatchable, _class.declMode);
847             }
848          }
849       }
850       else if(external.type == declarationExternal)
851       {
852          Declaration declaration = external.declaration;
853
854          if(declaration.type == initDeclaration)
855          {
856             if(external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess || external.declaration.declMode == staticAccess)
857             {
858                if(declaration.specifiers)
859                {
860                   Specifier specifier;
861                   for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
862                   {
863                      if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string &&
864                         (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
865                      {
866                         Symbol symbol = FindClass(specifier.id.string);
867                         if(symbol)
868                         {
869                            ClassType classType;
870
871                            if(specifier.type == enumSpecifier)
872                               classType = enumClass;
873                            else if(specifier.type == unionSpecifier)
874                               classType = unionClass;
875                            else
876                               classType = structClass;
877                            ProcessClass(classType, specifier.definitions, symbol, specifier.baseSpecs, specifier.list, false, external.declaration.declMode);
878                         }
879                      }
880                   }
881                }
882                if(external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess)
883                {
884                   if(declaration.declarators)
885                   {
886                      InitDeclarator d;
887                      for(d = declaration.declarators->first; d; d = d.next)
888                      {
889                         if(d.declarator)
890                         {
891                            Symbol symbol = d.declarator.symbol;
892                            if(symbol)
893                            {
894                               DataDefine dataDefine;
895                               char typeString[1024];
896                               typeString[0] = '\0';
897                               PrintType(symbol.type, typeString, false, true);
898                               dataDefine = DataDefine
899                               {
900                                  type = dataDefinition;
901                                  name = CopyString(symbol.string);
902                                  dataType = CopyString(typeString);
903                               };
904                               precompDefines.Add(dataDefine);
905                            }
906                         }
907                      }
908                   }
909                }
910             }
911          }
912          else if(declaration.type == instDeclaration)
913          {
914             if(external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess)
915             {
916                Symbol symbol = declaration.inst.symbol;
917                if(symbol)
918                {
919                   DataDefine dataDefine;
920                   char typeString[1024];
921                   typeString[0] = '\0';
922                   PrintType(symbol.type, typeString, false, true);
923                   dataDefine = DataDefine
924                   {
925                      type = dataDefinition;
926                      name = CopyString(symbol.string);
927                      dataType = CopyString(typeString);
928                   };
929                   precompDefines.Add(dataDefine);
930                }
931             }
932             globalInstance = true;
933          }
934          else if(declaration.type == defineDeclaration)
935          {
936             if(external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess)
937             {
938                Define definition
939                {
940                   type = defineDefinition;
941                   name = CopyString(declaration.id.string);
942                   exp = declaration.exp;
943                };
944                precompDefines.Add(definition);
945             }
946          }
947       }
948       else if(external.type == functionExternal && (external.function.declMode == publicAccess || external.function.declMode == privateAccess))
949       {
950          FunctionDefinition function = external.function;
951          FunctionDefine functionDefine;
952          char typeString[1024];
953          typeString[0] = '\0';
954          PrintType(function.declarator.symbol.type, typeString, true, true);
955          functionDefine = FunctionDefine
956          {
957             type = functionDefinition;
958             name = CopyString(function.declarator.symbol.string);
959             dataType = CopyString(typeString);
960          };
961          precompDefines.Add(functionDefine);
962       }
963       else if(external.type == nameSpaceExternal)
964       {
965          SetCurrentNameSpace(external.id.string); //currentNameSpace = external.id.string;
966          //currentNameSpaceLen = currentNameSpace ? strlen(currentNameSpace) : 0;
967       }
968    }
969
970    ComputeModuleClasses(privateModule);
971
972    // Second pass for enumeration values
973    for(external = ast->first; external; external = next)
974    {
975       next = external.next;
976       if(external.type == declarationExternal && (external.declaration.declMode == publicAccess || external.declaration.declMode == privateAccess))
977       {
978          Declaration declaration = external.declaration;
979
980          if(declaration.type == initDeclaration)
981          {
982             if(declaration.specifiers)
983             {
984                Specifier specifier;
985                for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
986                {
987                   if((specifier.type == enumSpecifier) && specifier.id && specifier.id.string &&
988                      (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
989                   {
990                      Symbol symbol = FindClass(specifier.id.string);
991                      if(symbol)
992                      {
993                         ProcessClassEnumValues(enumClass, specifier.definitions, symbol, specifier.baseSpecs, specifier.list);
994                      }
995                   }
996                }
997             }
998          }
999       }
1000    }
1001 }
1002
1003 static void OutputDataMembers(ClassDefine classDefine, Class _class, File f)
1004 {
1005    if(classDefine.propertiesAndMembers.first)
1006    {
1007       DataMemberDefine member = classDefine.propertiesAndMembers.first;
1008       MemberType last = unresolvedMember;
1009
1010       for(member = classDefine.propertiesAndMembers.first; member; member = member.next)
1011       {
1012          if(member.isProperty == propertyMember)
1013          {
1014             PropertyDefine prop = (PropertyDefine)member;
1015             if(last != propertyMember)
1016             {
1017                if(last)
1018                   f.Printf("         .\n");
1019                f.Printf("      [Defined Properties]\n");
1020             }
1021
1022             if(prop.name)
1023                f.Printf("         %s\n", prop.name);
1024             else
1025                f.Printf("         [Conversion]\n");
1026             if(prop.memberAccess == publicAccess)
1027                f.Printf("            [Public]\n");
1028             else
1029                f.Printf("            [Private]\n");
1030             if(prop.isVirtual)
1031                f.Printf("            [Virtual]\n");
1032             if(prop.hasSet)
1033                f.Printf("            [Set]\n");
1034             if(prop.hasGet)
1035                f.Printf("            [Get]\n");
1036             if(prop.isWatchable)
1037                f.Printf("            [Watchable]\n");
1038             f.Printf("            [Type]\n");
1039             f.Printf("               %s\n", prop.type ? prop.type : "");
1040          }
1041          else
1042          {
1043             if(last != dataMember)
1044             {
1045                if(last)
1046                   f.Printf("         .\n");
1047                f.Printf("      [Defined Data Members]\n");
1048             }
1049             if(member.memberType == normalMember)
1050             {
1051                f.Printf("         %s\n", member.name);
1052                if(member.memberAccess == publicAccess)
1053                   f.Printf("            [Public]\n");
1054                else
1055                   f.Printf("            [Private]\n");
1056                if(_class && _class.type == bitClass)
1057                {
1058                   if(member.size)
1059                   {
1060                      f.Printf("            [Size]\n");
1061                      f.Printf("               %d\n", member.size);
1062                   }
1063                   if(member.bitPos != -1)
1064                   {
1065                      f.Printf("            [Pos]\n");
1066                      f.Printf("               %d\n", member.bitPos);
1067                   }
1068                }
1069                f.Printf("            [Type]\n");
1070                f.Printf("               %s\n", member.type ? member.type : "");
1071             }
1072             else
1073             {
1074                if(member.memberAccess == publicAccess)
1075                   f.Printf("            [Public]\n");
1076                else
1077                   f.Printf("            [Private]\n");
1078                f.Printf((member.memberType == unionMember) ? "      [Union]\n" : "      [Struct]\n");
1079                OutputDataMembers((ClassDefine)member, null, f);
1080             }
1081          }
1082          last = member.isProperty;
1083       }
1084       f.Printf("         .\n");
1085    }
1086
1087    if(classDefine.classProperties.first)
1088    {
1089       PropertyDefine prop = classDefine.propertiesAndMembers.first;
1090       f.Printf("      [Defined Class Properties]\n");
1091       for(prop = classDefine.classProperties.first; prop; prop = prop.next)
1092       {
1093          if(prop.name)
1094             f.Printf("         %s\n", prop.name);
1095          if(prop.hasSet)
1096             f.Printf("            [Set]\n");
1097          if(prop.hasGet)
1098             f.Printf("            [Get]\n");
1099          f.Printf("            [Type]\n");
1100          f.Printf("               %s\n", prop.type ? prop.type : "");
1101       }
1102       f.Printf("         .\n");
1103    }
1104 }
1105
1106 static void OutputSymbols(const char * fileName)
1107 {
1108    File f = FileOpen(fileName, write);
1109    if(f)
1110    {
1111       DefinitionType lastType = (DefinitionType)-1;
1112       Definition definition;
1113
1114       if(globalInstance)
1115          f.Printf("[Global Instance]\n");
1116
1117       for(definition = precompDefines.first; definition; definition = definition.next)
1118       {
1119          if(definition.type != lastType)
1120          {
1121             if(lastType != (DefinitionType)-1)
1122                f.Printf("   .\n");
1123             if(definition.type == moduleDefinition)
1124                f.Printf("[Imported Modules]\n");
1125             else if(definition.type == classDefinition)
1126                f.Printf("[Defined Classes]\n");
1127             else if(definition.type == defineDefinition)
1128                f.Printf("[Defined Expressions]\n");
1129             else if(definition.type == functionDefinition)
1130                f.Printf("[Defined Functions]\n");
1131             else if(definition.type == dataDefinition)
1132                f.Printf("[Defined Data]\n");
1133             lastType = definition.type;
1134          }
1135          if(definition.type == moduleDefinition)
1136          {
1137             ImportedModule module = (ImportedModule) definition;
1138
1139             if(module.importType == staticImport)
1140                f.Printf("   [Static]\n");
1141             else if(module.importType == remoteImport)
1142                f.Printf("   [Remote]\n");
1143             if(module.importAccess == privateAccess)
1144                f.Printf("   [Private]\n");
1145             f.Printf("   %s\n", module.name);
1146          }
1147          else if(definition.type == classDefinition)
1148          {
1149             // Can we do this? Or should we fill up the definition?
1150             Class _class = eSystem_FindClass(privateModule, definition.name);
1151             ClassDefine classDefine = (ClassDefine) definition;
1152
1153             f.Printf("   %s\n", definition.name);
1154             if(classDefine.isStatic)
1155                f.Printf("      [Static]\n");
1156             if(classDefine.fixed)
1157                f.Printf("      [Fixed]\n");
1158             if(classDefine.noExpansion)
1159                f.Printf("      [No Expansion]\n");
1160             if(classDefine.isRemote)
1161                f.Printf("      [Remote]\n");
1162             if(classDefine.isWatchable)
1163                f.Printf("      [Watchable]\n");
1164             if(_class.type == enumClass)
1165                f.Printf("      [Enum]\n");
1166             else if(_class.type == bitClass)
1167                f.Printf("      [Bit]\n");
1168             else if(_class.type == structClass)
1169                f.Printf("      [Struct]\n");
1170             else if(_class.type == unitClass)
1171                f.Printf("      [Unit]\n");
1172             else if(_class.type == noHeadClass)
1173                f.Printf("      [NoHead]\n");
1174
1175             if(_class.inheritanceAccess == privateAccess)
1176                f.Printf("      [Private Base]\n");
1177             else
1178                f.Printf("      [Base]\n");
1179             if(classDefine.base)
1180                f.Printf("         %s\n", classDefine.base);
1181             else
1182                f.Printf("         [None]\n");
1183
1184             if(_class.templateParams.count)
1185             {
1186                ClassTemplateParameter param;
1187                TemplateParameter tp;
1188
1189                f.Printf("         [Template Parameters]\n");
1190
1191                for(tp = ((Symbol)_class.symbol).templateParams->first, param = _class.templateParams.first; param && tp; param = param.next, tp = tp.next)
1192                {
1193                   f.Printf("               %s\n", param.name);
1194                   switch(param.type)
1195                   {
1196                      case type:
1197                         f.Printf("               [Type]\n");
1198                         f.Printf("               %s\n", param.dataTypeString ? param.dataTypeString : "[None]");
1199                         f.Printf("               %s\n", param.defaultArg.dataTypeString ? param.defaultArg.dataTypeString : "[None]");
1200                         break;
1201                      case expression:
1202                         f.Printf("               [Expression]\n");
1203                         f.Printf("               %s\n", param.dataTypeString ? param.dataTypeString : "[None]");
1204                         if(tp.defaultArgument && tp.defaultArgument.expression)
1205                         {
1206                            char temp[8192];
1207                            temp[0] = 0;
1208                            PrintExpression(tp.defaultArgument.expression, temp);
1209                            ChangeCh(temp, '\n', ' ');
1210                            f.Printf("               ");
1211                            f.Puts(temp);
1212                            f.Puts("\n");
1213                         }
1214                         else
1215                            f.Printf("               [None]\n");
1216                         break;
1217                      case identifier:
1218                         f.Printf("               [Identifier]\n");
1219                         f.Printf("               %s\n", (param.memberType == dataMember) ? "[Data member]" : ((param.memberType == method) ? "[Method]" : "[Property]"));
1220                         if(tp.defaultArgument && tp.defaultArgument.identifier)
1221                         {
1222                            f.Printf("               ");
1223                            if(tp.defaultArgument.identifier._class && tp.defaultArgument.identifier._class.type == nameSpecifier &&
1224                               tp.defaultArgument.identifier._class.name)
1225                            {
1226                               f.Printf("%s::", tp.defaultArgument.identifier._class.name);
1227                            }
1228                            else if(tp.defaultArgument.identifier._class && tp.defaultArgument.identifier._class.type == templateTypeSpecifier &&
1229                               tp.defaultArgument.identifier._class.templateParameter.identifier)
1230                            {
1231                               f.Printf("%s::", tp.defaultArgument.identifier._class.templateParameter.identifier.string);
1232                            }
1233                            f.Printf("%s\n", tp.defaultArgument.identifier.string);
1234                         }
1235                         else
1236                         {
1237                            f.Printf("               [None]\n");
1238                         }
1239                         break;
1240                   }
1241                }
1242                f.Printf("         .\n");
1243             }
1244
1245             if(!classDefine.isStatic)
1246             {
1247                if(classDefine.methods.first)
1248                {
1249                   MethodDefine method;
1250
1251                   f.Printf("      [Defined Methods]\n");
1252                   for(method = classDefine.methods.first; method; method = method.next)
1253                   {
1254                      f.Printf("         %s\n", method.name);
1255                      if(method.memberAccess == publicAccess)
1256                         f.Printf("            [Public]\n");
1257                      else
1258                         f.Printf("            [Private]\n");
1259                      if(method.isVirtual)
1260                         f.Printf("            [Virtual]\n");
1261                      f.Printf("            [Type]\n");
1262                      f.Printf("               %s\n", method.type ? method.type : "");
1263                   }
1264                   f.Printf("         .\n");
1265                }
1266
1267                OutputDataMembers(classDefine, _class, f);
1268
1269                if(_class.type == enumClass)
1270                {
1271                   NamedLink value;
1272                   Class enumClass = eSystem_FindClass(privateModule, "enum");
1273                   EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
1274
1275                   f.Printf("      [Enum Values]\n");
1276                   for(value = e.values.first; value; value = value.next)
1277                   {
1278                      f.Printf("         %s = %d\n", value.name, value.data);
1279                   }
1280                   f.Printf("         .\n");
1281                }
1282             }
1283          }
1284          else if(definition.type == defineDefinition)
1285          {
1286             DefinedExpression defExp = eSystem_FindDefine(privateModule, definition.name);
1287             Define defineDefine = (Define) definition;
1288             f.Printf("   %s\n", definition.name);
1289             f.Printf("      [Value]\n");
1290             f.Printf("         ");
1291             OutputExpression(defineDefine.exp, f);
1292             f.Printf("\n");
1293          }
1294          else if(definition.type == functionDefinition)
1295          {
1296             FunctionDefine functionDefine = (FunctionDefine) definition;
1297             f.Printf("   %s\n", functionDefine.name);
1298             f.Printf("      [Type]\n");
1299             f.Printf("         %s\n", functionDefine.dataType);
1300          }
1301          else if(definition.type == dataDefinition)
1302          {
1303             DataDefine dataDefine = (DataDefine) definition;
1304             f.Printf("   %s\n", dataDefine.name);
1305             f.Printf("      [Type]\n");
1306             f.Printf("         %s\n", dataDefine.dataType);
1307          }
1308       }
1309       f.Printf("   .\n");
1310       delete f;
1311    }
1312 }
1313
1314 class PrecompApp : Application
1315 {
1316    void Main()
1317    {
1318       int c;
1319       bool valid = true;
1320       char defaultSymFile[MAX_LOCATION];
1321       char * cppCommand = null;
1322       char * cppOptions = null;
1323       int cppOptionsLen = 0;
1324       /*char ** argv = null;
1325       int argc = 0;*/
1326
1327       Platform targetPlatform = GetRuntimePlatform();
1328       int targetBits = GetHostBits();
1329       /*
1330       for(c = 0; c<this.argc; c++)
1331       {
1332          char * arg = this.argv[c];
1333          int argLen = strlen(arg);
1334
1335          argv = renew argv char *[argc + 1];
1336          argv[argc] = new char[argLen+1];
1337          strcpy(argv[argc], arg);
1338
1339          while(argv[argc][argLen-1] == '\\' && c < this.argc-1)
1340          {
1341             int len;
1342
1343             c++;
1344             arg = this.argv[c];
1345             len = strlen(arg);
1346             argv[argc] = renew argv[argc] char[argLen + len + 1];
1347
1348             argv[argc][argLen-1] = ' ';
1349             strcpy(argv[argc] + argLen, arg);
1350             argLen += len;
1351          }
1352          argc++;
1353       }*/
1354
1355 #if 0 //def _DEBUG
1356       printf("\nArguments given:\n");
1357       for(c=1; c<argc; c++)
1358          printf(" %s", argv[c]);
1359       printf("\n\n");
1360       for(c=1; c<argc; c++)
1361          PrintLn("Arg", c, ": ", argv[c]);
1362       printf("\n");
1363       //getch();
1364 #endif
1365
1366       for(c = 1; c<argc; c++)
1367       {
1368          const char * arg = argv[c];
1369          if(arg[0] == '-')
1370          {
1371             if(!strcmp(arg + 1, "m32") || !strcmp(arg + 1, "m64"))
1372             {
1373                int newLen = cppOptionsLen + 1 + strlen(arg);
1374                cppOptions = renew cppOptions char[newLen + 1];
1375                cppOptions[cppOptionsLen] = ' ';
1376                strcpy(cppOptions + cppOptionsLen + 1, arg);
1377                cppOptionsLen = newLen;
1378                targetBits = !strcmp(arg + 1, "m32") ? 32 : 64;
1379             }
1380             else if(!strcmp(arg + 1, "t32") || !strcmp(arg + 1, "t64"))
1381             {
1382                targetBits = !strcmp(arg + 1, "t32") ? 32 : 64;
1383             }
1384             else if(arg[1] == 'D' || arg[1] == 'I')
1385             {
1386                char * buf;
1387                int size = cppOptionsLen + 1 + strlen(arg) * 2 + 1;
1388                cppOptions = renew cppOptions char[size];
1389                buf = cppOptions + cppOptionsLen;
1390                *buf++ = ' ';
1391                PassArg(buf, arg);
1392                cppOptionsLen = cppOptionsLen + 1 + strlen(buf);
1393             }
1394             else if(!strcmp(arg+1, "t"))
1395             {
1396                if(++c < argc)
1397                   targetPlatform = argv[c];
1398                else
1399                   valid = false;
1400             }
1401             else if(!strcmp(arg+1, "cpp"))
1402             {
1403                if(++c < argc)
1404                   cppCommand = CopyString(argv[c]);
1405                else
1406                   valid = false;
1407             }
1408             else if(!strcmp(arg+1, "o"))
1409             {
1410                if(!GetOutputFile() && c + 1 < argc)
1411                {
1412                   SetOutputFile(argv[c+1]);
1413                   c++;
1414                }
1415                else
1416                   valid = false;
1417             }
1418             else if(!strcmp(arg+1, "c"))
1419             {
1420                if(!GetSourceFile() && c + 1 < argc)
1421                {
1422                   SetSourceFile(argv[c+1]);
1423                   c++;
1424                }
1425                else
1426                   valid = false;
1427             }
1428             else if(!strcmp(arg+1, "isystem") || !strcmp(arg+1, "isysroot"))
1429             {
1430                if(c + 1 < argc)
1431                {
1432                   char * buf;
1433                   const char * arg1 = argv[++c];
1434                   int size = cppOptionsLen + 1 + strlen(arg) * 2 + strlen(arg1) * 2 + 1;
1435                   cppOptions = renew cppOptions char[size];
1436                   buf = cppOptions + cppOptionsLen;
1437                   *buf++ = ' ';
1438                   buf = PassArg(buf, arg);
1439                   *buf++ = ' ';
1440                   buf = PassArg(buf, arg1);
1441                   cppOptionsLen = buf - cppOptions;
1442                }
1443                else
1444                   valid = false;
1445             }
1446             else if(!strcmp(arg+1, "fno-diagnostics-show-caret"))
1447             {
1448                char * buf;
1449                int size = cppOptionsLen + 1 + strlen(arg) * 2 + 1;
1450                cppOptions = renew cppOptions char[size];
1451                buf = cppOptions + cppOptionsLen;
1452                *buf++ = ' ';
1453                PassArg(buf, arg);
1454                cppOptionsLen = cppOptionsLen + 1 + strlen(buf);
1455             }
1456             else if(!strcmp(arg+1, "symbols"))
1457             {
1458                if(c + 1 < argc)
1459                {
1460                   SetSymbolsDir(argv[c+1]);
1461                   c++;
1462                }
1463                else
1464                   valid = false;
1465             }
1466             else if(!strcmp(arg+1, "defaultns"))
1467             {
1468                if(c + 1 < argc)
1469                {
1470                   SetDefaultNameSpace(argv[c+1]);
1471                   //defaultNameSpaceLen = strlen(argv[c+1]);
1472                   c++;
1473                }
1474                else
1475                   valid = false;
1476             }
1477             else if(!strcmp(arg+1, "strictns"))
1478             {
1479                SetStrictNameSpaces(true);
1480             }
1481             else if(!strcmp(arg+1, "module"))
1482             {
1483                if(c + 1 < argc)
1484                {
1485                   SetI18nModuleName(argv[c+1]);
1486                   c++;
1487                }
1488                else
1489                   valid = false;
1490             }
1491          }
1492          else
1493             valid = false;
1494       }
1495       if(valid)
1496       {
1497          if(!cppCommand)
1498             cppCommand = CopyString("gcc");
1499          if(!GetSourceFile())
1500             valid = false;
1501          else if(!GetOutputFile())
1502          {
1503             strcpy(defaultSymFile, GetSymbolsDir());
1504             PathCat(defaultSymFile, GetSourceFile());
1505             ChangeExtension(defaultSymFile, "sym", defaultSymFile);
1506             SetOutputFile(defaultSymFile);
1507          }
1508       }
1509
1510       if(!valid)
1511       {
1512          printf($"Syntax:\n   ecp [-t <target platform>] [-cpp <c preprocessor>] [-o <output>] [-symbols <outputdir>] [-I<includedir>]* [-isystem <sysincludedir>]* [-D<definition>]* -c <input>\n");
1513       }
1514       else
1515       {
1516          DualPipe cppOutput;
1517          // TODO: Improve this
1518          char command[MAX_F_STRING*3];
1519          SetGlobalData(&globalData);
1520          SetExcludedSymbols(&_excludedSymbols);
1521          SetGlobalContext(globalContext);
1522          SetCurrentContext(globalContext);
1523          SetTopContext(globalContext);
1524          SetDefines(&::defines);
1525          SetImports(&imports);
1526          SetInPreCompiler(true);
1527          SetPrecompDefines(&precompDefines);
1528          SetTargetPlatform(targetPlatform);
1529          SetTargetBits(targetBits);
1530          SetEchoOn(false);
1531
1532          privateModule = (Module)__ecere_COM_Initialize((bool)(true | (targetBits == sizeof(uintptr)*8 ? 0 : targetBits == 64 ? 2 : targetBits==32 ? 4 : 0) | 8), 1, null);
1533          SetPrivateModule(privateModule);
1534
1535          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint"), type = ProcessTypeString("unsigned int", false) });
1536          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint64"), type = ProcessTypeString("unsigned int64", false) });
1537          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint32"), type = ProcessTypeString("unsigned int", false) });
1538          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint16"), type = ProcessTypeString("unsigned short", false) });
1539          globalContext.types.Add((BTNode)Symbol { string = CopyString("byte"), type = ProcessTypeString("unsigned char", false) });
1540          globalContext.types.Add((BTNode)Symbol { string = CopyString("intptr_t"), type = ProcessTypeString("intptr", false) });
1541          globalContext.types.Add((BTNode)Symbol { string = CopyString("uintptr_t"), type = ProcessTypeString("uintptr", false) });
1542          globalContext.types.Add((BTNode)Symbol { string = CopyString("ssize_t"), type = ProcessTypeString("intsize", false) });
1543          globalContext.types.Add((BTNode)Symbol { string = CopyString("size_t"), type = ProcessTypeString("uintsize", false) });
1544
1545          {
1546             const char * outputFilePath = GetOutputFile();
1547             if(FileExists(outputFilePath))
1548                DeleteFile(outputFilePath);
1549          }
1550
1551          snprintf(command, sizeof(command), "%s%s -x c -E \"%s\"", cppCommand, cppOptions ? cppOptions : "", GetSourceFile());
1552          command[sizeof(command)-1] = 0;
1553 #if 0 //def _DEBUG
1554          PrintLn("ECP Executing:");
1555          PrintLn(command);
1556 #endif
1557          if((cppOutput = DualPipeOpen({ output = true }, command)))
1558          {
1559             int exitCode;
1560             OldList * ast;
1561             TempFile fileInput { };
1562             ModuleImport mainModule { };
1563             //fileInput = TempFile { };
1564             SetFileInput(fileInput);
1565
1566             SetMainModule(mainModule);
1567             imports.Add(/*(*/mainModule/* = ModuleImport { })*/);
1568
1569             resetScanner();
1570
1571             for(;!cppOutput.Eof();)
1572             {
1573                char junk[4096];
1574                int count = cppOutput.Read(junk, 1, 4096);
1575                fileInput.Write(junk, 1, count);
1576             }
1577             exitCode = cppOutput.GetExitCode();
1578             delete cppOutput;
1579
1580             fileInput.Seek(0, start);
1581
1582    #ifdef _DEBUG
1583             // SetYydebug(true);
1584    #endif
1585             ParseEc();
1586             SetCurrentNameSpace(null);
1587             SetYydebug(false);
1588             delete fileInput;
1589             SetFileInput(null);
1590
1591             ast = GetAST();
1592             if(!exitCode)
1593             {
1594                if(ast)
1595                {
1596                   ProcessDBTableDefinitions();
1597                   PreCompPreProcessClassDefinitions();
1598                }
1599                if(!this.exitCode)
1600                   OutputSymbols(GetOutputFile());
1601             }
1602             else
1603                this.exitCode = exitCode;
1604
1605             if(ast)
1606             {
1607                FreeASTTree(ast);
1608             }
1609          }
1610
1611          FreeContext(globalContext);
1612          FreeExcludedSymbols(_excludedSymbols);
1613
1614          ::defines.Free(FreeModuleDefine);
1615          imports.Free(FreeModuleImport);
1616
1617          precompDefines.Free(FreeDefinition);
1618
1619          FreeTypeData(privateModule);
1620          FreeIncludeFiles();
1621          FreeGlobalData(globalData);
1622
1623          delete privateModule;
1624       }
1625
1626       delete cppCommand;
1627       delete cppOptions;
1628
1629       /*
1630       for(c = 0; c<argc; c++)
1631          delete argv[c];
1632       delete argv;
1633       */
1634       SetSymbolsDir(null); // Free symbols dir
1635
1636 #if 0 //defined(_DEBUG) && defined(__WIN32__)
1637       // CheckMemory();
1638       PrintLn("Done.");
1639       getch();
1640 #endif
1641    }
1642 }