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