compiler/libec: Fixed parsing crash originating in grammar rules
[sdk] / compiler / libec / src / pass1.ec
1 import "ecdefs"
2
3 // UNTIL IMPLEMENTED IN GRAMMAR
4 #define ACCESS_CLASSDATA(_class, baseClass) \
5    (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
6
7 #define YYLTYPE Location
8 #include "grammar.h"
9
10 static Statement registerModuleBody;
11 static External registerModuleExternal;
12 static Statement unregisterModuleBody;
13 static External unregisterModuleExternal;
14
15 extern int propWatcherID;
16
17 bool buildingECERECOM = false;
18 public void SetBuildingEcereCom(bool b) { buildingECERECOM = b; } public bool GetBuildingEcereCom() { return buildingECERECOM; }
19 bool buildingECERECOMModule = false;
20 public void SetBuildingEcereComModule(bool b) { buildingECERECOMModule = b; } public bool GetBuildingEcereComModule() { return buildingECERECOMModule; }
21
22 // This will also be called by the instance processer to make the instance methods... (pass 1.5)
23 External ProcessClassFunction(Class owningClass, ClassFunction func, OldList defs, External after, bool makeStatic)
24 {
25    Identifier id = GetDeclId(func.declarator);
26    Type type = null;
27    Symbol symbol;
28    External external = null;
29
30    if(defs && func.declarator)
31    {
32       FunctionDefinition function = null;
33       Symbol propSymbol;
34       int symid = func.declarator.symbol.id;
35       int symidCode = func.declarator.symbol.idCode;
36
37       if(inCompiler)
38       {
39          if(!func.specifiers)
40             func.specifiers = MkList();
41          // Add static to the specifiers
42          if(makeStatic)
43             func.specifiers->Insert(null, MkSpecifier(STATIC));
44       }
45
46       propSymbol = func.declarator.symbol;
47
48       ReplaceThisClassSpecifiers(func.specifiers, owningClass);
49
50       if(propSymbol.externalGet == (External)func)
51          func.declarator.symbol = null;
52       else if(propSymbol.externalSet == (External)func)
53       {
54          func.declarator.symbol = null;
55          symid++;
56       }
57       else if(propSymbol.externalIsSet == (External)func)
58       {
59          func.declarator.symbol = null;
60          symid += 2; // TOFIX: What should we do with this? Where are 2 IDs allocated for properties? In MkProperty...
61       }
62
63       //if(inCompiler)
64       {
65          /*FunctionDefinition*/ function = _MkFunction(func.specifiers, func.declarator, null, false);
66          function.propSet = func.propSet;
67          function.type = func.type;
68          if(func.type) func.type.refCount++;
69          ProcessFunctionBody(function, func.body);
70          external = MkExternalFunction(function);
71          
72          external.symbol = func.declarator.symbol;
73          external.function._class = func._class;
74       }
75
76       symbol = func.declarator.symbol;
77       //symbol.id = func.id; //symid;
78       symbol.id = symid;
79       symbol.idCode = symidCode;
80       
81       if(!func.dontMangle)
82       {
83          // Normal method
84          Method method = func.declarator.symbol.method;
85          func.declarator.symbol.methodExternal = external;
86
87          // DANGER: Added this one... 
88
89          if(method && method.symbol)
90             //((Symbol)method.symbol).methodExternal = external;
91             ((Symbol)method.symbol).methodCodeExternal = external;
92
93          if(method && method.type == virtualMethod)
94          {
95             Type methodDataType;
96             ProcessMethodType(method);
97             
98             methodDataType = method.dataType;
99
100             // Do type checking here of type against method.dataType
101             // ThisClass must be the owning class for types not specified, static for static, or inherit from method's ThisClass is specified
102             // If not specified, defaults to ThisClass if ThisClass specified in method, otherwise overiding class or static
103
104             type = symbol.type;
105
106             if(!type.staticMethod && !type.thisClass && !type.thisClassTemplate)
107             {
108                if(method.dataType.thisClassTemplate)
109                {
110                   if(owningClass.templateArgs)
111                   {
112                      ClassTemplateArgument * arg = FindTemplateArg(owningClass, method.dataType.thisClassTemplate);
113                      type.byReference = method.dataType.byReference;
114
115                      methodDataType = ProcessTypeString(method.dataTypeString, false);
116                      type.thisClass = methodDataType.thisClass = arg ? FindClass(arg->dataTypeString) : null;
117                   }
118                }
119                else if(method.dataType.staticMethod)
120                   type.staticMethod = true;
121                else if(method.dataType.thisClass)
122                {
123                   type.thisClass = method.dataType.thisClass;
124                   type.byReference = method.dataType.byReference;
125                }
126                else
127                {
128                   if(!owningClass.symbol)
129                      owningClass.symbol = FindClass(owningClass.fullName);
130
131                   type.thisClass = owningClass.symbol;
132                   // WORKING ON THIS TO SUPPORT : pass.NotifyClicked(this, pass, 0, 0, key.modifiers);
133                   type.extraParam = true;
134                }
135             }
136
137             yylloc = func.loc;
138             if(!MatchTypes(type, methodDataType, null, owningClass, method._class /*owningClass*/, true, true, true, false))
139             {
140 #ifdef _DEBUG
141                // MatchTypes(type, methodDataType, null, owningClass, owningClass, true, true, true, false);
142 #endif
143                Compiler_Error($"Incompatible virtual function %s\n", method.name);
144             }
145             else
146             {
147                // Mark typed_object/any_object parameters as such according to method type
148                Type typeParam;
149                Declarator funcDecl = GetFuncDecl(func.declarator);
150                if(funcDecl.function.parameters)
151                {
152                   TypeName param = funcDecl.function.parameters->first;
153
154                   for(typeParam = methodDataType.params.first; typeParam; typeParam = typeParam.next)
155                   {
156                      if(typeParam.classObjectType)
157                      {
158                         param.classObjectType = typeParam.classObjectType;
159                         if(param.declarator && param.declarator.symbol)
160                            param.declarator.symbol.type.classObjectType = typeParam.classObjectType;
161                      }
162                      param = param.next;
163                   }
164                }
165             }
166             if(methodDataType != method.dataType)
167                FreeType(methodDataType);
168          }
169          else
170          {
171             type = symbol.type;
172             if(!type.staticMethod && !type.thisClass)
173             {
174                if(owningClass && !owningClass.symbol)
175                   owningClass.symbol = FindClass(owningClass.fullName);
176
177                type.thisClass = owningClass ? FindClass(owningClass.fullName) : null;
178             }
179          }
180       }
181       else
182       {
183          // TESTING THIS HERE: (Implementing Class Properties)
184          if(symbol.type && !symbol.type.staticMethod && !symbol.type.thisClass)
185          {
186             if(!owningClass.symbol)
187                owningClass.symbol = FindClass(owningClass.fullName);
188             symbol.type.thisClass = owningClass.symbol;
189          }
190
191          // Those type of classes don't need a this parameter for Set methods, null thisClass before changing the externals
192          if(propSymbol.externalSet == (External)func && propSymbol._property && propSymbol._property.conversion)
193          {
194             if(symbol.type.thisClass && symbol.type.classObjectType != classPointer)
195             {
196                // TODO: Perhaps improve this so as to support both "this =" and "return " syntax for all types of classes
197                if(owningClass.type != structClass)
198                   //function.propertyNoThis = true;
199                   symbol.type.thisClass = null;
200             }
201          }
202
203          // Property
204          if(propSymbol.externalGet == (External)func)
205          {
206             propSymbol.externalGet = external;
207          }
208          else if(propSymbol.externalSet == (External)func)
209          {
210             propSymbol.externalSet = external;
211          }
212          else if(propSymbol.externalIsSet == (External)func)
213          {
214             propSymbol.externalIsSet = external;
215          }
216          else 
217          {
218             // Constructor destructor
219             //symbol.type = Type { };
220          }
221       }
222       if(inCompiler)
223       {
224          if(func.body)
225          {
226             func.declarator = null;
227             func.specifiers = null;
228             func.body = null;
229
230             defs.Insert(after, external);
231          }
232          else
233          {
234             Method method = func.declarator.symbol.method;
235             if(method && method.symbol)
236                ((Symbol)method.symbol).methodCodeExternal = null;
237
238             //external.function = null;
239             func.declarator = null;
240             func.specifiers = null;
241
242             FreeExternal(external); // Free external here?
243          }
244       }
245       else
246       {
247          globalContext /*curContext*/.symbols.Remove((BTNode)symbol);
248          excludedSymbols->Add(symbol);
249          
250          // Testing this...
251          defs.Insert(after, external);
252
253          external.function.declarator = CopyDeclarator(external.function.declarator);
254          external.function.specifiers = CopyList(external.function.specifiers, CopySpecifier);
255          external.function.body = null;
256       }
257    }
258    return external;
259 }
260
261 void CreateRegisterModuleBody()
262 {
263    if(!registerModuleBody && inCompiler)
264    {
265       char registerName[1024], moduleName[MAX_FILENAME];
266       OldList * specifiers;
267       Declarator declarator;
268       TypeName moduleParam;
269
270       registerModuleBody = MkCompoundStmt(MkList(), MkList());
271       registerModuleBody.compound.context = Context { parent = globalContext };
272
273       #if 0
274       ListAdd(registerModuleBody.compound.declarations, 
275          MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null) /*MkSpecifierName("ecere::com::Class")*/ /*MkStructOrUnion(SpecifierStruct, MkIdentifier("Class"), null)*/),
276                        MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class"))), null))));
277       #endif
278       ListAdd(registerModuleBody.compound.declarations, 
279          MkDeclaration(MkListOne(MkSpecifierName("ecere::com::Class")),
280                        MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("class")), null))));
281
282       specifiers = MkList();
283       ListAdd(specifiers, MkSpecifier(VOID));
284
285       moduleParam = MkTypeName(MkListOne(/*MkSpecifier(VOID)*/MkSpecifierName("Module")), 
286          //MkDeclaratorPointer(MkPointer(null, null), 
287          MkDeclaratorIdentifier(MkIdentifier("module")));
288
289       GetLastDirectory(outputFile, moduleName);
290       //strcpy(moduleName, argv[2]);
291       StripExtension(moduleName);
292       ChangeCh(moduleName, '.', '_');
293       ChangeCh(moduleName, ' ', '_');
294       ChangeCh(moduleName, '-', '_');
295       sprintf(registerName, "__ecereRegisterModule_%s", moduleName);
296
297       declarator = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(registerName)),
298          MkListOne(moduleParam));
299
300       {
301          FunctionDefinition function = _MkFunction(specifiers, declarator, null, false);
302          ProcessFunctionBody(function, registerModuleBody);
303          function.declMode = defaultAccess;
304          if(!ast) ast = MkList();
305          ListAdd(ast, (registerModuleExternal = MkExternalFunction(function)));
306       }
307    }
308
309    // Unregister Module
310    if(!unregisterModuleBody && inCompiler)
311    {      
312       char registerName[1024], moduleName[MAX_FILENAME];
313       OldList * specifiers;
314       Declarator declarator;
315       TypeName moduleParam;
316
317       unregisterModuleBody = MkCompoundStmt(MkList(), MkList());
318       unregisterModuleBody.compound.context = Context { parent = globalContext };
319
320       specifiers = MkList();
321       ListAdd(specifiers, MkSpecifier(VOID));
322
323       moduleParam = MkTypeName(MkListOne(/*MkSpecifier(VOID)*/ MkSpecifierName("Module")), 
324          //MkDeclaratorPointer(MkPointer(null, null), 
325          MkDeclaratorIdentifier(MkIdentifier("module")));
326
327       GetLastDirectory(outputFile, moduleName);
328       StripExtension(moduleName);
329       ChangeCh(moduleName, '.', '_');
330       ChangeCh(moduleName, ' ', '_');
331       ChangeCh(moduleName, '-', '_');
332       //strcpy(moduleName, argv[2]);
333       sprintf(registerName, "__ecereUnregisterModule_%s", moduleName);
334
335       declarator = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(registerName)),
336          MkListOne(moduleParam));
337
338       {
339          FunctionDefinition function = _MkFunction(specifiers, declarator, null, false);
340          ProcessFunctionBody(function, unregisterModuleBody);
341          function.declMode = defaultAccess;
342          if(!ast) ast = MkList();
343          ListAdd(ast, (unregisterModuleExternal = MkExternalFunction(function)));
344       }
345    }
346 }
347
348 void RegisterMembersAndProperties(Class regClass, bool isMember, char * className, Statement statement)
349 {
350    DataMember dataMember = isMember ? (DataMember)regClass : null;
351    DataMember member;
352    Property prop;
353    Expression exp;
354    Statement stmt;
355    char dataMemberSize[16];
356
357    uint lastOffset = 0;
358    int privateID = 0;
359    bool privateMembers = false;
360
361    sprintf(dataMemberSize, "%d", (int)sizeof(DataMember));
362    if(!isMember)
363    {
364       for(prop = regClass.conversions.first; prop; prop = prop.next)
365       {
366          OldList * args = MkList();
367          char name[1024];
368
369          // Class class
370          ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
371          // char * name
372          ListAdd(args, MkExpConstant("0"));
373
374          // char * type
375          {
376             char * string = QMkString(prop.dataTypeString);
377             ListAdd(args, MkExpString(string));
378             delete string;
379          }
380          // void * Set
381          if(prop.Set)
382          {
383             strcpy(name, "__ecereProp_");
384             FullClassNameCat(name, regClass.fullName, false);
385             strcat(name, "_Set_");
386             // strcat(name, prop.name);
387             FullClassNameCat(name, prop.name, true);
388             MangleClassName(name);
389             ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
390          }
391          else
392             ListAdd(args, MkExpConstant("0"));
393          // void * Get
394          if(prop.Get)
395          {
396             strcpy(name, "__ecereProp_");
397             FullClassNameCat(name, regClass.fullName, false);
398             strcat(name, "_Get_");
399             // strcat(name, prop.name);
400             FullClassNameCat(name, prop.name, true);
401             MangleClassName(name);
402
403             ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
404          }
405          else
406             ListAdd(args, MkExpConstant("0"));
407
408
409          // Declaration Mode
410          switch(prop.memberAccess)
411          {
412             case staticAccess:
413                ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
414                break;
415             case privateAccess:
416                ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
417                break;
418             case publicAccess:
419             default:
420                ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
421                break;
422          }
423
424          strcpy(name, "__ecereProp_");
425          FullClassNameCat(name, regClass.fullName, false);
426          strcat(name, "_");
427          FullClassNameCat(name, prop.name, true);
428          // strcat(name, prop.name);
429          MangleClassName(name);
430
431          stmt = MkExpressionStmt(MkListOne(
432             MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=',
433             MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddProperty")), args))));
434          ListAdd(registerModuleBody.compound.statements, stmt);
435       }
436    }
437
438    for(member = isMember ? dataMember.members.first : regClass.membersAndProperties.first; member; member = member.next)
439    {
440       if(member.isProperty)
441       {
442          prop = (Property) member;
443          {
444             OldList * args = MkList();
445             char name[1024], nameM[1024];
446             char * string = QMkString(prop.name);
447
448             // Class class
449             ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
450
451             // char * name
452             ListAdd(args, MkExpString(string));
453             delete string;
454
455             // char * type
456             {
457                char * string = QMkString(prop.dataTypeString);
458                ListAdd(args, MkExpString(string));
459                delete string;
460             }
461             // void * Set
462             if(prop.Set)
463             {
464                strcpy(name, "__ecereProp_");
465                FullClassNameCat(name, regClass.fullName, false);
466                strcat(name, "_Set_");
467                FullClassNameCat(name, prop.name, true);
468                // strcat(name, prop.name);
469                MangleClassName(name);
470                ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
471             }
472             else
473                ListAdd(args, MkExpConstant("0"));
474             // void * Get
475             if(prop.Get)
476             {
477                strcpy(name, "__ecereProp_");
478                FullClassNameCat(name, regClass.fullName, false);
479                strcat(name, "_Get_");
480                FullClassNameCat(name, prop.name, true);
481                // strcat(name, prop.name);
482                MangleClassName(name);
483                ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
484             }
485             else
486                ListAdd(args, MkExpConstant("0"));
487
488             // Declaration Mode
489             switch(prop.memberAccess)
490             {
491                case staticAccess:
492                   ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
493                   break;
494                case privateAccess:
495                   ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
496                   break;
497                case publicAccess:
498                default:
499                   ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
500                   break;
501             }
502
503             strcpy(name, "__ecereProp_");
504             FullClassNameCat(name, regClass.fullName, false);
505             strcat(name, "_");
506             FullClassNameCat(name, prop.name, true);
507             // strcat(name, prop.name);
508             MangleClassName(name);
509
510             strcpy(nameM, "__ecerePropM_");
511             FullClassNameCat(nameM, regClass.fullName, false);
512             strcat(nameM, "_");
513             FullClassNameCat(nameM, prop.name, true);
514             // strcat(nameM, prop.name);
515             MangleClassName(nameM);
516
517             if(prop.dataTypeString)
518             {
519                stmt = MkExpressionStmt(MkListOne(
520                   MkExpOp(MkExpIdentifier(MkIdentifier(nameM)), '=',
521                   MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddProperty")), args))));
522             }
523             else
524             {
525                stmt = MkExpressionStmt(MkListOne(MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddProperty")), args)));
526             }
527             ListAdd(registerModuleBody.compound.statements, stmt);
528
529             if(prop.IsSet)
530             {
531                char name[1024];
532                strcpy(name, "__ecereProp_");
533                FullClassNameCat(name, regClass.fullName, true);
534                strcat(name, "_IsSet_");
535                FullClassNameCat(name, prop.name, false);
536                // strcat(name, prop.name);
537                MangleClassName(name);
538
539                stmt = MkExpressionStmt(MkListOne(
540                   MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier(nameM)), MkIdentifier("IsSet")), '=',
541                   MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null)), MkExpIdentifier(MkIdentifier(name))))));
542                ListAdd(registerModuleBody.compound.statements, stmt);
543             }
544             if(prop.symbol && ((Symbol)prop.symbol).propCategory)
545             {
546                stmt = MkExpressionStmt(MkListOne(
547                   MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier(nameM)), MkIdentifier("category")), '=',
548                   CopyExpression(((Symbol)prop.symbol).propCategory))));
549                ListAdd(registerModuleBody.compound.statements, stmt);
550             }
551
552             if(prop.dataTypeString)
553             {
554                OldList * list = MkList();
555                ListAdd(list, MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', MkExpIdentifier(MkIdentifier(nameM))));
556                ListAdd(list, MkExpOp(MkExpIdentifier(MkIdentifier(nameM)), '=', MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null)), MkExpConstant("0"))));
557                // stmt = MkIfStmt(MkListOne(MkExpOp(null, '!', MkExpIdentifier(MkIdentifier(name)))), MkExpressionStmt(list), null);
558                stmt = MkIfStmt(MkListOne(MkExpOp(
559                      MkExpMember(MkExpIdentifier(MkIdentifier("module")), MkIdentifier("application")), EQ_OP, 
560                      MkExpMember(MkExpIdentifier(MkIdentifier("__thisModule")), MkIdentifier("application")))), MkExpressionStmt(list), null);
561
562                ListAdd(registerModuleBody.compound.statements, stmt);
563
564                // Unregister 2nd property
565                stmt = MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(nameM)), '=', 
566                   MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null,null), null)), MkExpConstant("0")))));
567                ListAdd(unregisterModuleBody.compound.statements, stmt);
568             }
569          }
570       }
571       else if(member.type == normalMember && !isMember && regClass.type == bitClass)
572       {
573          BitMember bitMember = (BitMember) member;
574          OldList * args = MkList();
575
576          // Class class
577          ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
578
579          // char * name
580          {
581             char * string = QMkString(bitMember.name);
582             ListAdd(args, MkExpString(string));
583             delete string;
584          }
585          // char * type
586          {
587             char * string = QMkString(bitMember.dataTypeString);
588             ListAdd(args, MkExpString(string));
589             delete string;
590          }
591          // int bitSize
592          {
593             char string[256];
594             sprintf(string, "%d", bitMember.size);
595             ListAdd(args, (exp = MkExpConstant(string)));
596          }
597          // int bitPos
598          {
599             char string[256];
600             sprintf(string, "%d", bitMember.pos);
601             ListAdd(args, (exp = MkExpConstant(string)));
602          }
603
604          // Declaration Mode
605          switch(member.memberAccess)
606          {
607             case staticAccess:
608                ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
609                break;
610             case privateAccess:
611                ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
612                break;
613             case publicAccess:
614             default:
615                ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
616                break;
617          }
618
619          stmt = MkExpressionStmt(MkListOne(
620             MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddBitMember")), args)));
621
622          ListAdd(statement.compound.statements, stmt);
623       }
624       else if(member.memberAccess == publicAccess || (member.type == normalMember && !member.dataTypeString))
625       {
626          OldList * args;
627          // ADD PRIVATE DATA PADDING HERE...
628          if(privateMembers)
629          {
630             uint offset = member.offset - lastOffset;
631
632             args = MkList();
633
634             // Class class
635             ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
636
637             // char * name
638             {
639                char string[200];
640                sprintf(string, "\"__ecerePrivateData%d\"", privateID++);
641                ListAdd(args, MkExpString(string));
642             }
643             // char * type
644             {
645                char string[200];
646                sprintf(string, "\"byte[%d]\"", offset);
647                ListAdd(args, MkExpString(string));
648             }
649             // int size
650             {
651                char string[256];
652                sprintf(string, "%d", offset);
653                ListAdd(args, (exp = MkExpConstant(string)));
654             }
655
656             // int alignment
657             ListAdd(args, (exp = MkExpConstant("1")));
658
659             // Declaration Mode
660             ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
661             
662             stmt = MkExpressionStmt(MkListOne(
663                MkExpCall(MkExpIdentifier(MkIdentifier(isMember ? "eMember_AddDataMember" : "eClass_AddDataMember")), args)));
664
665             ListAdd(statement.compound.statements, stmt);
666             privateMembers = false;
667          }
668
669          if(member.type == normalMember)
670          {
671             if(!member.dataType)
672                member.dataType = ProcessTypeString(member.dataTypeString, false);
673
674             ComputeTypeSize(member.dataType);
675
676             args = MkList();
677
678             // Class class
679             ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
680
681             // char * name
682             {
683                char * string = QMkString(member.name);
684                ListAdd(args, MkExpString(string));
685                delete string;
686             }
687             // char * type
688             {
689                char * string = QMkString(member.dataTypeString);
690                ListAdd(args, MkExpString(string));
691                delete string;
692             }
693             // int size
694             {
695                char string[256];
696                sprintf(string, "%d", member.dataType.size);
697                ListAdd(args, (exp = MkExpConstant(string)));
698             }
699
700             // int alignment
701             {
702                char string[256];
703                sprintf(string, "%d", member.dataType.alignment);
704                ListAdd(args, (exp = MkExpConstant(string)));
705             }
706
707             // Declaration Mode
708             switch(member.memberAccess)
709             {
710                case staticAccess:
711                   ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
712                   break;
713                case privateAccess:
714                   ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
715                   break;
716                case publicAccess:
717                default:
718                   ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
719                   break;
720             }
721             
722             stmt = MkExpressionStmt(MkListOne(
723                MkExpCall(MkExpIdentifier(MkIdentifier(isMember ? "eMember_AddDataMember" : "eClass_AddDataMember")), args)));
724
725             ListAdd(statement.compound.statements, stmt);
726
727             lastOffset = member.offset + member.dataType.size;
728          }
729          else
730          {
731             static int memberCount = 0;
732
733             Context context;
734             Statement compound;
735             char memberName[256];
736             sprintf(memberName, "dataMember%d", memberCount);
737             memberCount++;
738
739             curContext = statement.compound.context;
740             context = PushContext();
741             
742             args = MkListOne(MkExpIdentifier(MkIdentifier((member.type == unionMember) ? "unionMember" : "structMember")));
743             
744             // Declaration Mode
745             switch(member.memberAccess)
746             {
747                case staticAccess:
748                   ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
749                   break;
750                case privateAccess:
751                   ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
752                   break;
753                case publicAccess:
754                default:
755                   ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
756                   break;
757             }
758             
759             compound = MkCompoundStmt(MkListOne(MkDeclaration(MkListOne(MkSpecifierName("DataMember")), 
760                MkListOne(MkInitDeclarator(/*MkDeclaratorPointer(MkPointer(null, null), */MkDeclaratorIdentifier(MkIdentifier(memberName))/*)*/, 
761                   MkInitializerAssignment(MkExpCall(MkExpIdentifier(MkIdentifier("eMember_New")), args)))))), MkList());
762             compound.compound.context = context;
763          
764             args = MkList();
765
766             // Class class / DataMember member
767             ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
768
769             // DataMember dataMember
770             ListAdd(args, MkExpIdentifier(MkIdentifier(memberName)));
771
772             RegisterMembersAndProperties((Class)member, true, memberName, compound);
773
774             if(isMember)
775                stmt = MkExpressionStmt(MkListOne(
776                   MkExpCall(MkExpIdentifier(MkIdentifier("eMember_AddMember")), args)));
777             else
778                stmt = MkExpressionStmt(MkListOne(
779                   MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddMember")), args)));
780
781             ListAdd(compound.compound.statements, stmt);
782
783             PopContext(context);
784
785             ListAdd(statement.compound.statements, compound);
786
787             memberCount--;
788
789             lastOffset = member.offset + member.memberOffset;
790          }
791       }
792       else
793          privateMembers = true;
794    }
795
796    if(!isMember)
797    {
798       ClassProperty classProperty;
799
800       // Watchable properties
801       for(prop = regClass.membersAndProperties.first; prop; prop = prop.next)
802       {
803          if(prop.isProperty && prop.isWatchable)
804          {
805             OldList * args;
806             char name[1024], nameM[1024];
807
808             strcpy(name, "__ecereProp_");
809             FullClassNameCat(name, regClass.fullName, true);
810             strcat(name, "_");
811             FullClassNameCat(name, prop.name, false);
812             // strcat(name, prop.name);
813             MangleClassName(name);
814
815             strcpy(nameM, "__ecerePropM_");
816             FullClassNameCat(nameM, regClass.fullName, true);
817             strcat(nameM, "_");
818             FullClassNameCat(nameM, prop.name, false);
819             // strcat(nameM, prop.name);
820             MangleClassName(nameM);
821
822             args = MkListOne(MkExpCondition(MkExpIdentifier(MkIdentifier(nameM)), MkListOne(MkExpIdentifier(MkIdentifier(nameM))), MkExpIdentifier(MkIdentifier(name))));
823             stmt = MkExpressionStmt(MkListOne(
824                MkExpCall(MkExpIdentifier(MkIdentifier("eProperty_Watchable")), args)));
825             ListAdd(registerModuleBody.compound.statements, stmt);
826          }
827       }
828
829       // Add Class Properties
830       for(classProperty = (ClassProperty)regClass.classProperties.first; classProperty; classProperty = (ClassProperty)((BTNode)classProperty).next)
831       {
832          OldList * args = MkList();
833          char name[1024];
834          char * string = QMkString(classProperty.name);
835
836          // Class * class
837          ListAdd(args, MkExpIdentifier(MkIdentifier(className)));
838
839          // char * name
840          ListAdd(args, MkExpString(string));
841          delete string;
842
843          // char * type
844          {
845             char * string = QMkString(classProperty.dataTypeString);
846             ListAdd(args, MkExpString(string));
847             delete string;
848          }
849          // void * Set
850          if(classProperty.Set)
851          {
852             strcpy(name, "__ecereClassProp_");
853             FullClassNameCat(name, regClass.fullName, true);
854             strcat(name, "_Set_");
855             strcat(name, classProperty.name);
856             MangleClassName(name);
857             ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
858          }
859          else
860             ListAdd(args, MkExpConstant("0"));
861          // void * Get
862          if(classProperty.Get)
863          {
864             strcpy(name, "__ecereClassProp_");
865             FullClassNameCat(name, regClass.fullName, true);
866             strcat(name, "_Get_");
867             strcat(name, classProperty.name);
868             MangleClassName(name);
869
870             ListAdd(args, MkExpIdentifier(MkIdentifier(name)));
871          }
872          else
873             ListAdd(args, MkExpConstant("0"));
874
875          stmt = MkExpressionStmt(MkListOne(MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddClassProperty")), args)));
876          ListAdd(registerModuleBody.compound.statements, stmt);
877       }
878    }
879 }
880
881 extern External curExternal;
882
883 void GetNameSpaceString(NameSpace ns, char * string)
884 {
885    if(ns.parent)
886       GetNameSpaceString(ns.parent, string);
887    if(ns.name)
888    {
889       strcat(string, ns.name);
890       strcat(string, "::");
891    }
892 }
893
894 // *******************************************************************
895 static void ProcessClass(ClassType classType, OldList definitions, Symbol symbol, OldList baseSpecs, OldList enumValues, OldList defs, External external, AccessMode declMode)
896 {
897    ClassDef def;
898    Class regClass = symbol.registered;
899    
900    if(regClass)
901    {
902       classType = regClass.type;
903       if(classType == enumClass && enumValues && (inCompiler || !buildingECERECOMModule))
904       {
905          Enumerator e;
906          for(e = enumValues.first; e; e = e.next)
907          {
908             if(e.exp)
909             {
910                Type destType
911                {
912                   kind = intType;
913                   refCount = 1;
914                };
915                e.exp.destType = destType;
916             
917                // Set parsingType to avoid producing errors
918                parsingType = true;
919                ProcessExpressionType(e.exp);
920                parsingType = false;
921
922                if(!e.exp.expType)
923                {
924                   destType.kind = TypeKind::classType;
925                   destType._class = symbol;
926                   ProcessExpressionType(e.exp);
927                }
928                ComputeExpression(e.exp);
929                if(e.exp.isConstant && /*e.exp.expType.kind == intType*/ e.exp.type == constantExp)
930                {
931                   Operand op = GetOperand(e.exp);
932                   int value;
933                   // TODO: 64 BIT ENUM SUPPORT...
934                   switch(op.kind)
935                   {
936                      case charType: value = op.c; break;
937                      case shortType: value = op.s; break;
938                      default: value = op.i;
939                   }
940
941                   // value = op.i; //strtol(e.exp.string, null, 0);
942                   eEnum_AddFixedValue(regClass, e.id.string, value);
943                }
944                else
945                   // Sort of an error
946                   eEnum_AddValue(regClass, e.id.string);                        
947             }
948             else
949                eEnum_AddValue(regClass, e.id.string);
950          }
951       }
952
953       // Process all functions
954       if(definitions != null)
955       {
956          if(inCompiler)
957          {
958             for(def = definitions.first; def; def = def.next)
959             {
960                if(def.type == propertyWatchClassDef && def.propertyWatch)
961                {
962                   PropertyWatch propWatch = def.propertyWatch;
963                   ClassFunction func;
964                   char watcherName[1024];
965                   Identifier propID;
966                   Statement stmt = MkExpressionStmt(MkList());
967                   Declarator decl;
968
969                   sprintf(watcherName,"__ecerePropertySelfWatcher_%d", propWatcherID++);
970                   for(propID = propWatch.properties->first; propID; propID = propID.next)
971                   {
972                      strcat(watcherName, "_");
973                      strcat(watcherName, propID.string);
974                   }
975
976                   // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
977                   decl = MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)), MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null)));
978                   func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, decl, null);
979                   ProcessClassFunctionBody(func, propWatch.compound);
980
981                   // TESTING WITH SAME SYMBOL ID AS CLASS
982                   decl.symbol = Symbol
983                   {
984                      id = symbol.id;
985                      idCode = symbol.idCode;
986                   };
987                   excludedSymbols->Add(decl.symbol);
988
989                   func.id = symbol.id;
990                   func.idCode = symbol.idCode;
991                   func.dontMangle = true;
992
993                   // Create a declaration above for constructor to see
994                   {
995                      External externalDecl = MkExternalDeclaration(null);
996                      Declaration decl;
997                      OldList * specifiers = MkList();
998                      ListAdd(specifiers, MkSpecifier(STATIC));
999                      ListAdd(specifiers, MkSpecifier(VOID));
1000
1001                      ast->Insert(curExternal.prev, externalDecl);
1002                
1003                      decl = MkDeclaration(specifiers, 
1004                         MkListOne(MkInitDeclarator(MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)), 
1005                            MkListOne(MkTypeName(MkListOne(MkSpecifierName(regClass.fullName)), null))), null)));
1006                      externalDecl.declaration = decl;
1007                      if(decl.symbol && !decl.symbol.methodExternal)
1008                      {
1009                         decl.symbol.methodExternal = externalDecl;
1010
1011                         // PATCHED THIS, 2 SYMBOLS WERE THERE.. THIS ONE HAD AN ID TOO BIG
1012                         decl.symbol.id = symbol.id;
1013                         decl.symbol.idCode = symbol.idCode;
1014                      }
1015                   }
1016             
1017                   propWatch.compound = null;
1018                   definitions.Insert(null, MkClassDefFunction(func));
1019
1020                   stmt.type = expressionStmt;
1021                   stmt.expressions = MkList();
1022
1023                   for(propID = propWatch.properties->first; propID; propID = propID.next)
1024                   {
1025                      Property prop = eClass_FindProperty(regClass, propID.string, privateModule);
1026                      if(prop)
1027                      {
1028                         // eProperty_SelfWatch(_class, name, callback);
1029                         OldList * args = MkList();
1030                         ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1031                         ListAdd(args, MkExpString(QMkString(propID.string)));
1032                         ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
1033
1034                         ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("eProperty_SelfWatch")), args));
1035                      }
1036                      else
1037                         Compiler_Error($"Property %s not found in class %s\n", propID.string, regClass.fullName);
1038                   }
1039                   FreePropertyWatch(def.propertyWatch);
1040                   def.propertyWatch = (PropertyWatch)stmt; // Store this here to use it after CreateRegisterModuleBody is done
1041
1042                   // ListAdd(statements, stmt);
1043                }
1044             }
1045          }
1046
1047          for(def = definitions.first; def; def = def.next)
1048          {
1049             if(def.type == functionClassDef)
1050             {
1051                ProcessClassFunction(regClass, def.function, defs, external.prev, declMode == staticAccess);
1052             }
1053          }
1054       }
1055
1056       // Make the RegisterClass section
1057
1058       if(inCompiler && symbol.id != MAXINT && regClass)
1059       {
1060          Statement stmt;
1061          OldList * args = MkList();
1062          Method method;
1063          Expression exp;
1064          char * registerFunction = null;
1065          AccessMode inheritanceAccess = publicAccess;
1066
1067          CreateRegisterModuleBody();
1068
1069          curExternal = registerModuleExternal;
1070
1071           // Class Type
1072          switch(regClass.type)
1073          {
1074             case structClass: ListAdd(args, MkExpIdentifier(MkIdentifier("structClass"))); break;
1075             case bitClass:    ListAdd(args, MkExpIdentifier(MkIdentifier("bitClass"))); break;
1076             case enumClass:   ListAdd(args, MkExpIdentifier(MkIdentifier("enumClass"))); break;
1077             case noHeadClass: ListAdd(args, MkExpIdentifier(MkIdentifier("noHeadClass"))); break;
1078             case unitClass:   ListAdd(args, MkExpIdentifier(MkIdentifier("unitClass"))); break;
1079             case normalClass: ListAdd(args, MkExpIdentifier(MkIdentifier("normalClass"))); break;
1080          }
1081
1082          {
1083             char nameSpace[1024] = "";
1084             char className[1024] = "";
1085             char * string;
1086             GetNameSpaceString(regClass.nameSpace, nameSpace);
1087
1088             if(declMode == staticAccess)
1089             {
1090                GetLastDirectory(sourceFile, className);
1091                ChangeCh(className, '.', '_');
1092                strcat(className, "}");
1093             }
1094             strcat(className, nameSpace);
1095             strcat(className, regClass.name);
1096             string = QMkString(className);
1097             ListAdd(args, MkExpString(string));
1098             delete string;
1099          }
1100
1101          /*
1102          {
1103             char * string = QMkString(regClass.base.name);
1104             ListAdd(args, regClass.base ? MkExpString(string) :
1105                MkExpConstant("0"));
1106             delete string;
1107          }
1108          */
1109
1110          if(baseSpecs != null)
1111          {
1112             Type baseType = ProcessType(baseSpecs, null);
1113             if(baseType.kind != structType && baseType.kind != unionType)
1114             {
1115                char baseName[1024] = "";
1116                char * string;
1117                if(baseType.kind == TypeKind::classType && baseType._class && baseType._class.isStatic)
1118                {
1119                   // TODO: Handle static classes and complex declarators...
1120                   GetLastDirectory(sourceFile, baseName);
1121                   ChangeCh(baseName, '.', '_');
1122                   strcat(baseName, "}");
1123                   strcat(baseName, baseType._class.string);
1124                }
1125                else
1126                   PrintType(baseType, baseName, false, true);
1127
1128                string = QMkString(baseName);
1129                ListAdd(args, MkExpString(string));
1130                delete string;
1131             }
1132             else
1133                ListAdd(args, MkExpConstant("0"));
1134             FreeType(baseType);
1135             if(((Specifier)baseSpecs.first).type == baseSpecifier && ((Specifier)baseSpecs.first).specifier == PRIVATE)
1136                inheritanceAccess = privateAccess;
1137          }
1138          else
1139             ListAdd(args, MkExpConstant("0"));
1140
1141          //ListAdd(args, class.declaredStruct ? MkExpTypeSize(MkTypeName(MkListOne(
1142             //MkSpecifierName(class.structName)), null)) : MkExpConstant("0"));
1143       
1144          if(regClass.type == structClass || regClass.type == normalClass || regClass.type == noHeadClass)
1145          {
1146             // Check if we have a data member in this class
1147             DataMember member = null;
1148             {
1149                Class base;
1150                for(base = regClass.base; base && base.type != systemClass; base = base.next)
1151                {
1152                   for(member = base.membersAndProperties.first; member; member = member.next)
1153                      if(!member.isProperty)
1154                         break;
1155                   if(member)
1156                      break;
1157                }
1158             }
1159
1160             if(regClass.type == structClass && symbol.declaredStruct && member)
1161             {
1162                char baseStructName[1024];
1163                baseStructName[0] = 0;
1164                // TESTING THIS HERE
1165                // FullClassNameCat(baseStructName, regClass.base.fullName, false);
1166                strcpy(baseStructName, (regClass.base.templateClass ? regClass.base.templateClass : regClass.base).fullName);
1167
1168                ListAdd(args, MkExpOp(
1169                   MkExpTypeSize(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(symbol.structName), null)), null)), '-',
1170                   MkExpTypeSize(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(baseStructName), null)), null))));
1171             }
1172             else
1173                ListAdd(args, symbol.declaredStruct ? MkExpTypeSize(MkTypeName(MkListOne(
1174                   MkStructOrUnion(structSpecifier, MkIdentifier(symbol.structName), null)), null)) : MkExpConstant("0"));
1175          }
1176          else
1177          {
1178             ListAdd(args, MkExpConstant("0"));
1179          }
1180
1181          //if(regClass.type == normalClass)
1182          {
1183             char classDataStructName[1024];
1184             strcpy(classDataStructName, "__ecereClassData_");
1185             FullClassNameCat(classDataStructName, symbol.string, false);
1186
1187             ListAdd(args, symbol.classData ? MkExpTypeSize(MkTypeName(MkListOne(
1188                MkStructOrUnion(structSpecifier, MkIdentifier(classDataStructName), null)), null)) : MkExpConstant("0"));
1189          }
1190          /*else
1191             // TODO: Support Class Data for all other types of classes
1192             ListAdd(args, MkExpConstant("0"));
1193             */
1194
1195          if(regClass.type == normalClass || regClass.type == noHeadClass)
1196          {
1197             // Constructor
1198             ListAdd(args, symbol.needConstructor ? 
1199                MkExpIdentifier(MkIdentifier(symbol.constructorName)) :
1200                MkExpConstant("0"));
1201             // Destructor
1202             ListAdd(args, symbol.needDestructor ? 
1203                MkExpIdentifier(MkIdentifier(symbol.destructorName)) :
1204                MkExpConstant("0"));
1205          }
1206          else
1207          {
1208             // TODO: Support Constructors / Destructors for structs
1209
1210             // Constructor
1211             ListAdd(args, MkExpConstant("0"));
1212             // Destructor
1213             ListAdd(args, MkExpConstant("0"));
1214          }
1215
1216          // Module
1217          ListAdd(args, MkExpIdentifier(MkIdentifier("module")));
1218
1219          // Declaration Mode
1220          switch(declMode)
1221          {
1222             case staticAccess:
1223                ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1224                break;
1225             case privateAccess:
1226                ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1227                break;
1228             case publicAccess:
1229             default:
1230                ListAdd(args, MkExpIdentifier(MkIdentifier(buildingECERECOMModule ? "baseSystemAccess" : "publicAccess")));
1231                break;
1232          }
1233          
1234          // Declaration Mode
1235          switch(inheritanceAccess)
1236          {
1237             case privateAccess:
1238                ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1239                break;
1240             case publicAccess:
1241             default:
1242                ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
1243                break;
1244          }
1245
1246          registerFunction = "eSystem_RegisterClass";
1247
1248          stmt = MkExpressionStmt(MkListOne(
1249             MkExpOp(MkExpIdentifier(MkIdentifier("class")), '=',
1250             MkExpCall((exp = MkExpIdentifier(MkIdentifier(registerFunction))), args))));
1251
1252          ListAdd(registerModuleBody.compound.statements, stmt);
1253
1254          /*
1255          stmt = MkIfStmt(MkListOne(MkExpOp(null, '!', MkExpIdentifier(MkIdentifier(symbol.className)))),
1256                MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(symbol.className)), '=',
1257             MkExpIdentifier(MkIdentifier("class"))))), null);
1258          */
1259
1260          stmt = MkIfStmt(MkListOne(
1261                   MkExpOp(MkExpOp(
1262                      MkExpMember(MkExpIdentifier(MkIdentifier("module")), MkIdentifier("application")), EQ_OP, 
1263                      MkExpMember(MkExpIdentifier(MkIdentifier("__thisModule")), MkIdentifier("application"))), AND_OP, MkExpIdentifier(MkIdentifier("class")))),
1264                MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(symbol.className)), '=',
1265             MkExpIdentifier(MkIdentifier("class"))))), null);
1266          /*
1267          stmt = MkIfStmt(MkListOne(
1268                   MkExpOp(MkExpOp(null, '!', MkExpIdentifier(MkIdentifier(symbol.className))), AND_OP, MkExpIdentifier(MkIdentifier("class")))),
1269                MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(symbol.className)), '=',
1270             MkExpIdentifier(MkIdentifier("class"))))), null);
1271          */
1272
1273          ListAdd(registerModuleBody.compound.statements, stmt);
1274
1275          if(external && external.type == classExternal && external._class.deleteWatchable)
1276          {
1277             args = MkListOne(MkExpIdentifier(MkIdentifier("class")));
1278             stmt = MkExpressionStmt(MkListOne(
1279                MkExpCall(MkExpIdentifier(MkIdentifier("eClass_DestructionWatchable")), args)));
1280             ListAdd(registerModuleBody.compound.statements, stmt);
1281          }
1282
1283          // Add Virtual Methods
1284          if(regClass.base)
1285          {
1286             Class base = regClass.base;
1287             int c;
1288             for(c = 0; c<base.vTblSize; c++)
1289             {
1290                Symbol method = (Symbol)regClass._vTbl[c];
1291                if((void *) method != DummyMethod && base._vTbl[c] != (void *)method ) // TOLOOKAT: Module check here?
1292                {
1293                   External external = method.methodExternal;
1294                   OldList * args = MkList();
1295                   Identifier id = external.function ? GetDeclId(external.function.declarator) : null;
1296                
1297                   // Class class
1298                   ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1299                   // char * name
1300                   {
1301                      //char * string = QMkString(method.string);
1302
1303                      char * string = QMkString(method.method.name);
1304                      ListAdd(args, MkExpString(string));
1305                      delete string;
1306                   }
1307                   // char * type
1308                   ListAdd(args, MkExpConstant("0"));
1309                   // void * function
1310                   ListAdd(args, (exp = MkExpIdentifier(MkIdentifier(
1311                      id.string))));
1312
1313                   // Declaration Mode
1314                   ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
1315
1316                   exp.expType = Type { refCount = 1 };
1317                   stmt = MkExpressionStmt(MkListOne(
1318                      MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddMethod")), args)));
1319                   ListAdd(registerModuleBody.compound.statements, stmt);
1320                }
1321             }
1322          }
1323
1324          // Add Virtual Methods in order
1325          {
1326             int c;
1327             for(c = regClass.base ? regClass.base.vTblSize : 0; c < regClass.vTblSize; c++)
1328             {
1329                for(method = (Method)regClass.methods.first; method; method = (Method)((BTNode)method).next)
1330                {
1331                   if(method.type == virtualMethod && method._class == regClass && method.vid == c)
1332                   {
1333                      char name[1024];
1334                      Expression exp;
1335
1336                      //External external = method->symbol ? ((Symbol)method.symbol).methodExternal : null;
1337                      External external = method.symbol ? ((Symbol)method.symbol).methodCodeExternal : null;
1338                      OldList * args = MkList();
1339                      Identifier id = (external && external.function) ? GetDeclId(external.function.declarator) : null;
1340
1341                      // Class * class
1342                      ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1343                      // char * name
1344                      {
1345                         char * string = QMkString(method.name);
1346                         ListAdd(args, MkExpString(string));
1347                         delete string;
1348                      }
1349                      // char * type
1350                      {
1351                         char * string = QMkString(method.dataTypeString);
1352                         ListAdd(args, MkExpString(string));
1353                         delete string;
1354                      }
1355                      // void * function
1356                      if(id && external.function.body)
1357                      {
1358                         ListAdd(args, (exp = MkExpIdentifier(MkIdentifier(id.string))));
1359                         exp.expType = Type { refCount = 1 };
1360                      }
1361                      else
1362                      {
1363                         ListAdd(args, (exp = MkExpConstant("0")));
1364                      }
1365
1366                      // Declaration Mode
1367                      switch(method.memberAccess)
1368                      {
1369                         case staticAccess:
1370                            ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1371                            break;
1372                         case privateAccess:
1373                            ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1374                            break;
1375                         case publicAccess:
1376                         default:
1377                            ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
1378                            break;
1379                      }
1380
1381                      //sprintf(name, "__ecereVMethodID_%s_%s", method._class.fullName, method.name);
1382                      strcpy(name, "__ecereVMethodID_");
1383                      FullClassNameCat(name, method._class.fullName, false);
1384                      strcat(name, "_");
1385                      strcat(name, method.name);
1386
1387                      exp = /*MkExpPointer(*/MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddVirtualMethod")), args)/*, MkIdentifier("vid"))*/;
1388                      /*
1389                      exp->expType = eSystem_New(sizeof(Type));
1390                      exp->expType->refCount++;
1391                      exp->expType->isSigned = true;
1392                      exp->expType->kind = TypeInt;
1393                      */
1394
1395                      stmt = MkExpressionStmt(MkListOne(/*
1396                         MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', */exp/*)*/));
1397
1398                      DeclareMethod(method, name);
1399
1400                      ListAdd(registerModuleBody.compound.statements, stmt);
1401                   }
1402                }
1403             }
1404          }
1405
1406
1407          // Add Public Methods (all for now)
1408          for(method = (Method)regClass.methods.first; method; method = (Method)((BTNode)method).next)
1409          {
1410             if(method.type == virtualMethod && method._class == regClass);
1411             else if(method.memberAccess == publicAccess || !method.dataTypeString)
1412             {
1413                //External external = method.symbol ? ((Symbol )method.symbol).methodExternal : null;
1414                External external = method.symbol ? ((Symbol )method.symbol).methodCodeExternal : null;
1415                OldList * args = MkList();
1416                Identifier id = (external && external.function) ? GetDeclId(external.function.declarator) : null;
1417
1418                // Class class
1419                ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1420                // char * name
1421                {
1422                   char * string = QMkString(method.name);
1423                   ListAdd(args, MkExpString(string));
1424                   delete string;
1425                }
1426                // char * type
1427                {
1428                   char * string = QMkString(method.dataTypeString);
1429                   ListAdd(args, MkExpString(string));
1430                   delete string;
1431                }
1432                // void * function
1433                if(id && external.function.body)
1434                {
1435                   ListAdd(args, (exp = MkExpIdentifier(MkIdentifier(
1436                      id.string))));
1437                   exp.expType = Type { refCount = 1 };
1438                }
1439                else
1440                {
1441                   ListAdd(args, (exp = MkExpConstant("0")));
1442                }
1443
1444                // Declaration Mode
1445                switch(method.memberAccess)
1446                {
1447                   case staticAccess:
1448                      ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1449                      break;
1450                   case privateAccess:
1451                      ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1452                      break;
1453                   case publicAccess:
1454                   default:
1455                      ListAdd(args, MkExpIdentifier(MkIdentifier("publicAccess")));
1456                      break;
1457                }
1458
1459                stmt = MkExpressionStmt(MkListOne(
1460                   MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddMethod")), args)));
1461                ListAdd(registerModuleBody.compound.statements, stmt);
1462             }
1463          }
1464
1465          RegisterMembersAndProperties(regClass, false, "class", registerModuleBody);
1466
1467          // Add Enumeration Values
1468          if(classType == enumClass)
1469          {
1470             NamedLink value;
1471             Class enumClass = eSystem_FindClass(privateModule, "enum");
1472             EnumClassData e = ACCESS_CLASSDATA(regClass, enumClass);
1473
1474             for(value = e.values.first; value; value = value.next)
1475             {
1476                OldList * args = MkList();
1477
1478                // Class class
1479                ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1480                // char * name
1481                {
1482                   char * string = QMkString(value.name);
1483                   ListAdd(args, MkExpString(string));
1484                   delete string;
1485                }
1486                // uint value
1487                {
1488                   char temp[1024];
1489                   // TODO: Support 64 bit enums
1490                   sprintf(temp, "%d", (int)value.data);
1491                   ListAdd(args, MkExpConstant(temp));
1492                }
1493
1494                stmt = MkExpressionStmt(MkListOne(
1495                   MkExpCall(MkExpIdentifier(MkIdentifier("eEnum_AddFixedValue")), args)));
1496                ListAdd(registerModuleBody.compound.statements, stmt);
1497             }
1498          }
1499
1500          // Add Template Parameters
1501          if(symbol.templateParams)
1502          {
1503             TemplateParameter param;
1504             for(param = symbol.templateParams->first; param; param = param.next)
1505             {
1506                OldList * args = MkList();
1507
1508                // Class
1509                ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1510
1511                // Name
1512                {
1513                   char * string = QMkString(param.identifier.string);
1514                   ListAdd(args, MkExpString(string));
1515                   delete string;
1516                }
1517
1518                // Type
1519                ListAdd(args, MkExpIdentifier(MkIdentifier((param.type == type) ? "type" : ((param.type == identifier) ? "identifier" : "expression"))));
1520
1521                // Parameter
1522                switch(param.type)
1523                {
1524                   case type:
1525                   case expression:
1526                   {
1527                      char * typeString = param.dataType ? StringFromSpecDecl(param.dataType.specifiers, param.dataType.decl) : null;
1528                      char * string = QMkString(typeString);
1529                      ListAdd(args, MkExpString(string));
1530                      delete typeString;
1531                      delete string;
1532                      break;
1533                   }
1534                   case identifier:
1535                   {
1536                      char memberTypeString[132] = "TemplateMemberType::";
1537                      bool needClass = true;
1538                      
1539                      param.memberType.OnGetString(memberTypeString + strlen(memberTypeString), null, &needClass);
1540                      ListAdd(args, 
1541                         MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)), 
1542                            MkExpIdentifier(MkIdentifier(memberTypeString))));
1543                      break;
1544                   }
1545                }
1546
1547                // Default Argument
1548                if(param.defaultArgument)
1549                {
1550                   OldList * members = MkList();
1551                   switch(param.type)
1552                   {
1553                      case type:
1554                      {
1555                         char * typeString = param.defaultArgument.templateDatatype ? 
1556                            StringFromSpecDecl(param.defaultArgument.templateDatatype.specifiers, param.defaultArgument.templateDatatype.decl) : null;
1557                         char * string = QMkString(typeString);
1558
1559                         members->Add(MkMemberInit(MkListOne(MkIdentifier("dataTypeString")), MkInitializerAssignment(MkExpString(string))));
1560
1561                         delete typeString;
1562                         delete string;
1563                         break;
1564                      }
1565                      case identifier:
1566                      {
1567                         char memberString[1024];
1568                         char * string;
1569                         memberString[0] = '\0';
1570
1571                         if(param.defaultArgument.identifier._class)
1572                         {
1573                            if(param.defaultArgument.identifier._class.type == templateTypeSpecifier)
1574                               strcpy(memberString, param.defaultArgument.identifier._class.templateParameter.identifier.string);
1575                            else if(param.defaultArgument.identifier._class.name)
1576                               strcpy(memberString, param.defaultArgument.identifier._class.name);
1577                         }
1578                         if(memberString[0])
1579                            strcat(memberString, "::");
1580
1581                         strcat(memberString, param.defaultArgument.identifier.string);
1582
1583                         string = QMkString(memberString);
1584
1585                         // TOFIX: UNIONS ARE BROKEN FOR ASSIGNMENTS, USING dataTypeString INSTEAD
1586                         // members->Add(MkMemberInit(MkListOne(MkIdentifier("memberString")), MkInitializerAssignment(MkExpString(string))));
1587                         members->Add(MkMemberInit(MkListOne(MkIdentifier("dataTypeString")), MkInitializerAssignment(MkExpString(string))));                        
1588
1589                         delete string;
1590                         break;
1591                      }
1592                      case expression:
1593                      {
1594                         Operand op { };
1595                         OldList * ids = MkList();
1596                         char * ui64String;
1597                         char * string = null;
1598
1599                         //ProcessExpressionType(param.defaultArgument.expression);
1600                         //ComputeExpression(param.defaultArgument.expression);
1601
1602                         op = GetOperand(param.defaultArgument.expression);
1603                         ui64String = PrintUInt64(op.ui64);
1604                         ids->Add(MkIdentifier("expression"));
1605                         ids->Add(MkIdentifier("ui64"));
1606
1607                         //string = QMkString(ui64String);
1608                         members->Add(MkMemberInit(ids, MkInitializerAssignment(MkExpConstant(ui64String))));
1609                         
1610                         delete string;
1611                         delete ui64String;
1612                         break;
1613                      }
1614                   }
1615                   ListAdd(args, MkExpInstance(MkInstantiation(MkSpecifierName("ClassTemplateArgument"), null,
1616                      MkListOne(MkMembersInitList(members)))));
1617                }
1618                else
1619                   ListAdd(args, MkExpIdentifier(MkIdentifier("null")));
1620
1621                stmt = MkExpressionStmt(MkListOne(
1622                   MkExpCall(MkExpIdentifier(MkIdentifier("eClass_AddTemplateParameter")), args)));
1623                ListAdd(registerModuleBody.compound.statements, stmt);
1624             }
1625             stmt = MkExpressionStmt(MkListOne(
1626                MkExpCall(MkExpIdentifier(MkIdentifier("eClass_DoneAddingTemplateParameters")), 
1627                   MkListOne(MkExpIdentifier(MkIdentifier("class"))))));
1628             ListAdd(registerModuleBody.compound.statements, stmt);
1629          }
1630
1631          if(definitions != null)
1632          {
1633             for(def = definitions.first; def; def = def.next)
1634             {
1635                if(def.type == propertyWatchClassDef && def.propertyWatch)
1636                {
1637                   ListAdd(registerModuleBody.compound.statements, (Statement)def.propertyWatch);
1638                   def.propertyWatch = null;
1639                }
1640                else if(def.type == classDesignerClassDef)
1641                {
1642                   /*
1643                   char className[1024];
1644                   sprintf(className, "__ecereClass_%s", def.designer);
1645                   MangleClassName(className);
1646
1647                   DeclareClass(FindClass(def.designer), className);
1648                   */
1649
1650                   stmt = MkIfStmt(MkListOne(MkExpIdentifier(MkIdentifier("class"))), MkExpressionStmt(MkListOne(
1651                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("designerClass")), '=',
1652                         MkExpString(QMkString(def.designer))))), null);
1653                   ListAdd(registerModuleBody.compound.statements, stmt);
1654                }
1655                else if(def.type == classNoExpansionClassDef)
1656                {
1657                   stmt = MkIfStmt(MkListOne(MkExpIdentifier(MkIdentifier("class"))), MkExpressionStmt(MkListOne(
1658                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("noExpansion")), '=',
1659                         MkExpConstant("1")))), null);
1660                   ListAdd(registerModuleBody.compound.statements, stmt);
1661                }
1662                else if(def.type == classFixedClassDef)
1663                {
1664                   stmt = MkIfStmt(MkListOne(MkExpIdentifier(MkIdentifier("class"))), MkExpressionStmt(MkListOne(
1665                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("fixed")), '=',
1666                         MkExpConstant("1")))), null);
1667                   ListAdd(registerModuleBody.compound.statements, stmt);
1668                   if(regClass)
1669                      regClass.fixed = true;
1670                }
1671                else if(def.type == designerDefaultPropertyClassDef)
1672                {
1673                   stmt = MkIfStmt(MkListOne(MkExpIdentifier(MkIdentifier("class"))), MkExpressionStmt(MkListOne(
1674                      MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("class")), MkIdentifier("defaultProperty")), '=',
1675                         MkExpString(QMkString(def.defaultProperty.string))))), null);
1676                   ListAdd(registerModuleBody.compound.statements, stmt);
1677                }
1678                else if(def.type == classPropertyValueClassDef)
1679                {
1680                   OldList * args = MkList();
1681                   ListAdd(args, MkExpIdentifier(MkIdentifier("class")));
1682                   ListAdd(args, MkExpString(QMkString(def.id.string)));
1683                   ListAdd(args, MkExpCast(MkTypeName(MkListOne(MkSpecifier(INT64)), null), def.initializer.exp));
1684
1685                   def.initializer.exp = null;
1686
1687                   stmt = MkExpressionStmt(MkListOne(
1688                      MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eClass_SetProperty")), args)));
1689
1690                   ListAdd(registerModuleBody.compound.statements, stmt);
1691                }
1692             }
1693          }
1694       }
1695    }
1696 }
1697
1698 public void ProcessClassDefinitions()
1699 {
1700    External external, next;
1701
1702    CreateRegisterModuleBody();
1703    if(ast)
1704    {
1705       // (Need to do those things after in case something is not yet defined)
1706       for(external = ast->first; external; external = next)
1707       {
1708          next = external.next;
1709          curExternal = external;
1710          if(external.type == classExternal)
1711          {
1712             ClassDefinition _class = external._class;
1713             if(_class.definitions)
1714             {
1715                ProcessClass(normalClass, _class.definitions, _class.symbol, _class.baseSpecs, null, ast, external, _class.declMode);
1716             }
1717             if(inCompiler)
1718             {
1719                ast->Remove(external);
1720                FreeExternal(external);
1721             }
1722          }
1723          else if(external.type == functionExternal)
1724          {
1725             bool setStaticMethod = false;
1726             // Mark
1727             if(external.symbol && !external.symbol.type.thisClass && !external.symbol.type.staticMethod)
1728             {
1729                // TOCHECK: Where do we actually need this to be set?
1730                external.symbol.type.staticMethod = true;
1731                setStaticMethod = true;
1732             }
1733
1734             if(inCompiler)
1735             {
1736                FunctionDefinition function = external.function;
1737                Statement stmt;
1738                OldList * args;
1739
1740                if(!strcmp(function.declarator.symbol.string, "__on_register_module"))
1741                {
1742                   ListAdd(registerModuleBody.compound.statements, function.body);
1743                   function.body.compound.context.parent = registerModuleBody.compound.context;
1744                   ast->Remove(external);
1745                   function.body = null;
1746                   FreeExternal(external);
1747                   continue;
1748                }
1749
1750                if(function.declMode != privateAccess && function.declMode != publicAccess) continue;
1751
1752                args = MkList();
1753
1754                CreateRegisterModuleBody();
1755
1756                // Identifier
1757                {
1758                   char * string = QMkString(function.declarator.symbol.string);
1759                   ListAdd(args, MkExpString(string));
1760                   delete string;
1761                }
1762
1763                // Type
1764                {
1765                   char * string;
1766                   char type[1024] = "";
1767                   // We don't want functions to be marked as static methods
1768                   if(setStaticMethod)
1769                      function.declarator.symbol.type.staticMethod = false;
1770                   PrintType(function.declarator.symbol.type, type, true, true);
1771                   if(setStaticMethod)
1772                      function.declarator.symbol.type.staticMethod = true;
1773                   string = QMkString(type);
1774                   ListAdd(args, MkExpString(string));
1775                   delete string;
1776                }
1777
1778                // Function
1779                {
1780                   ListAdd(args, MkExpIdentifier(MkIdentifier(function.declarator.symbol.string)));
1781                }
1782
1783                // Module
1784                ListAdd(args, MkExpIdentifier(MkIdentifier("module")));
1785
1786                // Declaration Mode
1787                switch(function.declMode)
1788                {
1789                   case staticAccess:
1790                      ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1791                      break;
1792                   case privateAccess:
1793                      ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1794                      break;
1795                   case publicAccess:
1796                   default:
1797                      ListAdd(args, MkExpIdentifier(MkIdentifier(buildingECERECOMModule ? "baseSystemAccess" : "publicAccess")));
1798                      break;
1799                }
1800
1801                stmt = MkExpressionStmt(MkListOne(
1802                   MkExpCall((MkExpIdentifier(MkIdentifier("eSystem_RegisterFunction"))), args)));
1803
1804                ListAdd(registerModuleBody.compound.statements, stmt);
1805             }
1806          }
1807          else if(external.type == declarationExternal)
1808          {
1809             Declaration declaration = external.declaration;
1810
1811             if(external.symbol)
1812             {
1813                if(external.symbol.type && external.symbol.type.kind == functionType && !external.symbol.type.thisClass)
1814                   external.symbol.type.staticMethod = true;
1815             }
1816
1817             if(external.symbol && declaration.type == initDeclaration)
1818             {
1819                if(declaration.specifiers)
1820                {
1821                   Specifier specifier;
1822                   bool removeExternal = false;
1823                
1824                   for(specifier = declaration.specifiers->first; specifier; specifier = specifier.next)
1825                   {
1826                      if((specifier.type == enumSpecifier || specifier.type == structSpecifier || specifier.type == unionSpecifier) && specifier.id && specifier.id.string && 
1827                         (declaration.declMode || specifier.baseSpecs || (specifier.type == enumSpecifier && specifier.definitions)))
1828                      {
1829                         Symbol symbol = FindClass(specifier.id.string);
1830                         if(symbol)
1831                         {
1832                            ClassType classType;
1833                            if(specifier.type == enumSpecifier)
1834                               classType = enumClass;
1835                            else 
1836                               classType = structClass;
1837
1838                            removeExternal = true;
1839                            // Transfer Context over to Symbol
1840                            symbol.ctx = specifier.ctx;
1841                            specifier.ctx = null;
1842
1843                            ProcessClass(classType, specifier.definitions, symbol, specifier.baseSpecs, specifier.list,ast, external, declaration.declMode);
1844                         }
1845                      }
1846                   }               
1847                   if(inCompiler && removeExternal)
1848                   {
1849                      ast->Remove(external);
1850                      FreeExternal(external);
1851                   }
1852                }
1853             }
1854             else if(declaration.type == defineDeclaration)
1855             {
1856                if(inCompiler && declaration.declMode != staticAccess)
1857                {
1858                   Statement stmt;
1859                   OldList * args = MkList();
1860
1861                   CreateRegisterModuleBody();
1862
1863                   // Identifier
1864                   {
1865                      char * string = QMkString(declaration.id.string);
1866                      ListAdd(args, MkExpString(string));
1867                      delete string;
1868                   }
1869
1870                   // Expression
1871                   {
1872                      char * string;
1873                      char type[1024] = "";
1874                      PrintExpression(declaration.exp, type);
1875                      string = QMkString(type);
1876                      ListAdd(args, MkExpString(string));
1877                      delete string;
1878                   }
1879
1880                   // Module
1881                   ListAdd(args, MkExpIdentifier(MkIdentifier("module")));
1882
1883                   // Declaration Mode
1884                   switch(declaration.declMode)
1885                   {
1886                      case staticAccess:
1887                         ListAdd(args, MkExpIdentifier(MkIdentifier("staticAccess")));
1888                         break;
1889                      case privateAccess:
1890                         ListAdd(args, MkExpIdentifier(MkIdentifier("privateAccess")));
1891                         break;
1892                      case publicAccess:
1893                      default:
1894                         ListAdd(args, MkExpIdentifier(MkIdentifier(buildingECERECOMModule ? "baseSystemAccess" : "publicAccess")));
1895                         break;
1896                   }
1897
1898                   stmt = MkExpressionStmt(MkListOne(
1899                      MkExpCall((MkExpIdentifier(MkIdentifier("eSystem_RegisterDefine"))), args)));
1900
1901                   ListAdd(registerModuleBody.compound.statements, stmt);
1902                }
1903             }
1904          }
1905       }
1906    }
1907 }