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