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