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