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