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