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