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