compiler: Support for i18n through $"string" syntax (generates .pot, requires libintl...
[sdk] / compiler / libec / src / ast.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.eh"
5 extern char * yytext;
6
7 char * defaultNameSpace;
8 int defaultNameSpaceLen;
9 public void SetDefaultNameSpace(char * s) { defaultNameSpace = s; defaultNameSpaceLen = s ? strlen(s) : 0; }
10
11 bool strictNameSpaces;
12 public void SetStrictNameSpaces(bool b) { strictNameSpaces = b; }
13
14 AccessMode declMode = privateAccess;
15 public void SetDeclMode(AccessMode accessMode) { declMode = accessMode; }
16 AccessMode defaultDeclMode = privateAccess;
17 public void SetDefaultDeclMode(AccessMode accessMode) { defaultDeclMode = accessMode; }
18
19 char * currentNameSpace;
20 int currentNameSpaceLen;
21 public void SetCurrentNameSpace(char * s) { currentNameSpace = s; currentNameSpaceLen = s ? strlen(s) : 0; }
22
23 #ifdef _TIMINGS
24 Time findClassTotalTime;
25 Time checkTypeTotalTime;
26 Time externalImportTotalTime;
27 Time findClassIgnoreNSTotalTime;
28 #endif
29
30 public OldList * MkList()
31 {
32    return new0 OldList[1];
33 }
34
35 public OldList * MkListOne(void * item)
36 {
37    OldList * list = new0 OldList[1];
38    list->Add(item);
39    return list;
40 }
41
42 void ListAdd(OldList list, void * item)
43 {
44    if(item)
45       list.Add(item);
46 }
47
48 void ListAddFront(OldList list, void * item)
49 {
50    if(item)
51       list.Insert(null, item);
52 }
53
54 public Identifier MkIdentifier(char * string)
55 {
56    Identifier id { };
57    int c;
58    
59    id._class = null; // Default class...
60
61    if(string)
62    {
63       char * namePart;
64       bool gotColon = false;
65       for(c = strlen(string)-1; c >= 0; c--)
66          if(string[c] == ':')
67          {
68             gotColon = true;
69             break;
70          }
71
72       namePart = string+c+1;
73       while(c >= 0 && string[c] == ':') c--;
74       if(c >= 0)
75       {
76          char name[1024];
77          Symbol symbol;
78
79          memcpy(name, string, c+1);
80          name[c+1] = '\0';
81          // TODO: Do these better, keep in string?
82          if(!strcmp(name, "typed_object"))
83          {
84             id._class = MkSpecifierName("class");
85             id.string = CopyString(namePart);
86          }
87          else if(!strcmp(name, "property"))
88          {
89             id._class = MkSpecifierName("property");
90             id.string = CopyString(namePart);
91          }
92          else if(!strcmp(name, "typed_object&"))
93          {
94             id._class = MkSpecifierName("typed_object&");
95             id.string = CopyString(namePart);
96          }
97          else if(!strcmp(name, "any_object"))
98          {
99             id._class = MkSpecifierName("any_object");
100             id.string = CopyString(namePart);
101          }
102          else
103          {
104             TemplatedType templatedType = FindTemplateTypeParameter(curContext, name);
105             if(templatedType)
106             {
107                id._class = Specifier { type = templateTypeSpecifier, templateParameter = templatedType.param };
108                //id._class = MkSpecifierName(name);
109                id.string = CopyString(namePart);
110             }
111             else
112             {
113                symbol = FindClass(name);
114                if(symbol)
115                {
116                   id._class = _MkSpecifierName(symbol.string, symbol, null);
117                   id.string = CopyString(namePart);
118                }
119                else
120                   id.string = CopyString(string);
121             }
122          }         
123       }
124       else if(gotColon)
125       {
126          id._class = MkSpecifierName(null);
127          id.string = CopyString(namePart);
128       }
129       else
130          id.string = CopyString(string);
131    }
132    else
133       id.string = CopyString("");
134    return id;
135 }
136
137 public TemplateParameter MkTypeTemplateParameter(Identifier identifier, TemplateDatatype baseTplDatatype, TemplateArgument defaultArgument)
138 {
139    if(identifier.string)
140    {
141       TemplateParameter param { type = TemplateParameterType::type, identifier = identifier, dataType = baseTplDatatype, defaultArgument = defaultArgument };
142       TemplatedType type { key = (uint)identifier.string, param = param };
143       curContext.templateTypes.Add((BTNode)type);
144       return param;
145    }
146    return null;
147 }
148
149 public TemplateParameter MkIdentifierTemplateParameter(Identifier identifier, TemplateMemberType memberType, TemplateArgument defaultArgument)
150 {
151    if(identifier.string)
152    {
153       TemplateParameter param { type = TemplateParameterType::identifier, identifier = identifier, memberType = memberType, defaultArgument = defaultArgument };
154       return param;
155    }
156    return null;
157 }
158
159 public TemplateParameter MkExpressionTemplateParameter(Identifier identifier, TemplateDatatype dataType, TemplateArgument defaultArgument)
160 {
161    if(identifier.string)
162    {
163       TemplateParameter param { type = TemplateParameterType::expression, identifier = identifier, dataType = dataType, defaultArgument = defaultArgument };
164       return param;
165    }
166    return null;
167 }
168
169 public TemplateDatatype MkTemplateDatatype(OldList * specifiers, Declarator decl)
170 {
171    TemplateDatatype datatype { specifiers = specifiers, decl = decl };
172    return datatype;
173 }
174
175 public TemplateArgument MkTemplateTypeArgument(TemplateDatatype tplDatatype)
176 {
177    TemplateArgument argument { type = type, templateDatatype = tplDatatype };
178    return argument;
179 }
180
181 public TemplateArgument MkTemplateExpressionArgument(Expression expr)
182 {
183    TemplateArgument argument { type = expression, expression = expr };
184    return argument;
185 }
186
187 public TemplateArgument MkTemplateIdentifierArgument(Identifier ident)
188 {
189    TemplateArgument argument { type = identifier, identifier = ident };
190    return argument;
191 }
192
193 Expression MkExpExtensionCompound(Statement compound)
194 {
195    return { type = extensionCompoundExp, compound = compound };
196 }
197
198 Expression MkExpExtensionExpression(OldList * expressions)
199 {
200    return { type = extensionExpressionExp, list = expressions, loc = yylloc };
201 }
202
203 Expression MkExpExtensionInitializer(TypeName typeName, Initializer initializer)
204 {
205    return { type = extensionInitializerExp, initializer.typeName = typeName, initializer.initializer = initializer, loc = yylloc };
206 }
207
208 public Expression MkExpIdentifier(Identifier id)
209 {
210    return { type = identifierExp, identifier = id };
211 }
212
213 public Expression MkExpDummy()
214 {
215    return { type = dummyExp };
216 }
217
218 public Expression MkExpConstant(char * string)
219 {
220    return { type = constantExp, constant = CopyString(string) };
221 }
222
223 Expression MkExpString(char * string)
224 {
225    return { type = stringExp, string = CopyString(string) };
226 }
227
228 Map<String, Location> intlStrings { };
229
230 Expression MkExpIntlString(char * string)
231 {
232    if(inCompiler)
233    {
234       MapIterator<String, Location> it { map = intlStrings };
235       if(!it.Index(string, false))
236       {
237          intlStrings[string] = yylloc;
238       }
239    }
240    return MkExpCall(QMkExpId("gettext"), MkListOne(MkExpString(string)));
241 }
242
243 Expression MkExpOp(Expression exp1, int op, Expression exp2)
244 {
245    Expression exp
246    {
247       type = opExp;
248       op.op = op;
249       op.exp1 = exp1;
250       op.exp2 = exp2
251    };
252    if(exp1 || exp2)
253    {
254       exp.loc.start = exp1 ? exp1.loc.start : exp2.loc.start;
255       exp.loc.end   = exp2 ? exp2.loc.end   : exp1.loc.end;
256    }
257    return exp;
258 }
259
260 Expression MkExpBrackets(OldList expressions)
261 {
262    Expression exp
263    {
264       type = bracketsExp;
265       list = expressions;
266    };
267    if(expressions && expressions.first)
268    {
269       exp.loc.start = ((Expression)expressions.first).loc.start;
270       exp.loc.end   = ((Expression)expressions.last).loc.end;
271    }
272    return exp;
273 }
274
275 Expression MkExpIndex(Expression expression, OldList index)
276 {
277    return { type = indexExp, index.exp = expression, index.index = index };
278 }
279
280 Expression MkExpCall(Expression expression, OldList arguments)
281 {
282    return { type = callExp, call.exp = expression, call.arguments = arguments };
283 }
284
285 Expression MkExpMember(Expression expression, Identifier member)
286 {
287    return { type = memberExp, member.exp = expression, member.member = member };
288 }
289
290 Expression MkExpPointer(Expression expression, Identifier member)
291 {
292    return { type = pointerExp, member.exp = expression, member.member = member };
293 }
294
295 Expression MkExpTypeSize(TypeName typeName)
296 {
297    return { type = typeSizeExp, typeName = typeName };
298 }
299
300 Expression MkExpClassSize(Specifier _class)
301 {
302    return { type = classSizeExp, _class = _class };
303 }
304
305 Expression MkExpCast(TypeName typeName, Expression expression)
306 {
307    return { type = castExp, cast.typeName = typeName, cast.exp = expression };
308 }
309
310 Expression MkExpCondition(Expression cond, OldList expressions, Expression elseExp)
311 {
312    return { type = conditionExp, cond.cond = cond, cond.exp = expressions, cond.elseExp = elseExp };
313 }
314
315 Expression MkExpRenew(Expression memExp, TypeName type, Expression size)
316 {
317    return { type = renewExp, _renew.exp = memExp, _renew.typeName = type, _renew.size = size };
318 }
319
320 Expression MkExpRenew0(Expression memExp, TypeName type, Expression size)
321 {
322    return { type = renew0Exp, _renew.exp = memExp, _renew.typeName = type, _renew.size = size };
323 }
324
325 Expression MkExpNew(TypeName type, Expression size)
326 {
327    return { type = newExp, _new.typeName = type, _new.size = size };
328 }
329
330 Expression MkExpNew0(TypeName type, Expression size)
331 {
332    return { type = new0Exp, _new.typeName = type, _new.size = size };
333 }
334
335 Expression MkExpVaArg(Expression exp, TypeName type)
336 {
337    return { type = vaArgExp, vaArg.exp = exp, vaArg.typeName = type };
338 }
339
340 Specifier MkSpecifier(int specifier)
341 {
342    return { type = baseSpecifier, specifier = specifier };
343 }
344
345 Specifier MkSpecifierTypeOf(Expression expression)
346 {
347    return { type = typeOfSpecifier, expression = expression };
348 }
349
350 Specifier MkSpecifierSubClass(Specifier _class)
351 {
352    return { type = subClassSpecifier, _class = _class };
353 }
354
355 Specifier MkSpecifierExtended(char * name)
356 {
357    return { type = extendedSpecifier, name = CopyString(name) };
358 }
359
360 Specifier MkEnum(Identifier id, OldList list)
361 {
362    Specifier spec 
363    {
364       type = enumSpecifier;
365       id = id;
366       list = list;
367    };
368    if(list && (!declMode || !id))
369    {
370       Type type;
371       Enumerator e;
372       OldList specs { };
373       specs.Add(spec);
374       type = ProcessType(&specs, null);
375
376       if(id)
377       {
378          curContext.structSymbols.Add((BTNode)Symbol { string = CopyString(id.string), isStruct = true, type = type });
379          type.refCount++;
380       }
381       for(e = list.first; e; e = e.next)
382       {
383          (curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)Symbol { string = CopyString(e.id.string), type = type });
384          type.refCount++;
385       }
386       FreeType(type);
387    }
388    return spec;
389 }
390
391 Specifier MkStructOrUnion(SpecifierType type, Identifier id, OldList definitions)
392 {
393    Specifier spec { type = type, id = id };
394    if(id && FindType(curContext, id.string))
395       declMode = defaultAccess;
396    spec.definitions = definitions;
397    if(definitions && id && !declMode)
398    {
399       OldList specs { };
400       specs.Add(spec);
401       curContext.structSymbols.Add((BTNode)Symbol { string = CopyString(id.string), type = ProcessType(specs, null), isStruct = true });
402    }
403    return spec;
404 }
405
406 void AddStructDefinitions(Specifier spec, OldList definitions)
407 {
408    spec.definitions = definitions;
409    if(definitions && spec.id && !declMode)
410    {
411       OldList specs { };
412       specs.Add(spec);
413       curContext.parent.structSymbols.Add((BTNode)Symbol { string = CopyString(spec.id.string), type = ProcessType(specs, null), isStruct = true });
414    }
415 }
416
417 public Declarator MkDeclaratorIdentifier(Identifier id)
418 {
419    return { type = identifierDeclarator, identifier = id };
420 }
421
422 Declarator MkDeclaratorFunction(Declarator declarator, OldList parameters)
423 {
424    return { type = functionDeclarator, declarator = declarator, function.parameters = parameters };
425 }
426
427 Declarator MkDeclaratorExtended(char * extended, Declarator declarator)
428 {
429    return { type = extendedDeclarator, declarator = declarator, extended.extended = extended };
430 }
431
432 Declarator MkDeclaratorExtendedEnd(char * extended, Declarator declarator)
433 {
434    return { type = extendedDeclaratorEnd, declarator = declarator, extended.extended = extended };
435 }
436
437 Declarator MkStructDeclarator(Declarator declarator, Expression exp)
438 {
439    return { type = structDeclarator, declarator = declarator, structDecl.exp = exp };
440 }
441
442 Declarator MkDeclaratorBrackets(Declarator declarator)
443 {
444    return { type = bracketsDeclarator, declarator = declarator };
445 }
446
447 Declarator MkDeclaratorArray(Declarator declarator, Expression exp)
448 {
449    return { type = arrayDeclarator, declarator = declarator, array.exp = exp };
450 }
451
452 Declarator MkDeclaratorEnumArray(Declarator declarator, Specifier _class)
453 {
454    return { type = arrayDeclarator, declarator = declarator, array.enumClass = _class };
455 }
456
457 Declarator MkDeclaratorPointer(Pointer pointer, Declarator declarator)
458 {
459    return { type = pointerDeclarator, declarator = declarator, pointer.pointer = pointer };
460 }
461
462 Enumerator MkEnumerator(Identifier id, Expression exp)
463 {
464    return { id = id, exp = exp };
465 }
466
467 Pointer MkPointer(OldList qualifiers, Pointer pointer)
468 {
469    return { qualifiers = qualifiers, pointer = pointer };
470 }
471
472 Initializer MkInitializerAssignment(Expression exp)
473 {
474    /*if(yylloc.start.line == 1)
475       printf("bug");*/
476    return { type = expInitializer, exp = exp, loc = yylloc };
477 }
478
479 Initializer MkInitializerList(OldList list)
480 {
481    /*if(yylloc.start.line == 1)
482       printf("bug");*/
483    return { type = listInitializer, list = list, loc = yylloc };
484 }
485
486 InitDeclarator MkInitDeclarator(Declarator declarator, Initializer initializer)
487 {
488    return { declarator = declarator, initializer = initializer };
489 }
490
491 public TypeName MkTypeName(OldList qualifiers, Declarator declarator)
492 {
493    return { qualifiers = qualifiers, declarator = declarator };
494 }
495
496 public Identifier GetDeclId(Declarator decl)
497 {
498    while(decl && decl.type != identifierDeclarator)
499       decl = decl.declarator;
500    return decl ? decl.identifier : null;
501 }
502
503 Declaration MkDeclarationClassInst(Instantiation inst)
504 {
505    return { type = instDeclaration, inst = inst, loc = yylloc };
506 }
507
508 Declaration MkDeclarationInst(Instantiation inst)
509 {
510    Declaration decl { type = instDeclaration, inst = inst, loc = yylloc };
511    Symbol symbol;
512    if(curContext == globalContext && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
513    {
514       char name[1024];
515       int len = 0, stringLen;
516       if(defaultNameSpace)
517       {
518          memcpy(name, defaultNameSpace, defaultNameSpaceLen);
519          len += defaultNameSpaceLen;
520          name[len++] = ':';
521          name[len++] = ':';
522       }
523       if(currentNameSpace)
524       {
525          memcpy(name + len, currentNameSpace, currentNameSpaceLen);
526          len += currentNameSpaceLen;
527          name[len++] = ':';
528          name[len++] = ':';
529       }
530
531       stringLen = strlen(inst.exp.identifier.string);
532       memcpy(name + len, inst.exp.identifier.string, stringLen);
533       len += stringLen;
534       name[len] = 0;
535       delete inst.exp.identifier.string;
536       inst.exp.identifier.string = CopyString(name);
537    }
538
539    symbol = Symbol
540    {
541       string = (inst.exp.type == identifierExp) ? CopyString(inst.exp.identifier.string) : null;
542       type = MkClassTypeSymbol(inst._class.symbol);
543    };
544    symbol.idCode = symbol.id = curContext.nextID++;
545    (curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)symbol);
546    decl.symbol = inst.symbol = symbol;
547    return decl;
548 }
549
550 Declaration MkDeclarationDefine(Identifier id, Expression exp)
551 {
552    Declaration decl { type = defineDeclaration, id = id, exp = exp, loc = yylloc };
553    char expString[1024];
554    expString[0] = '\0';
555
556    PrintExpression(exp, expString);
557
558    if(curContext == globalContext && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
559    {
560       char name[1024];
561       int len = 0, stringLen;
562       if(defaultNameSpace)
563       {
564          memcpy(name, defaultNameSpace, defaultNameSpaceLen);
565          len += defaultNameSpaceLen;
566          name[len++] = ':';
567          name[len++] = ':';
568       }
569       if(currentNameSpace)
570       {
571          memcpy(name + len, currentNameSpace, currentNameSpaceLen);
572          len += currentNameSpaceLen;
573          name[len++] = ':';
574          name[len++] = ':';
575       }
576       stringLen = strlen(id.string);
577       memcpy(name + len, id.string, stringLen);
578       len += stringLen;
579       name[len] = 0;
580       delete id.string;
581       id.string = CopyString(name);
582    }
583
584    if(!eSystem_FindDefine(privateModule, id.string))
585       eSystem_RegisterDefine(id.string, expString, privateModule, buildingECERECOMModule ? baseSystemAccess : publicAccess);
586    else
587       Compiler_Warning("Redefinition of %s ignored\n", id.string);
588    return decl;
589 }
590
591 Declaration MkDeclaration(OldList specifiers, OldList initDeclarators)
592 {
593    Declaration decl { type = initDeclaration, declarators = initDeclarators, specifiers = specifiers, loc = yylloc };
594    bool variable = true;
595    
596    if(specifiers != null)
597    {
598       Specifier spec;
599       for(spec = specifiers.first; spec; spec = spec.next)
600       {
601          if(spec.type == baseSpecifier && spec.specifier == TYPEDEF)
602          {
603             if(initDeclarators != null)
604             {
605                InitDeclarator d;
606          
607                for(d = initDeclarators.first; d; d = d.next)
608                {
609                   if(GetDeclId(d.declarator).string)
610                   {
611                      Symbol type
612                      {
613                         string = CopyString(GetDeclId(d.declarator).string);
614                         type = ProcessType(specifiers, d.declarator);
615                      };
616                      type.id = type.idCode = curContext.nextID++;
617
618                      (curContext.templateTypesOnly ? curContext.parent : curContext).types.Add((BTNode)type);
619                      decl.symbol = d.declarator.symbol = type;
620                   }
621                }
622             }
623             else if(spec.next)
624             {
625                for(; spec; spec = spec.next)
626                {
627                   if(spec.type == nameSpecifier && spec.name)
628                   {
629                      Symbol type
630                      {
631                         string = CopyString(spec.name);
632                         type = ProcessType(specifiers, null);
633                      };
634                      type.id = type.idCode = curContext.nextID++;
635                      (curContext.templateTypesOnly ? curContext.parent : curContext).types.Add((BTNode)type);
636                      decl.symbol = type;
637                   }
638                }
639             }
640             variable = false;
641             break;
642          }
643          else if(spec.type == baseSpecifier && 
644             (spec.specifier == STRUCT || spec.specifier == UNION))
645             variable = false;
646       }
647    }
648    if(variable && initDeclarators)
649    {
650       InitDeclarator d;
651       for(d = initDeclarators.first; d; d = d.next)
652       {
653          Identifier id = GetDeclId(d.declarator);
654          if(id && id.string && id.string[0])
655          {
656             if(curContext)
657             {
658                Symbol symbol;
659
660                if(curContext == globalContext && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
661                {
662                   char name[1024];
663                   int len = 0, stringLen;
664                   if(defaultNameSpace)
665                   {
666                      memcpy(name, defaultNameSpace, defaultNameSpaceLen);
667                      len += defaultNameSpaceLen;
668                      name[len++] = ':';
669                      name[len++] = ':';
670                   }
671                   if(currentNameSpace)
672                   {
673                      memcpy(name + len, currentNameSpace, currentNameSpaceLen);
674                      len += currentNameSpaceLen;
675                      name[len++] = ':';
676                      name[len++] = ':';
677                   }
678                   stringLen = strlen(id.string);
679                   memcpy(name + len, id.string, stringLen);
680                   len += stringLen;
681                   name[len] = 0;
682                   delete id.string;
683                   id.string = CopyString(name);
684                }
685                
686                symbol = Symbol { string = CopyString(id.string), type = ProcessType(specifiers, d.declarator) };
687                (curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)symbol);
688                // TODO: Add better support to count declarators
689                if(symbol.type && symbol.type.kind == arrayType && !symbol.type.arraySizeExp && d.initializer)
690                {
691                   if(d.initializer.type == listInitializer)
692                   {
693                      char string[256];
694                      sprintf(string, "%d",d.initializer.list->count);
695                      symbol.type.arraySizeExp = MkExpConstant(string);
696                      symbol.type.freeExp = true;
697                   }
698                   else if(d.initializer.type == expInitializer && d.initializer.exp.type == stringExp && d.initializer.exp.string)
699                   {
700                      char string[256];
701                      int c, count = 0;
702                      char ch;
703                      bool escaped = false;
704                      char * s = d.initializer.exp.string;
705
706                      // MAKE MORE ACCURATE
707                      for(c = 1; (ch = s[c]); c++)
708                      {
709                         if(ch == '\\' && !escaped)
710                            escaped = true;
711                         else
712                         {
713                            count++;
714                            escaped = false;
715                         }
716                      }
717
718                      sprintf(string, "%d", count);
719                      symbol.type.arraySizeExp = MkExpConstant(string);
720                      symbol.type.freeExp = true;
721                   }
722                }
723                symbol.id = symbol.idCode = curContext.nextID++;
724                decl.symbol = d.declarator.symbol = symbol;
725             }
726          }
727       }
728    }
729    else
730    {
731       decl.symbol = Symbol { };
732       decl.symbol.id = decl.symbol.idCode = curContext.nextID++;
733       excludedSymbols->Add(decl.symbol);
734    }
735    return decl;
736 }
737
738 Declaration MkStructDeclaration(OldList specifiers, OldList declarators, Specifier extStorage)
739 {
740    return { type = structDeclaration, declarators = declarators, specifiers = specifiers, extStorage = extStorage, loc = yylloc };
741 }
742
743 Statement MkLabeledStmt(Identifier id, Statement statement)
744 {
745    return { type = labeledStmt, labeled.id = id, labeled.stmt = statement, loc = yylloc };
746 }
747
748 Statement MkCaseStmt(Expression exp, Statement statement)
749 {
750    return { type = caseStmt, caseStmt.exp = exp, caseStmt.stmt = statement, loc = yylloc };
751 }
752
753 Statement MkCompoundStmt(OldList declarations, OldList statements)
754 {
755    return { type = compoundStmt, compound.declarations = declarations, compound.statements = statements, loc = yylloc };
756 }
757
758 Statement MkExpressionStmt(OldList expressions)
759 {
760    return { type = expressionStmt, expressions = expressions, loc = yylloc };
761 }
762
763 Statement MkBadDeclStmt(Declaration decl)
764 {
765    return { type = badDeclarationStmt, decl = decl, loc = yylloc };
766 }
767
768 Statement MkIfStmt(OldList exp, Statement statement, Statement elseStmt)
769 {
770    return { type = ifStmt, ifStmt.exp = exp, ifStmt.stmt = statement, ifStmt.elseStmt = elseStmt, loc = yylloc };
771 }
772
773 Statement MkSwitchStmt(OldList exp, Statement statement)
774 {
775    // To know it's a switch compound... (Don't want declarations in there... bugs)
776    if(statement)
777       statement.compound.isSwitch = true;
778    return { type = switchStmt, switchStmt.exp = exp, switchStmt.stmt = statement, loc = yylloc };
779 }
780
781 Statement MkWhileStmt(OldList exp, Statement statement)
782 {
783    return { type = whileStmt, whileStmt.exp = exp, whileStmt.stmt = statement, loc = yylloc };
784 }
785
786 Statement MkDoWhileStmt(Statement statement, OldList exp)
787 {
788    return { type = doWhileStmt, doWhile.exp = exp, doWhile.stmt = statement, loc = yylloc };
789 }
790
791 Statement MkForStmt(Statement init, Statement check, OldList inc, Statement statement)
792 {
793    return { type = forStmt, forStmt.init = init, forStmt.check = check, forStmt.increment = inc, forStmt.stmt = statement, loc = yylloc };
794 }
795
796 Statement MkForEachStmt(Identifier id, OldList exp, OldList filter, Statement statement)
797 {
798    return { type = forEachStmt, forEachStmt.id = id, forEachStmt.exp = exp, forEachStmt.filter = filter, forEachStmt.stmt = statement, loc = yylloc };
799 }
800
801 Statement MkGotoStmt(Identifier id)
802 {
803    return { type = gotoStmt, gotoStmt.id = id, loc = yylloc };
804 }
805
806 Statement MkContinueStmt()
807 {
808    return { type = continueStmt, loc = yylloc };
809 }
810
811 Statement MkBreakStmt()
812 {
813    return { type = breakStmt, loc = yylloc };
814 }
815
816 Statement MkReturnStmt(OldList exp)
817 {
818    return { type = returnStmt, expressions = exp, loc = yylloc };
819 }
820
821 FunctionDefinition MkFunction(OldList specifiers, Declarator declarator, OldList declarationList)
822 {
823    return { specifiers = specifiers, declarator = declarator, declarations = declarationList };
824 }
825
826 void ProcessFunctionBody(FunctionDefinition func, Statement body)
827 {
828    Declarator declarator = func.declarator;
829    Declarator funcDecl = GetFuncDecl(declarator);
830    Symbol symbol;
831
832    func.body = body;
833
834    if(funcDecl && funcDecl.function.parameters && body)
835    {
836       Context context = body.compound.context;
837       TypeName param;
838       for(param = funcDecl.function.parameters->first; param; param = param.next)
839       {
840          if(param.declarator)
841          {
842             Symbol symbol = null;
843             Identifier id = GetDeclId(param.declarator);
844             char * string = id ? id.string : null;
845             if(string)
846             {
847                for(symbol = (Symbol)context.symbols.first; symbol; symbol = (Symbol)((BTNode)symbol).next)
848                   if(!strcmp(symbol.string, string))
849                      break;
850                // This parameter is not shadowed by a local declaration
851                if(!symbol && id)
852                {
853                   symbol = Symbol { string = CopyString(id.string), type = ProcessType(param.qualifiers, param.declarator), isParam = true };
854                   context.symbols.Add((BTNode)symbol);
855
856                   // TODO: Fix this, the parameters' IDs should really be smaller...
857                   symbol.id = context.nextID++;
858                   param.declarator.symbol = symbol;
859                }
860             }
861          }
862       }
863    }
864
865    if(!declarator.symbol)
866    {
867       Identifier id = GetDeclId(declarator);
868
869       if((currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess && strcmp(id.string, "__on_register_module"))
870       {
871          char name[1024];
872          int len = 0, stringLen;
873          if(defaultNameSpace)
874          {
875             memcpy(name, defaultNameSpace, defaultNameSpaceLen);
876             len += defaultNameSpaceLen;
877             name[len++] = ':';
878             name[len++] = ':';
879          }
880          if(currentNameSpace)
881          {
882             memcpy(name + len, currentNameSpace, currentNameSpaceLen);
883             len += currentNameSpaceLen;
884             name[len++] = ':';
885             name[len++] = ':';
886          }
887          stringLen = strlen(id.string);
888          memcpy(name + len, id.string, stringLen);
889          len += stringLen;
890          name[len] = 0;
891          delete id.string;
892          id.string = CopyString(name);
893       }
894       symbol = Symbol { string = CopyString(id.string), type = ProcessType(func.specifiers, declarator) };
895       symbol.idCode = symbol.id = globalContext.nextID++;
896       globalContext.symbols.Add((BTNode)symbol);
897       declarator.symbol = symbol;
898    }
899    else
900    {
901       symbol = declarator.symbol;
902       excludedSymbols->Remove(declarator.symbol);
903       delete symbol.string;
904       symbol.string = CopyString(GetDeclId(declarator).string);
905       globalContext.symbols.Add((BTNode)symbol);
906
907       if(!symbol.type)
908          symbol.type = ProcessType(func.specifiers, declarator);
909    }
910    if(symbol.type && (symbol.type.kind == functionType || symbol.type.kind == methodType))
911    {
912       if(!symbol.type.params.count)
913       {
914          Type type { refCount = 1 };
915          symbol.type.params.Add(type);
916       }
917    }
918    else
919    {
920       //printf("");
921    }
922 }
923
924 External MkExternalFunction(FunctionDefinition function)
925 {
926    External external { type = functionExternal, function = function, symbol = function.declarator.symbol };
927    if(function.specifiers)
928    {
929       Specifier spec;
930       for(spec = function.specifiers->first; spec; spec = spec.next)
931          if(spec.type == baseSpecifier && spec.specifier == STATIC)
932          {
933             declMode = staticAccess;
934             break;
935          }
936    }
937
938    if(external.symbol && !external.symbol.methodExternal)
939       external.symbol.methodExternal = external;
940    return external;
941 }
942
943 External MkExternalImport(char * name, ImportType importType, AccessMode importAccess)
944 {
945    External external { type = importExternal };
946    int len = strlen(name) - 2;
947    external.importString = new char[len + 1];
948    strncpy(external.importString, name+1, len);
949    external.importString[len] = '\0';
950    delete name;
951
952    {
953 #ifdef _TIMINGS
954       Time startTime = GetTime();
955       Time time;
956 #endif
957       ImportModule(external.importString, importType, importAccess, true);
958       ImportModule(external.importString, importType, importAccess, false);
959 #ifdef _TIMINGS
960       time = GetTime() - startTime;
961       printf("Importing took %.3f seconds for %s\n", time, external.importString);
962       externalImportTotalTime += time;
963 #endif
964    }
965    return external;
966 }
967
968 External MkExternalDeclaration(Declaration declaration)
969 {
970    External external { type = declarationExternal, declaration = declaration, symbol = declaration ? declaration.symbol : null };
971    InitDeclarator d = (declaration && declaration.declarators) ? declaration.declarators->last : null;
972    if(declaration && declaration.type == initDeclaration && declaration.specifiers)
973    {
974       Specifier spec;
975       for(spec = declaration.specifiers->first; spec; spec = spec.next)
976          if(spec.type == baseSpecifier && spec.specifier == TYPEDEF)
977          {
978             declMode = defaultAccess;
979             break;
980          }
981          else if(spec.type == baseSpecifier && spec.specifier == STATIC)
982          {
983             declMode = staticAccess;
984             break;
985          }
986    }
987    if(declaration && declaration.symbol && !declaration.symbol.methodExternal)
988       declaration.symbol.methodExternal = external;
989    return external;
990 }
991
992 External MkExternalNameSpace(Identifier identifier)
993 {
994    External external { type = nameSpaceExternal, id = identifier };
995    currentNameSpace = identifier ? identifier.string : null;
996    currentNameSpaceLen = currentNameSpace ? strlen(currentNameSpace) : 0;
997    return external;
998 }
999
1000 void SetClassTemplateArgs(Specifier spec, OldList templateArgs)
1001 {
1002    if(spec.type == nameSpecifier)
1003    {
1004       Symbol symbol = spec.symbol;
1005       spec.templateArgs = templateArgs;
1006       if(templateArgs && templateArgs.first)
1007       {
1008          char templateString[1024];
1009          TemplateArgument arg;
1010          strcpy(templateString, symbol ? symbol.string : spec.name);
1011          strcat(templateString, "<");
1012          for(arg = templateArgs.first; arg; arg = arg.next)
1013          {
1014             char argument[256];
1015             argument[0] = '\0';
1016             switch(arg.type)
1017             {
1018                case expression:
1019                {
1020                   char expString[1024];
1021                   Class backupThisClass = thisClass;
1022                   thisClass = null;
1023                   expString[0] = '\0';
1024                   // Will this work here?
1025                   /*
1026                   Location oldLocation = yylloc;
1027                   File backFileInput = fileInput;
1028                   declMode = 0;
1029                   resetScanner();
1030                   */
1031
1032                   // TESTING THIS SCANNER RESUME STUFF
1033                   /*
1034                   resetScanner();
1035                   yylloc = oldLocation;
1036                   fileInput = backFileInput;
1037                   if(fileInput)
1038                   {
1039                      fileInput.Seek(yylloc.start.pos, start); 
1040                      resetScannerPos(&yylloc.start);
1041                      yychar = -2;
1042                   }
1043                   */
1044
1045                   //ProcessExpressionType(arg.expression);
1046                   //ComputeExpression(arg.expression);
1047                   PrintExpression(arg.expression, expString);
1048                   strcat(argument, expString);
1049                   thisClass = backupThisClass;
1050                   break;
1051                }
1052                case identifier:
1053                {
1054                   strcat(argument, arg.identifier.string);
1055                   break;
1056                }
1057                case type:
1058                {
1059                   char * typeString = StringFromSpecDecl(arg.templateDatatype.specifiers, arg.templateDatatype.decl);
1060                   strcat(argument, typeString);
1061                   delete typeString;
1062                   break;
1063                }
1064             }
1065             if(argument[0])
1066             {
1067                if(arg.prev) strcat(templateString, ", ");
1068                if(arg.name)
1069                {
1070                   strcat(templateString, arg.name.string);
1071                   strcat(templateString, " = ");
1072                }
1073                strcat(templateString, argument);
1074             }
1075          }
1076          {
1077             int len = strlen(templateString);
1078             if(templateString[len-1] == '>') templateString[len++] = ' ';
1079             templateString[len++] = '>';
1080             templateString[len++] = '\0';
1081          }
1082          // printf("SetClassTemplateArgs templateString: %s\n", templateString);
1083          symbol = FindClass(templateString);
1084          if(!symbol && spec.symbol)
1085          {
1086             // If class was only decl'ed, invoke DeclClass on this templated class as well
1087             symbol = _DeclClass(MAXINT, templateString);
1088          }
1089          // Add a reference to all templated class to the basic class
1090          if(spec.symbol)
1091             spec.symbol.templatedClasses.Add(OldLink { data = symbol });
1092          delete spec.name;
1093          spec.symbol = symbol;
1094          spec.name = CopyString(symbol ? symbol.string : templateString);
1095       }
1096    }
1097    else
1098       FreeList(templateArgs, FreeTemplateArgument);
1099 }
1100
1101 Specifier _MkSpecifierName(char * name, Symbol symbol, OldList templateArgs)
1102 {
1103    Specifier spec { type = nameSpecifier };
1104
1105    if(name)
1106    {
1107       if(!symbol)
1108       {
1109          TemplatedType templatedType = FindTemplateTypeParameter(curContext, name);
1110          if(templatedType)
1111          {
1112             spec.templateParameter = templatedType.param;
1113             spec.type = templateTypeSpecifier;
1114             return spec;
1115          }
1116          else
1117             symbol = FindClass(name);
1118       }
1119       if(symbol && symbol.registered && symbol.registered.isRemote == 1)
1120       {
1121          char className[1024];
1122          strcpy(className, "DCOMClient_");
1123          if(!strncmp(name, className, strlen(className)))
1124             spec.name = CopyString(name);
1125          else
1126          {
1127             strcat(className, name);
1128             spec.name = CopyString(className);
1129          }
1130       }
1131       else if(symbol)
1132          spec.name = CopyString(symbol.string);   
1133       else
1134          spec.name = CopyString(name);
1135       spec.symbol = symbol;
1136       if(templateArgs != null)
1137          SetClassTemplateArgs(spec, templateArgs);
1138    }
1139    return spec;
1140 }
1141
1142 public Specifier MkSpecifierName(char * name)
1143 {
1144    return _MkSpecifierName(name, null, null);
1145 }
1146
1147 public Specifier MkSpecifierNameArgs(char * name, OldList * templateArgs)
1148 {
1149    return _MkSpecifierName(name, null, templateArgs);
1150 }
1151
1152 /*
1153 Specifier MkClassName(char * string)
1154 {
1155    return { type = SpecifierClass, name = CopyString(string) };
1156 }
1157 */
1158 ClassFunction MkClassFunction(OldList specifiers, Specifier _class, Declarator decl, OldList declList)
1159 {
1160    return { specifiers = specifiers, /*_class = _class,*/ declarator = decl, declarations = declList };
1161 }
1162
1163 void ProcessClassFunctionBody(ClassFunction func, Statement body)
1164 {
1165    Symbol symbol;
1166
1167    Declarator decl = func.declarator;
1168    //TESTING THIS
1169    //Declarator decl = GetFuncDecl(func.declarator);
1170    Declarator funcDecl = GetFuncDecl(func.declarator);
1171
1172    func.body = body;
1173
1174    if(decl && !decl.symbol)
1175    {
1176       OldList * symbolSpecs = MkList();
1177
1178       // WHAT WILL WE DO WITH THIS? Double instances?
1179       //if(decl.function.parameters && body)
1180       if(funcDecl && funcDecl.function.parameters && body)
1181       {
1182          Context context = body.compound.context;
1183          TypeName param;
1184          for(param = funcDecl.function.parameters->first; param; param = param.next)
1185          {
1186             if(param.declarator)
1187             {
1188                Symbol symbol = null;
1189                Identifier id = GetDeclId(param.declarator);
1190                char * string = id ? id.string : null;
1191                if(string)
1192                {
1193                   symbol = (Symbol)context.symbols.FindString(string);
1194                }
1195                // This parameter is not shadowed by a local declaration
1196                if(!symbol && id)
1197                {
1198                   symbol = Symbol
1199                   {
1200                      string = CopyString(id.string);
1201                      type = ProcessType(param.qualifiers, param.declarator);
1202                      isParam = true;
1203                   };
1204
1205                   // TODO: Fix this, the parameters' IDs should really be smaller...
1206                   symbol.idCode = symbol.id = context.nextID++;
1207                   context.symbols.Add((BTNode)symbol);
1208
1209                   param.declarator.symbol = symbol;
1210                }
1211             }
1212          }
1213       }
1214       //////////////////////////////////
1215
1216       symbol = Symbol
1217       {
1218          
1219       };
1220
1221       {
1222          Identifier id = GetDeclId(funcDecl);
1223          if(id)
1224          {
1225             int c;
1226             for(c = strlen(id.string)-1; c >= 0; c--)
1227             {
1228                if(id.string[c] == ':')
1229                {
1230                   char * string = CopyString(id.string + c + 1);
1231                   id.string[c - 1] = 0;
1232                   id._class = MkSpecifierName(id.string);
1233                   delete id.string;
1234                   id.string = string;
1235                   break;
1236                }
1237             }
1238             symbol.string = CopyString(id.string);
1239          }
1240       }
1241
1242       if(func.specifiers)
1243       {
1244          Specifier spec;
1245          for(spec = func.specifiers->first; spec; spec = spec.next)
1246             symbolSpecs->Add(CopySpecifier(spec));
1247       }
1248       symbol.type = ProcessType(symbolSpecs, decl);
1249       symbol.idCode = symbol.id = globalContext.nextID++;
1250       decl.symbol = symbol;
1251
1252       excludedSymbols->Add(symbol);
1253
1254       FreeList(symbolSpecs, FreeSpecifier);
1255    }
1256 }
1257
1258 OldList * MkSpecsClass(Specifier _class)
1259 {
1260    OldList * list = MkList();
1261    ListAdd(list, _class);
1262    return list;
1263 }
1264
1265 MemberInit MkMemberInit(OldList ids, Initializer initializer)
1266 {
1267    return { identifiers = ids, initializer = initializer };
1268 }
1269
1270 MemberInit MkMemberInitExp(Expression idExp, Initializer initializer)
1271 {
1272    MemberInit init { initializer = initializer, identifiers = MkList() };
1273    Expression exp;
1274
1275    for(exp = idExp; exp && exp.type == memberExp; exp = exp.member.exp)
1276    {
1277       init.identifiers->Insert(null, exp.member.member);
1278       exp.member.member = null;
1279    }
1280    if(exp && exp.type == identifierExp)
1281    {
1282       init.identifiers->Insert(null, exp.identifier);
1283       exp.identifier = null;
1284    }
1285    FreeExpression(idExp);
1286    return init;
1287 }
1288
1289 MembersInit MkMembersInitList(OldList dataMembers)
1290 {
1291    return { type = dataMembersInit, dataMembers = dataMembers };
1292 }
1293
1294 MembersInit MkMembersInitMethod(ClassFunction function)
1295 {
1296    return { type = methodMembersInit, function = function };
1297 }
1298
1299 Instantiation MkInstantiation(Specifier _class, Expression exp, OldList members)
1300 {
1301    return { _class = _class, exp = exp, members = members };
1302 }
1303
1304 Instantiation MkInstantiationNamed(OldList specs, Expression exp, OldList members)
1305 {
1306    Instantiation inst { exp = exp, members = members };
1307
1308    if(specs != null)
1309    {
1310       Specifier spec;
1311       for(spec = specs.first; spec; spec = spec.next)
1312          if(spec.type == nameSpecifier /*classSpecifier*/)
1313          {
1314             inst._class = spec;
1315             specs.Remove(spec);
1316             break;
1317          }
1318
1319       FreeList(specs, FreeSpecifier);
1320          
1321       if(!spec)
1322       {
1323          Compiler_Error("Expecting class specifier\n");
1324          inst._class = MkSpecifierName /*MkClassName*/("");
1325          //exit(1);
1326          //return null;
1327       }
1328    }
1329    return inst;
1330 }
1331
1332 ClassDef MkClassDefAccessOverride(AccessMode access, Identifier id)
1333 {
1334    return { type = accessOverrideClassDef, id = id, memberAccess = access };
1335 }
1336
1337 ClassDef MkClassDefMemberAccess()
1338 {
1339    return { type = memberAccessClassDef };
1340 }
1341
1342 ClassDef MkClassDefDeclaration(Declaration decl)
1343 {
1344    return { type = declarationClassDef, decl = decl };
1345 }
1346
1347 ClassDef MkClassDefClassData(Declaration decl)
1348 {
1349    return { type = classDataClassDef, decl = decl };
1350 }
1351
1352 ClassDef MkClassDefDesigner(char * designer)
1353 {
1354    return { type = classDesignerClassDef, designer = CopyString(designer) };
1355 }
1356
1357 ClassDef MkClassDefNoExpansion()
1358 {
1359    return { type = classNoExpansionClassDef };
1360 }
1361
1362 ClassDef MkClassDefFixed()
1363 {
1364    return { type = classFixedClassDef };
1365 }
1366
1367 ClassDef MkClassDefDesignerDefaultProperty(Identifier id)
1368 {
1369    return { type = designerDefaultPropertyClassDef, defaultProperty = id };
1370 }
1371
1372 ClassDef MkClassDefDefaultProperty(OldList defProperties)
1373 {
1374    return { type = defaultPropertiesClassDef, defProperties = defProperties };
1375 }
1376
1377 ClassDef MkClassDefFunction(ClassFunction function)
1378 {
1379    ClassDef def { };
1380    if(function && function.declarator)
1381    {
1382       Declarator funcDecl = GetFuncDecl(function.declarator);
1383       if(funcDecl && funcDecl.declarator && funcDecl.declarator.type == bracketsDeclarator)
1384       {
1385          def.type = declarationClassDef;
1386          def.decl = MkStructDeclaration(function.specifiers, MkListOne(MkStructDeclarator(function.declarator, null)), null);
1387          function.declarator = null;
1388          function.specifiers = null;
1389          FreeClassFunction(function);
1390          return def;
1391       }
1392    }
1393    def.type = functionClassDef;
1394    def.function = function;
1395    return def;
1396 }
1397
1398 Symbol DeclClassAddNameSpace(int symbolID, char * className)
1399 {
1400    char name[1024];
1401    int len = 0, stringLen;
1402    name[0] = '\0';
1403    if((currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
1404    {
1405       if(defaultNameSpace)
1406       {
1407          memcpy(name, defaultNameSpace, defaultNameSpaceLen);
1408          len += defaultNameSpaceLen;
1409          name[len++] = ':';
1410          name[len++] = ':';
1411       }
1412       if(currentNameSpace)
1413       {
1414          memcpy(name + len, currentNameSpace, currentNameSpaceLen);
1415          len += currentNameSpaceLen;
1416          name[len++] = ':';
1417          name[len++] = ':';
1418       }
1419    }
1420    stringLen = strlen(className);
1421    memcpy(name + len, className, stringLen);
1422    len += stringLen;
1423    name[len] = 0;
1424    return _DeclClass(symbolID, name);
1425 }
1426
1427 Symbol DeclClass(int symbolID, char * name)
1428 {
1429    if(strchr(name, ':'))
1430       return _DeclClass(symbolID, name);
1431    else
1432       return DeclClassAddNameSpace(symbolID, name);
1433 }
1434
1435 Symbol _DeclClass(int symbolID, char * name)
1436 {
1437    Symbol symbol = FindClass(name);
1438    if(!symbol)
1439    {
1440       /*
1441       Context classContext;
1442       for(classContext = curContext; classContext && !classContext.classDef; classContext = classContext.parent);
1443       if(classContext)
1444       {
1445          
1446       }
1447       */
1448       if(name[0] == ':' && name[1] == ':')
1449          name += 2;
1450       symbol = Symbol
1451       {
1452          string = CopyString(name);
1453          idCode = symbolID, id = symbolID;
1454       };
1455       globalContext.classes.Add((BTNode)symbol);
1456
1457       {
1458          int start = 0, c;
1459          char ch;
1460          for(c = 0; (ch = name[c]); c++)
1461          {
1462             if(ch == '.' || (ch == ':' && name[c+1] == ':'))
1463             {
1464                if(ch == ':') c++;
1465                start = c+1;
1466             }
1467          }
1468          if(start && c - start)
1469             symbol.shortName = CopyString(name + start);
1470       }
1471    }
1472    if(symbolID)
1473       symbol.idCode = symbol.id = symbolID;
1474    return symbol;
1475 }
1476
1477 void SetupBaseSpecs(Symbol symbol, OldList baseSpecs)
1478 {
1479    if(baseSpecs && baseSpecs.first && ((Specifier)baseSpecs.first).type == nameSpecifier)
1480    {
1481       char name[1024];
1482       Symbol baseClass;
1483       char * tpl;
1484       strcpy(name, ((Specifier)baseSpecs.first).name);
1485       tpl = strchr(name, '<');
1486       if(tpl) *tpl = 0;
1487       
1488       baseClass = FindClass(name);
1489       if(baseClass.ctx)
1490       {
1491          TemplatedType copy;
1492          for(copy = (TemplatedType)baseClass.ctx.templateTypes.first; copy; copy = (TemplatedType)copy.next)
1493          {
1494             TemplatedType type { key = copy.key, param = copy.param };
1495             curContext.templateTypes.Add((BTNode)type);
1496          }
1497       }
1498       else if(baseClass.registered)
1499       {
1500          Class sClass;
1501          for(sClass = baseClass.registered; sClass; sClass = sClass.base)
1502          {
1503             ClassTemplateParameter p;
1504             for(p = sClass.templateParams.first; p; p = p.next)
1505             {
1506                //OldList * specs = MkList();
1507                //Declarator decl = null;
1508                //decl = SpecDeclFromString(p.dataTypeString, specs, null);
1509                if(p.type == type)
1510                {
1511                   TemplateParameter param = p.param;
1512                   TemplatedType type;
1513                   if(!param)
1514                   {
1515                      p.param = param = TemplateParameter
1516                      {
1517                         identifier = MkIdentifier(p.name), type = p.type, 
1518                         dataTypeString = p.dataTypeString /*, dataType = { specs, decl }*/
1519                      };
1520                   }
1521                   type = TemplatedType { key = (uint)p.name, param = param };
1522                   curContext.templateTypes.Add((BTNode)type);
1523                }
1524             }
1525          }
1526       }
1527    }
1528 }
1529
1530 ClassDefinition MkClass(Symbol symbol, OldList baseSpecs, OldList definitions)
1531 {
1532    ClassDefinition classDef;
1533    SetupBaseSpecs(symbol, baseSpecs);
1534    symbol.ctx = curContext;
1535    classDef = { symbol = symbol, _class = MkSpecifierName /*MkClassName*/(symbol.string), baseSpecs = baseSpecs, definitions = definitions, nameLoc = symbol.nameLoc };
1536    curContext.classDef = classDef;
1537    return classDef;
1538 }
1539
1540 Expression MkExpInstance(Instantiation inst)
1541 {
1542    return { type = instanceExp, instance = inst };
1543 }
1544
1545 External MkExternalClass(ClassDefinition _class)
1546 {
1547    return { type = classExternal, _class = _class, symbol = _class.symbol };
1548 }
1549
1550 PropertyDef MkProperty(OldList specs, Declarator decl, Identifier id, Statement setStmt, Statement getStmt)
1551 {
1552    PropertyDef prop
1553    {
1554       specifiers = specs;
1555       declarator = decl;
1556       setStmt = setStmt;
1557       getStmt = getStmt;
1558    };
1559    Symbol symbol;
1560    Type type = ProcessType(specs, decl);
1561    if(!id)
1562    {
1563       char typeString[1024];
1564       typeString[0] = '\0';
1565       PrintType(type, typeString, false, true);
1566       id = MkIdentifier(typeString);
1567       prop.conversion = true;
1568    }
1569    prop.id = id;
1570
1571    symbol = Symbol
1572    {
1573       string = CopyString(id.string);
1574       type = type;
1575    };
1576    symbol.idCode = symbol.id = globalContext.nextID++;
1577    excludedSymbols->Add(symbol);
1578    globalContext.nextID++;
1579    globalContext.nextID++;
1580    prop.symbol = symbol;
1581    return prop;
1582 }
1583
1584 ClassDef MkClassDefProperty(PropertyDef propertyDef)
1585 {
1586    return { type = propertyClassDef, propertyDef = propertyDef };
1587 }
1588
1589 ClassDef MkClassDefClassProperty(PropertyDef propertyDef)
1590 {
1591    return { type = classPropertyClassDef, propertyDef = propertyDef };
1592 }
1593
1594 ClassDef MkClassDefClassPropertyValue(Identifier id, Initializer initializer)
1595 {
1596    return { type = classPropertyValueClassDef, id = id, initializer = initializer };
1597 }
1598
1599 int CheckType(char * text)
1600 {
1601 #ifdef _TIMINGS
1602    Time startTime = GetTime();
1603 #endif
1604    if(FindTemplateTypeParameter(curContext, text))
1605    {
1606 #ifdef _TIMINGS
1607       checkTypeTotalTime += GetTime() - startTime;
1608 #endif
1609       return TYPE_NAME;
1610    }
1611    if(FindType(curContext, text))
1612    {
1613 #ifdef _TIMINGS
1614       checkTypeTotalTime += GetTime() - startTime;
1615 #endif
1616       return TYPE_NAME;
1617    }
1618    if(FindClass(text))
1619    {
1620 #ifdef _TIMINGS
1621       checkTypeTotalTime += GetTime() - startTime;
1622 #endif
1623       return TYPE_NAME; //CLASS_NAME;
1624    }
1625 #ifdef _TIMINGS
1626    checkTypeTotalTime += GetTime() - startTime;
1627 #endif
1628    return IDENTIFIER;
1629 }
1630
1631 int check_type()
1632 {
1633    return CheckType(yytext);
1634 }
1635
1636 Context PushContext()
1637 {
1638    Context ctx { parent = curContext };
1639    curContext = ctx;
1640    return ctx;
1641 }
1642
1643 void PopContext(Context ctx)
1644 {
1645    curContext = ctx.parent;
1646 }
1647
1648 Symbol FindType(Context ctx, char * name)
1649 {
1650    Symbol type = null;
1651    if(curContext)
1652    {
1653       type = (Symbol)ctx.types.FindString(name);
1654       if(!type && ctx.parent)
1655          type = FindType(ctx.parent, name);
1656    }
1657    return type;
1658 }
1659
1660 TemplatedType FindTemplateTypeParameter(Context ctx, char * name)
1661 {
1662    TemplatedType templatedType = null;
1663    if(curContext)
1664    {
1665       templatedType = (TemplatedType)ctx.templateTypes.FindString(name);
1666       if(!templatedType && ctx.parent)
1667          templatedType = FindTemplateTypeParameter(ctx.parent, name);
1668    }
1669    return templatedType;
1670 }
1671
1672 bool ModuleAccess(Module searchIn, Module searchFor)
1673 {
1674    SubModule subModule;
1675    
1676    if(searchFor == searchIn)
1677       return true;
1678
1679    for(subModule = searchIn.modules.first; subModule; subModule = subModule.next)
1680    {
1681       if(subModule.importMode == publicAccess /*|| searchIn == searchIn.application*/)
1682       {
1683          if(ModuleAccess(subModule.module, searchFor))
1684             return true;
1685       }
1686    }
1687    return false;
1688 }
1689
1690 ModuleImport FindModule(Module moduleToFind)
1691 {
1692    ModuleImport module;
1693    if(!moduleToFind.name)
1694       return mainModule;
1695    for(module = imports->first; module; module = module.next)
1696       if(module.name && !strcmp(module.name, moduleToFind.name))
1697          break;
1698    if(!module)
1699    {
1700       module = ModuleImport 
1701       { 
1702          name = CopyString(moduleToFind.name), importType = moduleToFind.importType,
1703          importAccess = ModuleAccess(privateModule, moduleToFind) ? publicAccess : privateAccess
1704       };
1705       imports->Add(module);
1706    }
1707    return module;
1708 }
1709
1710 /*
1711 // TO REMOVE: OBSOLETE...
1712 static void GetFullClassNameSpace(NameSpace * ns, char * name)
1713 {
1714    if(ns->parent)
1715    {
1716       GetFullClassNameSpace(ns->parent, name);
1717       strcat(name, ns->name);
1718       strcat(name, "::");      
1719    }
1720 }
1721
1722 static char * GetFullClassName(Class c, char * name)
1723 {
1724    NameSpace * nameSpace;
1725    name[0] = 0;
1726    GetFullClassNameSpace(c.nameSpace, name);
1727    strcat(name, c.name);
1728    return name;
1729 }
1730 */
1731
1732 public Symbol FindClass(char * name)
1733 {
1734 #ifdef _DEBUG
1735    Time startTime = GetTime();
1736 #endif
1737    Symbol cl = null;
1738    Class _class;
1739    bool global = false;
1740    char fullName[1024];
1741
1742    if(name[0] == ':' && name[1] == ':')
1743    {
1744       global = true;
1745       name += 2;
1746    }
1747
1748    if(!global && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
1749    {
1750       int len = 0, stringLen;
1751       if(defaultNameSpace)
1752       {
1753          memcpy(fullName, defaultNameSpace, defaultNameSpaceLen);
1754          len += defaultNameSpaceLen;
1755          fullName[len++] = ':';
1756          fullName[len++] = ':';
1757       }
1758       if(currentNameSpace)
1759       {
1760          memcpy(fullName + len, currentNameSpace, currentNameSpaceLen);
1761          len += currentNameSpaceLen;
1762          fullName[len++] = ':';
1763          fullName[len++] = ':';
1764       }
1765       stringLen = strlen(name);
1766       memcpy(fullName + len, name, stringLen);
1767       len += stringLen;
1768       fullName[len] = 0;
1769       cl = globalContext ? (Symbol)globalContext.classes.FindString(fullName) : null;
1770    }
1771
1772    if(!cl)
1773       cl = globalContext ? (Symbol)globalContext.classes.FindString(name) : null;
1774
1775    if(!cl && !global)
1776    {
1777 #ifdef _TIMINGS
1778       Time startTime = GetTime();
1779 #endif
1780       // Ignore name space name when searching
1781       for(cl = globalContext ? (Symbol)globalContext.classes.first : null; cl; cl = (Symbol)((BTNode)cl).next)
1782       {
1783          /*
1784          int start = 0, c;
1785          char * string = cl.string;
1786          char ch;
1787          for(c = 0; (ch = string[c]); c++)
1788          {
1789             if(ch == '.' || (ch == ':' && string[c+1] == ':'))
1790             {
1791                if(ch == ':') c++;
1792                start = c+1;
1793             }
1794          }
1795          if(start && c - start)
1796          {
1797             if(!strcmp(string + start, name))
1798                break;
1799          }
1800          */
1801          if(cl.shortName && !strcmp(cl.shortName, name))
1802             break;            
1803       }
1804 #ifdef _TIMINGS
1805       findClassIgnoreNSTotalTime += GetTime() - startTime;
1806 #endif
1807    }
1808    if(!cl)
1809    {
1810       _class = null;
1811       if(!global && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
1812          _class = eSystem_FindClass(privateModule, fullName);
1813       if(!_class)
1814          _class = eSystem_FindClass(privateModule, name);
1815
1816       if(_class)
1817       {
1818          name = _class.fullName;
1819
1820          cl = (Symbol)globalContext.classes.FindString(name);
1821          if(!cl)
1822          {
1823             cl = Symbol
1824             {
1825                string = CopyString(name);
1826                registered = _class;
1827                id = MAXINT;
1828                idCode = MAXINT;
1829                imported = true;
1830             };
1831             _class.symbol = cl;
1832             if(_class.module)
1833                cl.module = FindModule(_class.module);
1834             else
1835                cl.module = mainModule;
1836             globalContext.classes.Add((BTNode)cl);
1837             if(strcmp(name, _class.name))
1838                cl.shortName = CopyString(_class.name);
1839          }
1840       }
1841    }
1842 #ifdef _TIMINGS
1843    findClassTotalTime += GetTime() - startTime;
1844 #endif
1845    return cl;
1846 }
1847
1848 void CopyTypeInto(Type type, Type src)
1849 {
1850    type = *src;
1851    type.name = CopyString(src.name);
1852    type.enumName = CopyString(src.enumName);
1853    type.refCount = 1;
1854
1855    if(src.kind == enumType)
1856    {
1857       NamedLink member;
1858
1859       type.members.Clear();
1860       for(member = type.members.first; member; member = member.next)
1861       {
1862          type.members.Add(NamedLink { name = CopyString(member.name), data = member.data });
1863       }
1864    }
1865    else if(src.kind == structType || src.kind == unionType)
1866    {
1867       Type member;
1868       // Tricky stuff... will be removed from list only when ref count reaches 0
1869       for(member = type.members.first; member; member = member.next)
1870          member.refCount++;
1871    }
1872    else if(src.kind == functionType)
1873    {
1874       Type param;
1875       type.returnType.refCount++;
1876       for(param = type.params.first; param; param = param.next)
1877          param.refCount++;
1878    }
1879    else if(src.kind == pointerType || src.kind == arrayType)
1880    {
1881       type.type.refCount++;
1882       if(src.kind == arrayType)
1883       {
1884          if(type.arraySizeExp)
1885             type.arraySizeExp = CopyExpression(type.arraySizeExp);
1886       }
1887
1888    }
1889 }
1890
1891 public Type ProcessType(OldList specs, Declarator decl)
1892 {
1893    Type type = null;
1894    bool isTypedef = false;
1895    if(!specs || specs.first)
1896    {
1897       Declarator funcDecl = GetFuncDecl(decl);
1898       Type specType { };
1899       bool dllExport = false;
1900
1901       specType.kind = intType;
1902       specType.isSigned = true;   
1903       specType.refCount = 1;
1904
1905       type = Type { refCount = 1 };
1906
1907       while(decl && (decl.type == structDeclarator || decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd))
1908       {
1909          if(decl.type == structDeclarator && decl.structDecl.exp)
1910          {
1911             ProcessExpressionType(decl.structDecl.exp);
1912             ComputeExpression(decl.structDecl.exp);
1913             if(decl.structDecl.exp.type == constantExp)
1914                specType.bitFieldCount = strtoul(decl.structDecl.exp.constant, null, 0);
1915          }
1916          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended && 
1917             (!strcmp(decl.extended.extended, "__declspec(dllexport)") || !strcmp(decl.extended.extended, "dllexport")))
1918          {
1919             dllExport = true;
1920          }
1921          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended && 
1922             (strstr(decl.extended.extended, "__attribute__")))
1923          {
1924             specType.keepCast = true;
1925          }
1926          decl = decl.declarator;
1927       }
1928
1929       // If we'll be using the specType
1930       if(funcDecl || !decl || decl.type == identifierDeclarator)
1931       {
1932          Specifier spec;
1933          if(specs != null)
1934          {
1935             bool isLong = false;
1936             for(spec = specs.first; spec; spec = spec.next)
1937             {
1938                if(spec.type == extendedSpecifier && (!strcmp(spec.name, "__declspec(dllexport)") || !strcmp(spec.name, "dllexport")))
1939                {
1940                   dllExport = true;
1941                }
1942                if(spec.type == extendedSpecifier && strstr(spec.name, "__attribute__"))
1943                {
1944                   specType.keepCast = true;
1945                }
1946
1947                if(specType.kind == structType || specType.kind == unionType)
1948                {
1949                   FreeType(specType);
1950                   specType = { kind = intType, isSigned = true, refCount = 1 };
1951                }
1952
1953                if(spec.type == baseSpecifier)
1954                {
1955                   if(spec.specifier == TYPEDEF) isTypedef = true;
1956                   else if(spec.specifier == VOID) specType.kind = voidType;
1957                   else if(spec.specifier == CHAR) specType.kind = charType;
1958                   else if(spec.specifier == INT) { if(specType.kind != shortType && specType.kind != longType) specType.kind = intType; }
1959                   else if(spec.specifier == UINT) { if(specType.kind != shortType && specType.kind != longType) specType.kind = intType; specType.isSigned = false; }
1960                   else if(spec.specifier == INT64) specType.kind = int64Type;
1961                   else if(spec.specifier == VALIST) 
1962                      specType.kind = vaListType;
1963                   else if(spec.specifier == SHORT) specType.kind = shortType;
1964                   else if(spec.specifier == LONG) 
1965                   {
1966                      if(isLong)
1967                         specType.kind = int64Type;
1968                      else
1969                         specType.kind = intType;
1970                      isLong = true;
1971                      // specType.kind = longType;
1972                   }
1973                   else if(spec.specifier == FLOAT) specType.kind = floatType;
1974                   else if(spec.specifier == DOUBLE) specType.kind = doubleType;
1975                   else if(spec.specifier == SIGNED) specType.isSigned = true;
1976                   else if(spec.specifier == UNSIGNED) specType.isSigned = false;
1977                   else if(spec.specifier == CONST) specType.constant = true;
1978                   else if(spec.specifier == TYPED_OBJECT) 
1979                   { 
1980                      specType.classObjectType = typedObject; specType.kind = classType; specType._class = FindClass("class"); 
1981                   }
1982                   else if(spec.specifier == ANY_OBJECT) 
1983                   { 
1984                      specType.classObjectType = anyObject; specType.kind = classType; specType._class = FindClass("class"); 
1985                   }
1986                   else if(spec.specifier == CLASS)
1987                   {
1988                      specType.classObjectType = classPointer; specType.kind = classType; specType._class = FindClass("class");
1989                   }
1990                   else if(spec.specifier == THISCLASS)
1991                      specType.kind = thisClassType;
1992                }
1993                else if(spec.type == nameSpecifier)
1994                {
1995                   Symbol symbol = spec.name ? FindType(curContext, spec.name) : null;
1996                   if(symbol && symbol.type)
1997                   {
1998                      CopyTypeInto(specType, symbol.type);
1999                      specType.typeName = CopyString(symbol.type.name);
2000                   }
2001                   else if(!isTypedef) // !specType.kind)    // TESTING THIS FOR enum / typedef problem
2002                   {
2003                      // key.sym enum values need FindClass:
2004                      specType._class = spec.name ? FindClass(spec.name) : null;
2005                      // specType._class = spec.symbol; 
2006                      specType.kind = classType;
2007                      if(!specType._class)
2008                         specType.kind = intType;
2009                   }
2010                }
2011                else if(spec.type == enumSpecifier)
2012                {
2013
2014                   specType.kind = enumType;
2015                   specType.enumName = spec.id ? CopyString(spec.id.string) : null;
2016
2017                   if(spec.list)
2018                   {
2019                      Enumerator e;
2020                      int nextValue = 0;
2021                      for(e = spec.list->first; e; e = e.next)
2022                      {
2023                         specType.members.Add(NamedItem { name = CopyString(e.id.string) });
2024                         /*
2025                         if(e.exp && ComputeExpression(e.exp), e.exp.isConstant && e.exp.expType.kind == intType)
2026                            value.data = (void *) nextValue = strtol(e.exp.string, null, 0);
2027                         else
2028                            value.data = (void *)nextValue++;
2029                         */
2030                      }
2031                   }
2032                   /*
2033                   if(spec.list)
2034                   {
2035                      Declaration decl;
2036                      for(enumerator = spec.list->first; enumerator; enumerator = enumerator.next)
2037                         if(decl.declarators)
2038                         {
2039                            Declarator d;
2040                            for(d = decl.declarators.first; d; d = d.next)
2041                            {
2042                               Type memberType = ProcessType(decl.specifiers, d);
2043                               specType.members.Add(memberType);
2044                            }
2045                         }
2046                         else if(decl.specifiers)
2047                         {
2048                            Type memberType = ProcessType(decl.specifiers, null);
2049                            specType.members.Add(memberType);
2050                         }
2051                   }
2052                   */
2053                }
2054                else if(spec.type == templateTypeSpecifier)
2055                {
2056                   /*
2057                   printf("spec %x\n", spec);
2058                   printf("template param %x\n", spec.templateParameter);
2059                   printf("identifier %x\n", spec.templateParameter.identifier);
2060                   printf("string %x\n", spec.templateParameter.identifier.string);
2061                   */
2062                   specType.kind = templateType;
2063                   specType.templateParameter = spec.templateParameter;
2064                }
2065                else if(spec.type == structSpecifier || spec.type == unionSpecifier)
2066                {
2067                   Symbol _class = spec.id ? FindClass(spec.id.string) : null;
2068                   if(_class)
2069                   {
2070                      if(!_class.registered || _class.registered.type != structClass)
2071                         specType.directClassAccess = true;
2072                      specType._class = _class;
2073                      specType.kind = classType;
2074                      break;
2075                   }
2076                   if(spec.type == structSpecifier)
2077                      specType.kind = structType;
2078                   else if(spec.type == unionSpecifier)
2079                      specType.kind = unionType;
2080                   if(spec.id)
2081                   {
2082                      // TESTING THIS HERE... Had 0 type size 
2083                      if(!spec.definitions && !isTypedef)
2084                      {
2085                         Symbol symbol = spec.id.string ? FindSymbol(spec.id.string, curContext, globalContext, true, false) : null;
2086                         if(symbol && symbol.type)
2087                         {
2088                            specType = *symbol.type;
2089                            specType.name = CopyString(symbol.type.name);
2090                            specType.typeName = CopyString(spec.name);
2091                            specType.enumName = CopyString(symbol.type.enumName);
2092                            specType.refCount = 1;
2093
2094                            if(symbol.type.kind == enumType)
2095                            {
2096                               NamedLink member;
2097
2098                               specType.members.Clear();
2099                               for(member = specType.members.first; member; member = member.next)
2100                               {
2101                                  specType.members.Add(NamedLink { name = CopyString(member.name), data = member.data });
2102                               }
2103                            }
2104                            else if(symbol.type.kind == structType || symbol.type.kind == unionType)
2105                            {
2106                               Type member;
2107                               // Tricky stuff... will be removed from list only when ref count reaches 0
2108                               for(member = specType.members.first; member; member = member.next)
2109                                  member.refCount++;
2110                            }
2111                            else if(symbol.type.kind == functionType)
2112                            {
2113                               Type param;
2114                               specType.returnType.refCount++;
2115                               for(param = specType.params.first; param; param = param.next)
2116                                  param.refCount++;
2117                            }
2118                            else if(symbol.type.kind == pointerType || symbol.type.kind == arrayType)
2119                            {
2120                               specType.type.refCount++;
2121                               if(symbol.type.kind == arrayType)
2122                               {
2123                                  if(specType.arraySizeExp)
2124                                     specType.arraySizeExp = CopyExpression(specType.arraySizeExp);
2125                               }
2126
2127                            }
2128                         }
2129                         else
2130                            specType.enumName = CopyString(spec.id.string);
2131                      }
2132                      else
2133                         specType.enumName = CopyString(spec.id.string);
2134                   }
2135
2136                   if(spec.definitions)
2137                   {
2138                      ClassDef def;
2139                      for(def = spec.definitions->first; def; def = def.next)
2140                      {
2141                         if(def.type == declarationClassDef && def.decl.type == structDeclaration)
2142                         {
2143                            Declaration decl = def.decl;
2144                            if(decl.declarators)
2145                            {
2146                               Declarator d;
2147                               for(d = decl.declarators->first; d; d = d.next)
2148                               {
2149                                  Type memberType = ProcessType(decl.specifiers, d);
2150                                  specType.members.Add(memberType);
2151                               }
2152                            }
2153                            else if(decl.specifiers)
2154                            {
2155                               Type memberType = ProcessType(decl.specifiers, null);
2156                               specType.members.Add(memberType);
2157                            }
2158                         }
2159                      }
2160                   }
2161                   break;
2162                }
2163                else if(spec.type == subClassSpecifier)
2164                {
2165                   specType.kind = specType.kind = subClassType;
2166                   specType._class = spec._class.symbol; // FindClass(spec._class.name);
2167                }
2168                /*
2169                else if(spec.type == classSpecifier)
2170                {
2171                   specType._class = FindClass(spec.name);
2172                   specType.kind = classType;
2173                }
2174                */
2175             }
2176          }
2177          else if(!decl)
2178             specType.kind = ellipsisType;
2179       }
2180
2181       if(funcDecl)
2182       {
2183          Declarator d = funcDecl.declarator;
2184          Type funcType { };
2185          TypeName param;
2186
2187          funcType.kind = functionType;
2188          funcType.refCount = 1;
2189          if(funcDecl.function.parameters)
2190          {
2191             for(param = funcDecl.function.parameters->first; param; param = param.next)
2192             {
2193                /*
2194                if(param.typedObject)
2195                {
2196                   Type typedObjectType
2197                   {
2198                      refCount = 1;
2199                      byReference = param.byReference;
2200                      kind = TypeTypedObject;
2201                   };
2202                   funcType.params.Add(typedObjectType);
2203                }
2204                else*/
2205                   funcType.params.Add(ProcessType(param.qualifiers, param.declarator));
2206             }
2207          }
2208
2209          // Function returning a pointer...
2210          if(decl.type == pointerDeclarator)
2211          {
2212             Pointer pointer = decl.pointer.pointer;
2213             Type ptrType { };
2214             funcType.returnType = ptrType;
2215             funcType.returnType.refCount = 1;
2216             while(pointer)
2217             {
2218                ptrType.kind = pointerType;
2219                pointer = pointer.pointer;
2220                if(pointer)
2221                {
2222                   ptrType.type = Type { refCount = 1 };
2223                   ptrType = ptrType.type;
2224                }
2225             }
2226             ptrType.type = Type { refCount = 1 };
2227             *ptrType.type = specType;
2228          }
2229          else
2230          {
2231             funcType.returnType = Type { refCount = 1 };
2232             *funcType.returnType = specType;
2233          }
2234
2235          // TESTING: Added extendedDeclarator here
2236          while(d && (d.type == bracketsDeclarator || d.type == extendedDeclarator || d.type == extendedDeclaratorEnd))
2237          {
2238             if((d.type == extendedDeclarator || d.type == extendedDeclaratorEnd) && d.extended.extended && 
2239                (!strcmp(d.extended.extended, "__declspec(dllexport)") || !strcmp(d.extended.extended, "dllexport")))
2240             {
2241                dllExport = true;            
2242             }
2243             d = d.declarator;
2244          }
2245
2246          funcType.dllExport = dllExport;
2247
2248          if(d && d.type == pointerDeclarator)
2249          {
2250             Type ptrType;
2251             Identifier id;
2252
2253             if(d.declarator && d.declarator.type == arrayDeclarator)
2254             {
2255                // Arrays of pointers to functions (extremely tricky :()
2256                Pointer pointer = d.pointer.pointer;
2257
2258                // TO WORK ON: Fixed the order for the array...
2259                type.kind = arrayType;
2260                type.arraySizeExp = CopyExpression(d.declarator.array.exp);
2261                type.freeExp = true;
2262                if(d.declarator.array.enumClass)
2263                   type.enumClass = d.declarator.array.enumClass.symbol; // FindClass(d.declarator.array.enumClass.name);
2264                if(d.declarator.declarator && d.declarator.declarator.type == arrayDeclarator)
2265                {
2266                   Type tmpType = type;
2267                   Type inType;
2268                   type = ProcessType(null, d.declarator.declarator);
2269                   inType = type.type;
2270                   type.type = tmpType;
2271                   tmpType.type = inType;
2272                }
2273                else
2274                   type.type = ProcessType(null, d.declarator.declarator);
2275
2276                for(ptrType = type.type; ptrType && ptrType.kind && ptrType.type; ptrType = ptrType.type);
2277
2278                while(pointer)
2279                {
2280                   ptrType.kind = pointerType;
2281                   pointer = pointer.pointer;
2282                   if(pointer)
2283                   {
2284                      ptrType.type = Type { refCount = 1 };
2285                      ptrType = ptrType.type;
2286                   }
2287                }
2288                ptrType.type = ProcessType(specs, null);
2289             }
2290             else
2291             {
2292                // WARNING: Not caring if this declarator contains a declarator between
2293                //          the pointer and the function other than brackets (like in the case of array of pointers to functions)...
2294                // *********** Could it ever go in here???  Yes: void (* converters_table[10]) (); ***********
2295                Pointer pointer = d.pointer.pointer;
2296
2297                ptrType = type;
2298                while(pointer)
2299                {
2300                   ptrType.kind = pointerType;
2301                   ptrType.type = Type { refCount = 1 };
2302                   pointer = pointer.pointer;
2303                   if(pointer)
2304                      ptrType = ptrType.type;
2305                }
2306             }
2307
2308             *ptrType.type = funcType;
2309             id = GetDeclId(d);
2310             if(id)
2311             {
2312                if(id._class && !id._class.name)
2313                   ptrType.type.staticMethod =  true;
2314                else 
2315                {
2316                   // TODO : Ensure classSym has been resolved here... (Is this gonna cause problems? Supposed to do this later...)
2317                   if(!id.classSym)
2318                   {
2319                      if(id._class && id._class.name)
2320                      {
2321                         id.classSym = id._class.symbol; // FindClass(id._class.name);
2322                         /* TODO: Name Space Fix ups
2323                         if(!id.classSym)
2324                            id.nameSpace = eSystem_FindNameSpace(privateModule, id._class.name);
2325                         */
2326                      }
2327                   }
2328
2329                   ptrType.type.thisClass = id.classSym;
2330                   if(ptrType.type.thisClass && strcmp(ptrType.type.thisClass.string, "class"))
2331                      ptrType.type.extraParam = true;
2332                   else if(id._class && id._class.name && !strcmp(id._class.name, "any_object"))
2333                   {
2334                      ptrType.type.extraParam = true;
2335                      ptrType.type.thisClass = FindClass("class");
2336                   }
2337                }
2338
2339                type.name = CopyString(id.string);
2340             }
2341          }
2342          else if(!d || d.type == identifierDeclarator)
2343          {
2344
2345             *type = funcType;
2346             if(d)
2347             {
2348                if(d.identifier._class && d.identifier._class.type == templateTypeSpecifier)
2349                {
2350                   type.thisClassTemplate = d.identifier._class.templateParameter;
2351                   type.extraParam = true;
2352                }
2353                else
2354                {
2355                   if(d.identifier._class && !d.identifier._class.name)
2356                      type.staticMethod = true;
2357                   else
2358                   {
2359                      if(d.identifier._class && d.identifier._class.name && d.identifier._class.name[strlen(d.identifier._class.name)-1] == '&')
2360                      {
2361                         type.thisClass = FindClass("class");
2362                         type.byReference = true;
2363                      }
2364                      else
2365                         type.thisClass = d.identifier._class ? d.identifier._class.symbol /*FindClass(d.identifier._class.name)*/ : null;
2366                      if(type.thisClass && strcmp(type.thisClass.string, "class"))
2367                      {
2368                         type.extraParam = true;
2369                      }
2370                      else if(d.identifier._class && d.identifier._class.name && !strcmp(d.identifier._class.name, "any_object"))
2371                      {
2372                         type.extraParam = true;
2373                         type.thisClass = FindClass("class");
2374                      }
2375                      else if(d.identifier._class && d.identifier._class.name && !strcmp(d.identifier._class.name, "class"))
2376                      {
2377                         //type.extraParam = true;
2378                         type.thisClass = FindClass("class");
2379                         type.classObjectType = classPointer;
2380                      }
2381                   }
2382                }
2383                type.name = CopyString(d.identifier.string);
2384             }
2385          }
2386          delete funcType;
2387       }
2388       else if(decl && decl.type == pointerDeclarator)
2389       {
2390          if(decl.declarator && decl.declarator.type == arrayDeclarator)
2391          {
2392             // Arrays of pointers (tricky :))
2393             Identifier id;
2394             Pointer pointer = decl.pointer.pointer;
2395             Type ptrType;
2396
2397             // TO WORK ON: Fixed the order for the array...
2398             type.kind = arrayType;
2399             type.arraySizeExp = CopyExpression(decl.declarator.array.exp);
2400             type.freeExp = true;
2401             if(decl.declarator.array.enumClass)
2402                type.enumClass = decl.declarator.array.enumClass.symbol; // FindClass(decl.declarator.array.enumClass.name);
2403             if(decl.declarator.declarator && decl.declarator.declarator.type == arrayDeclarator)
2404             {
2405                Type tmpType = type;
2406                Type inType;
2407                type = ProcessType(null, decl.declarator.declarator);
2408                inType = type.type;
2409                type.type = tmpType;
2410                tmpType.type = inType;
2411             }
2412             else
2413                type.type = ProcessType(null, decl.declarator.declarator);
2414             /*
2415             type.type = ProcessType(null, decl.declarator.declarator);
2416             type.kind = arrayType;
2417             type.arraySizeExp = CopyExpression(decl.declarator.array.exp);
2418             type.arraySizeExp.freeExp = true;
2419             if(decl.array.enumClass)
2420                type.enumClass = FindClass(decl.array.enumClass.name);
2421             */
2422
2423             for(ptrType = type.type; ptrType && ptrType.kind && ptrType.type; ptrType = ptrType.type);
2424
2425             while(pointer)
2426             {
2427                ptrType.kind = pointerType;
2428                pointer = pointer.pointer;
2429                if(pointer)
2430                {
2431                   ptrType.type = Type { refCount = 1 };
2432                   ptrType = ptrType.type;
2433                }
2434             }
2435             ptrType.type = ProcessType(specs, null);
2436             id = GetDeclId(decl);
2437             if(id) type.name = CopyString(id.string);
2438          }
2439          else
2440          {
2441             Identifier id;
2442             Pointer pointer = decl.pointer.pointer;
2443             Type ptrType = type;
2444
2445             if(type.classObjectType)
2446             {
2447                type.byReference = true;
2448             }
2449             else
2450             {
2451                while(pointer)
2452                {
2453                   ptrType.kind = pointerType;
2454                   pointer = pointer.pointer;
2455                   if(pointer)
2456                   {
2457                      ptrType.type = Type { refCount = 1 };
2458                      ptrType = ptrType.type;
2459                   }
2460                }
2461                ptrType.type = ProcessType(specs, decl.declarator);
2462
2463                if(type.type.classObjectType)
2464                {
2465                   Type subType = type.type;
2466                   type.classObjectType = subType.classObjectType;
2467                   type.kind = subType.kind;
2468                   type._class = subType._class;
2469                   type.byReference = true;
2470
2471                   FreeType(subType);
2472                }
2473                id = GetDeclId(decl);
2474                if(id) type.name = CopyString(id.string);
2475             }
2476          }
2477       }
2478       else if(decl && decl.type == arrayDeclarator)
2479       {
2480          Identifier id;
2481
2482          type.kind = arrayType;
2483          
2484          type.arraySizeExp = CopyExpression(decl.array.exp);
2485          type.freeExp = true;
2486          if(decl.array.enumClass)
2487             type.enumClass = decl.array.enumClass.symbol; // FindClass(decl.array.enumClass.name);
2488          id = GetDeclId(decl);
2489
2490          // TO WORK ON: Fixed the order for the array...
2491          if(decl.declarator && decl.declarator.type == arrayDeclarator)
2492          {
2493             Type tmpType = type;
2494             Type inType;
2495             type = ProcessType(specs, decl.declarator);
2496             inType = type.type;
2497             type.type = tmpType;
2498             tmpType.type = inType;
2499          }
2500          else
2501             type.type = ProcessType(specs, decl.declarator);
2502
2503          if(id)
2504          {
2505             delete type.name;
2506             type.name = CopyString(id.string);
2507          }
2508       }
2509       else
2510       {
2511          if(!decl || decl.type == identifierDeclarator)
2512          {
2513             *type = specType;
2514             delete type.name;
2515             type.name = decl ? CopyString(decl.identifier.string) : null;
2516          }   
2517       }
2518       delete specType;
2519    }
2520    return type;
2521 }
2522
2523 public Type ProcessTypeString(char * string, bool staticMethod)
2524 {
2525    OldList * specs = MkList();
2526    Declarator decl = SpecDeclFromString(string, specs, null);
2527    Type type = ProcessType(specs, decl);
2528    if(type && !type.thisClass && staticMethod) type.staticMethod = true;
2529    FreeList(specs, FreeSpecifier);
2530    if(decl) FreeDeclarator(decl);
2531    return type;
2532 }
2533
2534 Type MkClassTypeSymbol(Symbol symbol)
2535 {
2536    if(symbol)
2537    {
2538       Type type { kind = classType, _class = symbol };
2539       if(!type._class)
2540       {
2541          // Defaults to an int instead...
2542          type.kind = intType;
2543       }
2544       type.refCount = 1;
2545       return type;
2546    }
2547    return null;
2548 }
2549
2550 public Type MkClassType(char * name)
2551 {
2552    if(name)
2553    {
2554       Type type { kind = classType, _class = FindClass(name) };
2555       if(!type._class)
2556       {
2557          // Defaults to an int instead...
2558          type.kind = intType;
2559       }
2560       type.refCount = 1;
2561       return type;
2562    }
2563    return null;
2564 }
2565
2566 AsmField MkAsmField(char * command, Expression expression)
2567 {
2568    return { command = command, expression = expression };
2569 }
2570
2571 Statement MkAsmStmt(Specifier spec, char * statements, OldList inputFields, OldList outputFields, OldList clobberedFields)
2572 {
2573    return { type = asmStmt, asmStmt.spec = spec, asmStmt.statements = statements, 
2574       asmStmt.inputFields = inputFields, asmStmt.outputFields = outputFields, 
2575       asmStmt.clobberedFields = clobberedFields };
2576 }
2577
2578 ClassDef MkClassDefPropertyWatch(PropertyWatch watcher)
2579 {
2580    return { type = propertyWatchClassDef, propertyWatch = watcher };
2581 }
2582
2583 Statement MkFireWatchersStmt(Expression object, OldList watches)
2584 {
2585    return { type = fireWatchersStmt, _watch.object = object, _watch.watches = watches };
2586 }
2587
2588 Statement MkStopWatchingStmt(Expression watcher, Expression object, OldList watches)
2589 {
2590    return { type = stopWatchingStmt, _watch.watcher = watcher, _watch.object = object, _watch.watches = watches };
2591 }
2592
2593 Statement MkWatchStmt(Expression watcher, Expression object, OldList watches)
2594 {
2595    return { type = watchStmt, _watch.watcher = watcher, _watch.object = object, _watch.watches = watches };
2596 }
2597
2598 PropertyWatch MkDeleteWatch(Statement compound)
2599 {
2600    return { compound = compound, deleteWatch = true };
2601 }
2602
2603 PropertyWatch MkPropertyWatch(OldList properties, Statement compound)
2604 {
2605    return { compound = compound, properties = properties };
2606 }
2607
2608 Expression MkExpClass(OldList * specifiers, Declarator decl)
2609 {
2610    return { type = classExp, _classExp.specifiers = specifiers, _classExp.decl = decl };
2611 }
2612
2613 Expression MkExpClassData(Identifier id)
2614 {
2615    return { type = classDataExp, classData.id = id };
2616 }
2617
2618
2619 External MkExternalDBTable(DBTableDef table)
2620 {
2621    return { type = dbtableExternal, table = table };
2622 }
2623
2624 DBTableDef MkDBTableDef(char * name, Symbol symbol, OldList * definitions)
2625 {
2626    return { name = name, symbol = symbol, definitions = definitions };
2627 }
2628
2629 DBTableEntry MkDBFieldEntry(TypeName type, Identifier id, char * name)
2630 {
2631    return { type = fieldEntry, dataType = type, id = id, name = name };
2632 }
2633
2634 DBIndexItem MkDBIndexItem(Identifier id, Order order)
2635 {
2636    return { id = id, order = order };
2637 }
2638
2639 DBTableEntry MkDBIndexEntry(OldList * items, Identifier id)
2640 {
2641    return { type = indexEntry, items = items, id = id };
2642 }
2643
2644 Expression MkExpDBOpen(Expression ds, Expression dbName)
2645 {
2646    return { type = dbopenExp, dbopen.ds = ds, dbopen.name = dbName };
2647 }
2648
2649 Expression MkExpDBField(char * table, Identifier id)
2650 {
2651    return { type = dbfieldExp, db.table = table, db.id = id };
2652 }
2653
2654 Expression MkExpDBIndex(char * table, Identifier id)
2655 {
2656    return { type = dbindexExp, db.table = table, db.id = id };
2657 }
2658
2659 Expression MkExpDBTable(char * table)
2660 {
2661    return { type = dbtableExp, db.table = table };
2662 }
2663
2664 Expression MkExpArray(OldList * expressions)
2665 {
2666    return { type = arrayExp, list = expressions };
2667 }
2668
2669 Expression GetTemplateArgExpByName(char * paramName, Class curClass, TemplateParameterType tplType)
2670 {
2671    Expression argExp = null;
2672    Class _class = curClass ? curClass : ((curExternal && curExternal.type == functionExternal && curExternal.function) ? curExternal.function._class : null);
2673    if(_class)
2674    {
2675       int id = 0;
2676       ClassTemplateParameter curParam;
2677       Class sClass;
2678       for(sClass = _class; sClass; sClass = sClass.base)
2679       {
2680          id = 0;
2681          for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
2682          {
2683             if(!strcmp(curParam.name, paramName))
2684             {
2685                for(sClass = sClass.base; sClass; sClass = sClass.base)
2686                   id += sClass.templateParams.count;
2687                break;
2688             }
2689             id++;
2690          }
2691          if(curParam) break;
2692       }
2693
2694       if(curParam && curParam.type != tplType)
2695          curParam = null;
2696
2697       if(curParam)
2698       {
2699          char idString[32];
2700          char className[1024];
2701          Expression classExp;
2702          
2703          sprintf(idString, "%d", id);
2704          strcpy(className, "__ecereClass_");
2705          FullClassNameCat(className, _class.fullName, true);
2706          MangleClassName(className);
2707          DeclareClass(FindClass(_class.fullName), className);
2708
2709          argExp = MkExpIndex((/*pointer ? MkExpPointer : */MkExpMember)
2710                (MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class")) /*MkExpIdentifier(MkIdentifier(className))*/, 
2711                MkIdentifier("templateArgs")), MkListOne(MkExpConstant(idString)));
2712       }
2713    }
2714    return argExp; 
2715 }
2716
2717 Expression GetTemplateArgExp(TemplateParameter param, Class curClass, bool pointer)
2718 {
2719    return param.identifier ? GetTemplateArgExpByName(param.identifier.string, curClass, type) : null;
2720 }
2721
2722 public void OutputIntlStrings()
2723 {
2724    if(intlStrings.count)
2725    {
2726       char * srcFile = GetSourceFile();
2727       char * objFile = GetOutputFile();
2728       char potFile[MAX_LOCATION];
2729       File f;
2730       ChangeExtension(objFile, "bowl", potFile);
2731       f = FileOpen(potFile, write);
2732       if(f)
2733       {
2734          for(s : intlStrings)
2735          {
2736             f.Printf("# %s %d\n", srcFile, s.start.line);
2737             f.Printf("msgid %s\n", &s);
2738             f.Printf("msgstr %s\n\n", &s);
2739          }
2740          delete f;
2741       }
2742       intlStrings.Free();
2743    }
2744 }