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