ide/Debugger/watches: Fix unichar evaluation broken by fa765a838029ec71a86787e95ebcab...
[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                         if(s[0] == 'L') s++;
983
984                         // MAKE MORE ACCURATE
985                         for(c = 1; (ch = s[c]); c++)
986                         {
987                            if(ch == '\\' && !escaped)
988                               escaped = true;
989                            else
990                            {
991                               count++;
992                               escaped = false;
993                            }
994                         }
995
996                         sprintf(string, "%d", count);
997                         symbol.type.arraySizeExp = MkExpConstant(string);
998                         symbol.type.freeExp = true;
999                      }
1000                   }
1001                }
1002                decl.symbol = d.declarator.symbol = symbol;
1003             }
1004          }
1005       }
1006    }
1007    else
1008    {
1009       decl.symbol = Symbol { };
1010       excludedSymbols->Add(decl.symbol);
1011    }
1012    return decl;
1013 }
1014
1015 Declaration MkStructDeclaration(OldList specifiers, OldList declarators, Specifier extStorage)
1016 {
1017    Declaration decl { type = structDeclaration, declarators = declarators, specifiers = specifiers, extStorage = extStorage, loc = yylloc };
1018    if(specifiers != null)
1019    {
1020       bool gotType = false;
1021       Specifier spec, next;
1022       for(spec = specifiers.first; spec; spec = next)
1023       {
1024          next = spec.next;
1025          if(gotType && declarators == null && ((spec.type == nameSpecifier && spec.name) || spec.type == baseSpecifier))
1026          {
1027             const String s = null;
1028             if(spec.type == nameSpecifier)
1029             {
1030                const char * colon = RSearchString(spec.name, "::", strlen(spec.name), true, false);
1031                s = colon ? colon + 2 : spec.name;
1032             }
1033             else if(spec.type == baseSpecifier)
1034             {
1035                if(spec.specifier == INT64) s = "int64";
1036             }
1037             if(s)
1038             {
1039                decl.declarators = declarators = MkListOne(MkStructDeclarator(MkDeclaratorIdentifier(MkIdentifier(s)), null));
1040                specifiers.Remove(spec);
1041                FreeSpecifier(spec);
1042                spec = null;
1043             }
1044          }
1045          if(spec && spec.type != extendedSpecifier)
1046             gotType = true;
1047       }
1048    }
1049    return decl;
1050 }
1051
1052 Statement MkLabeledStmt(Identifier id, Statement statement)
1053 {
1054    return { type = labeledStmt, labeled.id = id, labeled.stmt = statement, loc = yylloc };
1055 }
1056
1057 Statement MkCaseStmt(Expression exp, Statement statement)
1058 {
1059    return { type = caseStmt, caseStmt.exp = exp, caseStmt.stmt = statement, loc = yylloc };
1060 }
1061
1062 Statement MkCompoundStmt(OldList declarations, OldList statements)
1063 {
1064    return { type = compoundStmt, compound.declarations = declarations, compound.statements = statements, loc = yylloc };
1065 }
1066
1067 Statement MkExpressionStmt(OldList expressions)
1068 {
1069    return { type = expressionStmt, expressions = expressions, loc = yylloc };
1070 }
1071
1072 Statement MkBadDeclStmt(Declaration decl)
1073 {
1074    return { type = badDeclarationStmt, decl = decl, loc = yylloc };
1075 }
1076
1077 Statement MkIfStmt(OldList exp, Statement statement, Statement elseStmt)
1078 {
1079    return { type = ifStmt, ifStmt.exp = exp, ifStmt.stmt = statement, ifStmt.elseStmt = elseStmt, loc = yylloc };
1080 }
1081
1082 Statement MkSwitchStmt(OldList exp, Statement statement)
1083 {
1084    // To know it's a switch compound... (Don't want declarations in there... bugs)
1085    if(statement)
1086       statement.compound.isSwitch = true;
1087    return { type = switchStmt, switchStmt.exp = exp, switchStmt.stmt = statement, loc = yylloc };
1088 }
1089
1090 Statement MkWhileStmt(OldList exp, Statement statement)
1091 {
1092    return { type = whileStmt, whileStmt.exp = exp, whileStmt.stmt = statement, loc = yylloc };
1093 }
1094
1095 Statement MkDoWhileStmt(Statement statement, OldList exp)
1096 {
1097    return { type = doWhileStmt, doWhile.exp = exp, doWhile.stmt = statement, loc = yylloc };
1098 }
1099
1100 Statement MkForStmt(Statement init, Statement check, OldList inc, Statement statement)
1101 {
1102    return { type = forStmt, forStmt.init = init, forStmt.check = check, forStmt.increment = inc, forStmt.stmt = statement, loc = yylloc };
1103 }
1104
1105 Statement MkForEachStmt(Identifier id, OldList exp, OldList filter, Statement statement)
1106 {
1107    return { type = forEachStmt, forEachStmt.id = id, forEachStmt.exp = exp, forEachStmt.filter = filter, forEachStmt.stmt = statement, loc = yylloc };
1108 }
1109
1110 Statement MkGotoStmt(Identifier id)
1111 {
1112    return { type = gotoStmt, gotoStmt.id = id, loc = yylloc };
1113 }
1114
1115 Statement MkContinueStmt()
1116 {
1117    return { type = continueStmt, loc = yylloc };
1118 }
1119
1120 Statement MkBreakStmt()
1121 {
1122    return { type = breakStmt, loc = yylloc };
1123 }
1124
1125 Statement MkReturnStmt(OldList exp)
1126 {
1127    return { type = returnStmt, expressions = exp, loc = yylloc };
1128 }
1129
1130 FunctionDefinition MkFunction(OldList specifiers, Declarator declarator, OldList declarationList)
1131 {
1132    return _MkFunction(specifiers, declarator, declarationList, true);
1133 }
1134
1135 FunctionDefinition _MkFunction(OldList specifiers, Declarator declarator, OldList declarationList, bool errorOnOmit)
1136 {
1137    if(errorOnOmit)
1138    {
1139       Declarator funcDecl = GetFuncDecl(declarator);
1140       if(funcDecl && funcDecl.function.parameters)
1141       {
1142          TypeName tn;
1143          for(tn = funcDecl.function.parameters->first; tn; tn = tn.next)
1144          {
1145             if(tn.qualifiers || tn.declarator)
1146             {
1147                Identifier declID = tn.declarator ? GetDeclId(tn.declarator) : null;
1148                if(!declID)
1149                {
1150                   // Check for (void)
1151                   Specifier spec = tn.qualifiers ? tn.qualifiers->first : null;
1152                   if(!tn.declarator && !tn.prev && !tn.next && spec && !spec.next && spec.type == baseSpecifier && spec.specifier == VOID);
1153                   else
1154                      Compiler_Error($"parameter name omitted\n");
1155                   break;
1156                }
1157             }
1158          }
1159       }
1160    }
1161    return { specifiers = specifiers, declarator = declarator, declarations = declarationList };
1162 }
1163
1164 void ProcessFunctionBody(FunctionDefinition func, Statement body)
1165 {
1166    Declarator declarator = func.declarator;
1167    Declarator funcDecl = GetFuncDecl(declarator);
1168    Symbol symbol;
1169
1170    func.body = body;
1171
1172    if(funcDecl && funcDecl.function.parameters && body)
1173    {
1174       Context context = body.compound.context;
1175       TypeName param;
1176       for(param = funcDecl.function.parameters->first; param; param = param.next)
1177       {
1178          if(param.declarator)
1179          {
1180             Symbol symbol = null;
1181             Identifier id = GetDeclId(param.declarator);
1182             char * string = id ? id.string : null;
1183             if(string)
1184             {
1185                for(symbol = (Symbol)context.symbols.first; symbol; symbol = (Symbol)((BTNode)symbol).next)
1186                   if(!strcmp(symbol.string, string))
1187                      break;
1188                // This parameter is not shadowed by a local declaration
1189                if(!symbol && id)
1190                {
1191                   symbol = Symbol { string = CopyString(id.string), type = ProcessType(param.qualifiers, param.declarator), isParam = true };
1192                   if(!context.symbols.Add((BTNode)symbol))
1193                      excludedSymbols->Add(symbol);
1194
1195                   param.declarator.symbol = symbol;
1196                }
1197             }
1198          }
1199       }
1200    }
1201
1202    if(!declarator.symbol)
1203    {
1204       Identifier id = GetDeclId(declarator);
1205
1206       if((currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess && strcmp(id.string, "__on_register_module"))
1207       {
1208          char name[1024];
1209          int len = 0, stringLen;
1210          if(defaultNameSpace)
1211          {
1212             memcpy(name, defaultNameSpace, defaultNameSpaceLen);
1213             len += defaultNameSpaceLen;
1214             name[len++] = ':';
1215             name[len++] = ':';
1216          }
1217          if(currentNameSpace)
1218          {
1219             memcpy(name + len, currentNameSpace, currentNameSpaceLen);
1220             len += currentNameSpaceLen;
1221             name[len++] = ':';
1222             name[len++] = ':';
1223          }
1224          stringLen = strlen(id.string);
1225          memcpy(name + len, id.string, stringLen);
1226          len += stringLen;
1227          name[len] = 0;
1228          delete id.string;
1229          id.string = CopyString(name);
1230       }
1231       symbol = Symbol { string = CopyString(id.string), type = ProcessType(func.specifiers, declarator) };
1232       if(strstr(symbol.string, "::"))
1233          globalContext.hasNameSpace = true;
1234       if(!globalContext.symbols.Add((BTNode)symbol))
1235          excludedSymbols->Add(symbol);
1236       declarator.symbol = symbol;
1237    }
1238    else
1239    {
1240       symbol = declarator.symbol;
1241       excludedSymbols->Remove(declarator.symbol);
1242       delete symbol.string;
1243       symbol.string = CopyString(GetDeclId(declarator).string);
1244       if(strstr(symbol.string, "::"))
1245          globalContext.hasNameSpace = true;
1246       if(!globalContext.symbols.Add((BTNode)symbol))
1247          excludedSymbols->Add(symbol);
1248
1249       if(!symbol.type)
1250          symbol.type = ProcessType(func.specifiers, declarator);
1251    }
1252    if(symbol.type && (symbol.type.kind == functionType || symbol.type.kind == methodType))
1253    {
1254       if(!symbol.type.params.count)
1255       {
1256          Type type { refCount = 1 };
1257          symbol.type.params.Add(type);
1258       }
1259    }
1260    else
1261    {
1262       //printf("");
1263    }
1264 }
1265
1266 External MkExternalFunction(FunctionDefinition function)
1267 {
1268    External external { type = functionExternal, function = function, symbol = function.declarator.symbol };
1269    if(function.specifiers)
1270    {
1271       Specifier spec;
1272       for(spec = function.specifiers->first; spec; spec = spec.next)
1273          if(spec.type == baseSpecifier && spec.specifier == STATIC)
1274          {
1275             structDeclMode = declMode = staticAccess;
1276             break;
1277          }
1278    }
1279
1280    if(external.symbol && !external.symbol.methodExternal)
1281       external.symbol.methodExternal = external;
1282    return external;
1283 }
1284
1285 External MkExternalImport(char * name, ImportType importType, AccessMode importAccess)
1286 {
1287    External external { type = importExternal };
1288    int len = strlen(name) - 2;
1289    external.importString = new char[len + 1];
1290    strncpy(external.importString, name+1, len);
1291    external.importString[len] = '\0';
1292    delete name;
1293
1294    {
1295 #ifdef _TIMINGS
1296       Time startTime = GetTime();
1297       Time time;
1298 #endif
1299       ImportModule(external.importString, importType, importAccess, true);
1300       ImportModule(external.importString, importType, importAccess, false);
1301 #ifdef _TIMINGS
1302       time = GetTime() - startTime;
1303       printf("Importing took %.3f seconds for %s\n", time, external.importString);
1304       externalImportTotalTime += time;
1305 #endif
1306    }
1307    return external;
1308 }
1309
1310 External MkExternalDeclaration(Declaration declaration)
1311 {
1312    External external { type = declarationExternal, declaration = declaration, symbol = declaration ? declaration.symbol : null };
1313    if(declaration && declaration.type == initDeclaration && declaration.specifiers)
1314    {
1315       Specifier spec;
1316       for(spec = declaration.specifiers->first; spec; spec = spec.next)
1317          if(spec.type == baseSpecifier && spec.specifier == TYPEDEF)
1318          {
1319             structDeclMode = declMode = defaultAccess;
1320             break;
1321          }
1322          else if(spec.type == baseSpecifier && spec.specifier == STATIC)
1323          {
1324             structDeclMode = declMode = staticAccess;
1325             break;
1326          }
1327    }
1328    if(declaration && declaration.symbol && !declaration.symbol.methodExternal)
1329       declaration.symbol.methodExternal = external;
1330    return external;
1331 }
1332
1333 External MkExternalNameSpace(Identifier identifier)
1334 {
1335    External external { type = nameSpaceExternal, id = identifier };
1336    currentNameSpace = identifier ? identifier.string : null;
1337    currentNameSpaceLen = currentNameSpace ? strlen(currentNameSpace) : 0;
1338    return external;
1339 }
1340
1341 void SetClassTemplateArgs(Specifier spec, OldList templateArgs)
1342 {
1343    if(spec.type == nameSpecifier)
1344    {
1345       Symbol symbol = spec.symbol;
1346       spec.templateArgs = templateArgs;
1347       if(templateArgs && templateArgs.first)
1348       {
1349          char templateString[1024];
1350          TemplateArgument arg;
1351          strcpy(templateString, symbol ? symbol.string : spec.name);
1352          strcat(templateString, "<");
1353          for(arg = templateArgs.first; arg; arg = arg.next)
1354          {
1355             char argument[256];
1356             argument[0] = '\0';
1357             switch(arg.type)
1358             {
1359                case expression:
1360                {
1361                   char expString[1024];
1362                   Class backupThisClass = thisClass;
1363                   thisClass = null;
1364                   expString[0] = '\0';
1365                   // Will this work here?
1366                   /*
1367                   Location oldLocation = yylloc;
1368                   File backFileInput = fileInput;
1369                   declMode = 0;
1370                   resetScanner();
1371                   */
1372
1373                   // TESTING THIS SCANNER RESUME STUFF
1374                   /*
1375                   resetScanner();
1376                   yylloc = oldLocation;
1377                   fileInput = backFileInput;
1378                   if(fileInput)
1379                   {
1380                      fileInput.Seek(yylloc.start.pos, start);
1381                      resetScannerPos(&yylloc.start);
1382                      yychar = -2;
1383                   }
1384                   */
1385
1386                   //ProcessExpressionType(arg.expression);
1387                   //ComputeExpression(arg.expression);
1388                   PrintExpression(arg.expression, expString);
1389                   strcat(argument, expString);
1390                   thisClass = backupThisClass;
1391                   break;
1392                }
1393                case identifier:
1394                {
1395                   strcat(argument, arg.identifier.string);
1396                   break;
1397                }
1398                case type:
1399                {
1400                   char * typeString = StringFromSpecDecl(arg.templateDatatype.specifiers, arg.templateDatatype.decl);
1401                   strcat(argument, typeString);
1402                   delete typeString;
1403                   break;
1404                }
1405             }
1406             if(argument[0])
1407             {
1408                if(arg.prev) strcat(templateString, ", ");
1409                if(arg.name)
1410                {
1411                   strcat(templateString, arg.name.string);
1412                   strcat(templateString, " = ");
1413                }
1414                strcat(templateString, argument);
1415             }
1416          }
1417          {
1418             int len = strlen(templateString);
1419             if(templateString[len-1] == '>') templateString[len++] = ' ';
1420             templateString[len++] = '>';
1421             templateString[len++] = '\0';
1422          }
1423          // printf("SetClassTemplateArgs templateString: %s\n", templateString);
1424          symbol = FindClass(templateString);
1425          if(!symbol && spec.symbol)
1426          {
1427             // If class was only decl'ed, invoke DeclClass on this templated class as well
1428             symbol = _DeclClass(null, templateString);
1429             symbol.notYetDeclared = true;
1430          }
1431          // Add a reference to all templated class to the basic class
1432          if(spec.symbol)
1433             spec.symbol.templatedClasses.Add(OldLink { data = symbol });
1434          delete spec.name;
1435          spec.symbol = symbol;
1436          spec.name = CopyString(symbol ? symbol.string : templateString);
1437       }
1438    }
1439    else
1440       FreeList(templateArgs, FreeTemplateArgument);
1441 }
1442
1443 Specifier _MkSpecifierName(const char * name, Symbol symbol, OldList templateArgs)
1444 {
1445    Specifier spec { type = nameSpecifier };
1446
1447    if(name)
1448    {
1449       if(!symbol)
1450       {
1451          TemplatedType templatedType = FindTemplateTypeParameter(curContext, name);
1452          if(templatedType)
1453          {
1454             spec.templateParameter = templatedType.param;
1455             spec.type = templateTypeSpecifier;
1456             return spec;
1457          }
1458          else
1459             symbol = FindClass(name);
1460       }
1461       if(symbol && symbol.registered && symbol.registered.isRemote == 1)
1462       {
1463          char className[1024];
1464          strcpy(className, "DCOMClient_");
1465          if(!strncmp(name, className, strlen(className)))
1466             spec.name = CopyString(name);
1467          else
1468          {
1469             strcat(className, name);
1470             spec.name = CopyString(className);
1471          }
1472       }
1473       else if(symbol)
1474       {
1475          char nameSpace[1024];
1476          char * c = strstr(name, symbol.string);
1477          spec.name = CopyString(symbol.string);
1478          if(c && c >= name + 2 && c[-1] == ':' && c[-2] == ':')
1479          {
1480             if(c > name + 2)
1481             {
1482                memcpy(nameSpace, name, c - name - 2);
1483                nameSpace[c-name] = 0;
1484                spec.nsSpec = _MkSpecifierName(nameSpace, null, null);
1485             }
1486             else
1487                spec.nsSpec = _MkSpecifierName(null, null, null);
1488          }
1489       }
1490       else
1491          spec.name = CopyString(name);
1492       spec.symbol = symbol;
1493       if(templateArgs != null)
1494          SetClassTemplateArgs(spec, templateArgs);
1495    }
1496    return spec;
1497 }
1498
1499 public Specifier MkSpecifierName(const char * name)
1500 {
1501    return _MkSpecifierName(name, null, null);
1502 }
1503
1504 public Specifier MkSpecifierNameArgs(const char * name, OldList * templateArgs)
1505 {
1506    return _MkSpecifierName(name, null, templateArgs);
1507 }
1508
1509 /*
1510 Specifier MkClassName(const char * string)
1511 {
1512    return { type = SpecifierClass, name = CopyString(string) };
1513 }
1514 */
1515 ClassFunction MkClassFunction(OldList specifiers, Specifier _class, Declarator decl, OldList declList)
1516 {
1517    return { specifiers = specifiers, /*_class = _class,*/ declarator = decl, declarations = declList };
1518 }
1519
1520 void ProcessClassFunctionBody(ClassFunction func, Statement body)
1521 {
1522    Symbol symbol;
1523
1524    Declarator decl = func.declarator;
1525    //TESTING THIS
1526    //Declarator decl = GetFuncDecl(func.declarator);
1527    Declarator funcDecl = GetFuncDecl(func.declarator);
1528
1529    func.body = body;
1530
1531    if(decl && !decl.symbol)
1532    {
1533       OldList * symbolSpecs = MkList();
1534
1535       // WHAT WILL WE DO WITH THIS? Double instances?
1536       //if(decl.function.parameters && body)
1537       if(funcDecl && funcDecl.function.parameters && body)
1538       {
1539          Context context = body.compound.context;
1540          TypeName param;
1541          for(param = funcDecl.function.parameters->first; param; param = param.next)
1542          {
1543             if(param.declarator)
1544             {
1545                Symbol symbol = null;
1546                Identifier id = GetDeclId(param.declarator);
1547                char * string = id ? id.string : null;
1548                if(string)
1549                {
1550                   symbol = (Symbol)context.symbols.FindString(string);
1551                }
1552                // This parameter is not shadowed by a local declaration
1553                if(!symbol && id)
1554                {
1555                   symbol = Symbol
1556                   {
1557                      string = CopyString(id.string);
1558                      type = ProcessType(param.qualifiers, param.declarator);
1559                      isParam = true;
1560                   };
1561
1562                   if(!context.symbols.Add((BTNode)symbol))
1563                      excludedSymbols->Add(symbol);
1564
1565                   param.declarator.symbol = symbol;
1566                }
1567             }
1568          }
1569       }
1570       //////////////////////////////////
1571
1572       symbol = Symbol
1573       {
1574
1575       };
1576
1577       {
1578          Identifier id = GetDeclId(funcDecl);
1579          if(id)
1580          {
1581             int c;
1582             for(c = strlen(id.string)-1; c >= 0; c--)
1583             {
1584                if(id.string[c] == ':')
1585                {
1586                   char * string = CopyString(id.string + c + 1);
1587                   id.string[c - 1] = 0;
1588                   id._class = MkSpecifierName(id.string);
1589                   delete id.string;
1590                   id.string = string;
1591                   break;
1592                }
1593             }
1594             symbol.string = CopyString(id.string);
1595          }
1596       }
1597
1598       if(func.specifiers)
1599       {
1600          Specifier spec;
1601          for(spec = func.specifiers->first; spec; spec = spec.next)
1602             symbolSpecs->Add(CopySpecifier(spec));
1603       }
1604       symbol.type = ProcessType(symbolSpecs, decl);
1605       decl.symbol = symbol;
1606
1607       excludedSymbols->Add(symbol);
1608
1609       FreeList(symbolSpecs, FreeSpecifier);
1610    }
1611 }
1612
1613 OldList * MkSpecsClass(Specifier _class)
1614 {
1615    OldList * list = MkList();
1616    ListAdd(list, _class);
1617    return list;
1618 }
1619
1620 MemberInit MkMemberInit(OldList ids, Initializer initializer)
1621 {
1622    return { identifiers = ids, initializer = initializer };
1623 }
1624
1625 MemberInit MkMemberInitExp(Expression idExp, Initializer initializer)
1626 {
1627    MemberInit init { initializer = initializer, identifiers = MkList() };
1628    Expression exp;
1629
1630    for(exp = idExp; exp && exp.type == memberExp; exp = exp.member.exp)
1631    {
1632       init.identifiers->Insert(null, exp.member.member);
1633       exp.member.member = null;
1634    }
1635    if(exp && exp.type == identifierExp)
1636    {
1637       init.identifiers->Insert(null, exp.identifier);
1638       exp.identifier = null;
1639    }
1640    FreeExpression(idExp);
1641    return init;
1642 }
1643
1644 MembersInit MkMembersInitList(OldList dataMembers)
1645 {
1646    return { type = dataMembersInit, dataMembers = dataMembers };
1647 }
1648
1649 MembersInit MkMembersInitMethod(ClassFunction function)
1650 {
1651    return { type = methodMembersInit, function = function };
1652 }
1653
1654 Instantiation MkInstantiation(Specifier _class, Expression exp, OldList members)
1655 {
1656    return { _class = _class, exp = exp, members = members };
1657 }
1658
1659 Instantiation MkInstantiationNamed(OldList specs, Expression exp, OldList members)
1660 {
1661    Instantiation inst { exp = exp, members = members };
1662
1663    if(specs != null)
1664    {
1665       Specifier spec;
1666       for(spec = specs.first; spec; spec = spec.next)
1667          if(spec.type == nameSpecifier /*classSpecifier*/)
1668          {
1669             inst._class = spec;
1670             specs.Remove(spec);
1671             break;
1672          }
1673
1674       FreeList(specs, FreeSpecifier);
1675
1676       if(!spec)
1677       {
1678          Compiler_Error($"Expecting class specifier\n");
1679          inst._class = MkSpecifierName /*MkClassName*/("");
1680          //exit(1);
1681          //return null;
1682       }
1683    }
1684    return inst;
1685 }
1686
1687 ClassDef MkClassDefAccessOverride(AccessMode access, Identifier id)
1688 {
1689    return { type = accessOverrideClassDef, id = id, memberAccess = access };
1690 }
1691
1692 ClassDef MkClassDefMemberAccess()
1693 {
1694    return { type = memberAccessClassDef };
1695 }
1696
1697 ClassDef MkClassDefDeclaration(Declaration decl)
1698 {
1699    return { type = declarationClassDef, decl = decl };
1700 }
1701
1702 ClassDef MkClassDefClassData(Declaration decl)
1703 {
1704    return { type = classDataClassDef, decl = decl };
1705 }
1706
1707 ClassDef MkClassDefDesigner(const char * designer)
1708 {
1709    return { type = classDesignerClassDef, designer = CopyString(designer) };
1710 }
1711
1712 ClassDef MkClassDefNoExpansion()
1713 {
1714    return { type = classNoExpansionClassDef };
1715 }
1716
1717 ClassDef MkClassDefFixed()
1718 {
1719    return { type = classFixedClassDef };
1720 }
1721
1722 ClassDef MkClassDefDesignerDefaultProperty(Identifier id)
1723 {
1724    return { type = designerDefaultPropertyClassDef, defaultProperty = id };
1725 }
1726
1727 ClassDef MkClassDefDefaultProperty(OldList defProperties)
1728 {
1729    return { type = defaultPropertiesClassDef, defProperties = defProperties };
1730 }
1731
1732 ClassDef MkClassDefFunction(ClassFunction function)
1733 {
1734    ClassDef def { };
1735    if(function && function.declarator)
1736    {
1737       Declarator funcDecl = GetFuncDecl(function.declarator);
1738       if(funcDecl && funcDecl.declarator && funcDecl.declarator.type == bracketsDeclarator)
1739       {
1740          def.type = declarationClassDef;
1741          def.decl = MkStructDeclaration(function.specifiers, MkListOne(MkStructDeclarator(function.declarator, null)), null);
1742          function.declarator = null;
1743          function.specifiers = null;
1744          FreeClassFunction(function);
1745          return def;
1746       }
1747    }
1748    def.type = functionClassDef;
1749    def.function = function;
1750    return def;
1751 }
1752
1753 Symbol DeclClassAddNameSpace(Specifier _class, const char * className)
1754 {
1755    char name[1024];
1756    int len = 0, stringLen;
1757    name[0] = '\0';
1758    if(className[0] != ':' && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess && (!_class || _class.name))
1759    {
1760       if(defaultNameSpace)
1761       {
1762          memcpy(name, defaultNameSpace, defaultNameSpaceLen);
1763          len += defaultNameSpaceLen;
1764          name[len++] = ':';
1765          name[len++] = ':';
1766       }
1767       if(currentNameSpace)
1768       {
1769          memcpy(name + len, currentNameSpace, currentNameSpaceLen);
1770          len += currentNameSpaceLen;
1771          name[len++] = ':';
1772          name[len++] = ':';
1773       }
1774    }
1775    stringLen = strlen(className);
1776    memcpy(name + len, className, stringLen);
1777    len += stringLen;
1778    name[len] = 0;
1779    return _DeclClass(_class, name);
1780 }
1781
1782 Symbol DeclClass(Specifier _class, const char * name)
1783 {
1784    if(_class || strchr(name, ':'))
1785       return _DeclClass(_class, name);
1786    else
1787       return DeclClassAddNameSpace(_class, name);
1788 }
1789
1790 Symbol _DeclClass(Specifier _class, const char * name)
1791 {
1792    Symbol symbol;
1793    char nameBuffer[1024];
1794    if(_class)
1795    {
1796       strcpy(nameBuffer,  _class.name ? _class.name : "");
1797       strcat(nameBuffer, "::");
1798       strcat(nameBuffer, name);
1799       name = nameBuffer;
1800    }
1801
1802    symbol = FindClass(name);
1803    if(!symbol)
1804    {
1805       /*
1806       Context classContext;
1807       for(classContext = curContext; classContext && !classContext.classDef; classContext = classContext.parent);
1808       if(classContext)
1809       {
1810
1811       }
1812       */
1813       if(name[0] == ':' && name[1] == ':')
1814          name += 2;
1815       symbol = Symbol
1816       {
1817          string = CopyString(name);
1818          notYetDeclared = true;
1819       };
1820       if(!globalContext.classes.Add((BTNode)symbol))
1821          excludedSymbols->Add(symbol);
1822
1823       {
1824          int start = 0, c;
1825          char ch;
1826          for(c = 0; (ch = name[c]); c++)
1827          {
1828             if(ch == '.' || (ch == ':' && name[c+1] == ':'))
1829             {
1830                if(ch == ':') c++;
1831                start = c+1;
1832             }
1833          }
1834          if(start && c - start)
1835             symbol.shortName = CopyString(name + start);
1836       }
1837    }
1838    return symbol;
1839 }
1840
1841 void SetupBaseSpecs(Symbol symbol, OldList baseSpecs)
1842 {
1843    if(baseSpecs && baseSpecs.first && ((Specifier)baseSpecs.first).type == nameSpecifier)
1844    {
1845       char name[1024];
1846       Symbol baseClass;
1847       char * tpl;
1848       strcpy(name, ((Specifier)baseSpecs.first).name);
1849       tpl = strchr(name, '<');
1850       if(tpl) *tpl = 0;
1851
1852       baseClass = FindClass(name);
1853       if(baseClass && baseClass.ctx)
1854       {
1855          TemplatedType copy;
1856          for(copy = (TemplatedType)baseClass.ctx.templateTypes.first; copy; copy = (TemplatedType)copy.next)
1857          {
1858             TemplatedType type { key = copy.key, param = copy.param };
1859             if(!curContext.templateTypes.Add((BTNode)type))
1860                delete type;
1861          }
1862       }
1863       else if(baseClass && baseClass.registered)
1864       {
1865          Class sClass;
1866          for(sClass = baseClass.registered; sClass; sClass = sClass.base)
1867          {
1868             ClassTemplateParameter p;
1869             for(p = sClass.templateParams.first; p; p = p.next)
1870             {
1871                //OldList * specs = MkList();
1872                //Declarator decl = null;
1873                //decl = SpecDeclFromString(p.dataTypeString, specs, null);
1874                if(p.type == type)
1875                {
1876                   TemplateParameter param = p.param;
1877                   TemplatedType type;
1878                   if(!param)
1879                   {
1880                      p.param = param = TemplateParameter
1881                      {
1882                         identifier = MkIdentifier(p.name), type = p.type,
1883                         dataTypeString = p.dataTypeString /*, dataType = { specs, decl }*/
1884                      };
1885                   }
1886                   type = TemplatedType { key = (uintptr)p.name, param = param };
1887                   if(!curContext.templateTypes.Add((BTNode)type))
1888                      delete type;
1889                }
1890             }
1891          }
1892       }
1893    }
1894 }
1895
1896 ClassDefinition MkClass(Symbol symbol, OldList baseSpecs, OldList definitions)
1897 {
1898    ClassDefinition classDef;
1899    SetupBaseSpecs(symbol, baseSpecs);
1900    if(symbol.ctx)
1901    {
1902       ClassDefinition classDef = symbol.ctx.classDef;
1903       if(classDef)
1904       {
1905          // This can occur if two instances of a class are defined...
1906          // To avoid dangling 'parent' Contexts, we free the previous class definition
1907          External external;
1908          for(external = ast->first; external; external = external.next)
1909          {
1910             if(external.type == classExternal && external._class == classDef)
1911             {
1912                ast->Remove(external);
1913                FreeExternal(external);
1914                break;
1915             }
1916          }
1917       }
1918       FreeContext(symbol.ctx);
1919       delete symbol.ctx;
1920    }
1921    symbol.ctx = curContext;
1922    classDef = { symbol = symbol, _class = MkSpecifierName(symbol.string), baseSpecs = baseSpecs, definitions = definitions, nameLoc = symbol.nameLoc };
1923    curContext.classDef = classDef;
1924    return classDef;
1925 }
1926
1927 Expression MkExpInstance(Instantiation inst)
1928 {
1929    return { type = instanceExp, instance = inst };
1930 }
1931
1932 External MkExternalClass(ClassDefinition _class)
1933 {
1934    return { type = classExternal, _class = _class, symbol = _class.symbol };
1935 }
1936
1937 PropertyDef MkProperty(OldList specs, Declarator decl, Identifier id, Statement setStmt, Statement getStmt)
1938 {
1939    PropertyDef prop
1940    {
1941       specifiers = specs;
1942       declarator = decl;
1943       setStmt = setStmt;
1944       getStmt = getStmt;
1945    };
1946    Symbol symbol;
1947    Type type = ProcessType(specs, decl);
1948    if(!id)
1949    {
1950       char typeString[1024];
1951       typeString[0] = '\0';
1952       PrintTypeNoConst(type, typeString, false, true);
1953       id = MkIdentifier(typeString);
1954       prop.conversion = true;
1955    }
1956    prop.id = id;
1957
1958    symbol = Symbol
1959    {
1960       string = CopyString(id.string);
1961       type = type;
1962    };
1963    excludedSymbols->Add(symbol);
1964    prop.symbol = symbol;
1965    return prop;
1966 }
1967
1968 ClassDef MkClassDefProperty(PropertyDef propertyDef)
1969 {
1970    return { type = propertyClassDef, propertyDef = propertyDef, loc = yylloc };
1971 }
1972
1973 ClassDef MkClassDefClassProperty(PropertyDef propertyDef)
1974 {
1975    return { type = classPropertyClassDef, propertyDef = propertyDef, loc = yylloc };
1976 }
1977
1978 ClassDef MkClassDefClassPropertyValue(Identifier id, Initializer initializer)
1979 {
1980    return { type = classPropertyValueClassDef, id = id, initializer = initializer, loc = yylloc };
1981 }
1982
1983 int CheckType(const char * text)
1984 {
1985 #ifdef _TIMINGS
1986    Time startTime = GetTime();
1987 #endif
1988    if(FindTemplateTypeParameter(curContext, text))
1989    {
1990 #ifdef _TIMINGS
1991       checkTypeTotalTime += GetTime() - startTime;
1992 #endif
1993       return TYPE_NAME;
1994    }
1995    if(FindType(curContext, text))
1996    {
1997 #ifdef _TIMINGS
1998       checkTypeTotalTime += GetTime() - startTime;
1999 #endif
2000       return TYPE_NAME;
2001    }
2002    if(FindClass(text))
2003    {
2004 #ifdef _TIMINGS
2005       checkTypeTotalTime += GetTime() - startTime;
2006 #endif
2007       return TYPE_NAME; //CLASS_NAME;
2008    }
2009 #ifdef _TIMINGS
2010    checkTypeTotalTime += GetTime() - startTime;
2011 #endif
2012    return IDENTIFIER;
2013 }
2014
2015 int check_type()
2016 {
2017    return CheckType(yytext);
2018 }
2019
2020 Context PushContext()
2021 {
2022    Context ctx { parent = curContext };
2023    curContext = ctx;
2024    return ctx;
2025 }
2026
2027 void PopContext(Context ctx)
2028 {
2029    curContext = ctx.parent;
2030 }
2031
2032 Symbol FindType(Context ctx, const char * name)
2033 {
2034    Symbol type = null;
2035    if(ctx)
2036    {
2037       //char output[8192];
2038       type = (Symbol)ctx.types.FindString(name);
2039       /*if(!strcmp(name, "intptr_t") && !type)
2040       {
2041          ctx.types.Print(output, depthOrder);
2042          puts(output);
2043       }*/
2044       if(!type && ctx.parent)
2045          type = FindType(ctx.parent, name);
2046    }
2047    return type;
2048 }
2049
2050 Symbol FindStruct(Context ctx, const char * name)
2051 {
2052    Symbol type = null;
2053    if(ctx)
2054    {
2055       type = (Symbol)ctx.structSymbols.FindString(name);
2056       if(!type && ctx.parent)
2057          type = FindStruct(ctx.parent, name);
2058    }
2059    return type;
2060 }
2061
2062 TemplatedType FindTemplateTypeParameter(Context ctx, const char * name)
2063 {
2064    TemplatedType templatedType = null;
2065    if(curContext)
2066    {
2067       templatedType = (TemplatedType)ctx.templateTypes.FindString(name);
2068       if(!templatedType && ctx.parent)
2069          templatedType = FindTemplateTypeParameter(ctx.parent, name);
2070    }
2071    return templatedType;
2072 }
2073
2074 bool ModuleAccess(Module searchIn, Module searchFor)
2075 {
2076    SubModule subModule;
2077
2078    if(searchFor == searchIn)
2079       return true;
2080
2081    for(subModule = searchIn.modules.first; subModule; subModule = subModule.next)
2082    {
2083       if(subModule.importMode == publicAccess /*|| searchIn == searchIn.application*/)
2084       {
2085          if(ModuleAccess(subModule.module, searchFor))
2086             return true;
2087       }
2088    }
2089    return false;
2090 }
2091
2092 ModuleImport FindModule(Module moduleToFind)
2093 {
2094    ModuleImport module;
2095    if(!moduleToFind.name)
2096       return mainModule;
2097    for(module = imports->first; module; module = module.next)
2098       if(module.name && !strcmp(module.name, moduleToFind.name))
2099          break;
2100    if(!module)
2101    {
2102       module = ModuleImport
2103       {
2104          name = CopyString(moduleToFind.name), importType = moduleToFind.importType,
2105          importAccess = ModuleAccess(privateModule, moduleToFind) ? publicAccess : privateAccess
2106       };
2107       imports->Add(module);
2108    }
2109    return module;
2110 }
2111
2112 /*
2113 // TO REMOVE: OBSOLETE...
2114 static void GetFullClassNameSpace(NameSpace * ns, char * name)
2115 {
2116    if(ns->parent)
2117    {
2118       GetFullClassNameSpace(ns->parent, name);
2119       strcat(name, ns->name);
2120       strcat(name, "::");
2121    }
2122 }
2123
2124 static char * GetFullClassName(Class c, char * name)
2125 {
2126    NameSpace * nameSpace;
2127    name[0] = 0;
2128    GetFullClassNameSpace(c.nameSpace, name);
2129    strcat(name, c.name);
2130    return name;
2131 }
2132 */
2133
2134 public Symbol FindClass(const char * name)
2135 {
2136 #ifdef _TIMINGS
2137    Time startTime = GetTime();
2138 #endif
2139    Symbol cl = null;
2140    Class _class;
2141    bool global = false;
2142    char fullName[1024];
2143
2144    if(name[0] == ':' && name[1] == ':')
2145    {
2146       global = true;
2147       name += 2;
2148    }
2149
2150    if(!global && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
2151    {
2152       int len = 0, stringLen;
2153       if(defaultNameSpace)
2154       {
2155          memcpy(fullName, defaultNameSpace, defaultNameSpaceLen);
2156          len += defaultNameSpaceLen;
2157          fullName[len++] = ':';
2158          fullName[len++] = ':';
2159       }
2160       if(currentNameSpace)
2161       {
2162          memcpy(fullName + len, currentNameSpace, currentNameSpaceLen);
2163          len += currentNameSpaceLen;
2164          fullName[len++] = ':';
2165          fullName[len++] = ':';
2166       }
2167       stringLen = strlen(name);
2168       memcpy(fullName + len, name, stringLen);
2169       len += stringLen;
2170       fullName[len] = 0;
2171       cl = globalContext ? (Symbol)globalContext.classes.FindString(fullName) : null;
2172    }
2173
2174    if(!cl)
2175       cl = globalContext ? (Symbol)globalContext.classes.FindString(name) : null;
2176
2177    if(!cl && !global)
2178    {
2179 #ifdef _TIMINGS
2180       Time startTime = GetTime();
2181 #endif
2182       // Ignore name space name when searching
2183       for(cl = globalContext ? (Symbol)globalContext.classes.first : null; cl; cl = (Symbol)((BTNode)cl).next)
2184       {
2185          /*
2186          int start = 0, c;
2187          char * string = cl.string;
2188          char ch;
2189          for(c = 0; (ch = string[c]); c++)
2190          {
2191             if(ch == '.' || (ch == ':' && string[c+1] == ':'))
2192             {
2193                if(ch == ':') c++;
2194                start = c+1;
2195             }
2196          }
2197          if(start && c - start)
2198          {
2199             if(!strcmp(string + start, name))
2200                break;
2201          }
2202          */
2203          if(cl.shortName && !strcmp(cl.shortName, name))
2204             break;
2205       }
2206 #ifdef _TIMINGS
2207       findClassIgnoreNSTotalTime += GetTime() - startTime;
2208 #endif
2209    }
2210    if(!cl)
2211    {
2212       _class = null;
2213       if(!global && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
2214          _class = eSystem_FindClass(privateModule, fullName);
2215       if(!_class)
2216          _class = eSystem_FindClass(privateModule, name);
2217
2218       if(_class)
2219       {
2220          name = _class.fullName;
2221
2222          cl = (Symbol)globalContext.classes.FindString(name);
2223          if(!cl)
2224          {
2225             cl = Symbol
2226             {
2227                string = CopyString(name);
2228                registered = _class;
2229                notYetDeclared = true;
2230                imported = true;
2231             };
2232             _class.symbol = cl;
2233             if(_class.module)
2234                cl.module = FindModule(_class.module);
2235             else
2236                cl.module = mainModule;
2237             if(!globalContext.classes.Add((BTNode)cl))
2238                excludedSymbols->Add(cl);
2239             if(strcmp(name, _class.name))
2240                cl.shortName = CopyString(_class.name);
2241          }
2242       }
2243    }
2244 #ifdef _TIMINGS
2245    findClassTotalTime += GetTime() - startTime;
2246 #endif
2247    return cl;
2248 }
2249
2250 void CopyTypeInto(Type type, Type src)
2251 {
2252    type = *src;
2253
2254    type.name = CopyString(src.name);
2255    type.typeName = CopyString(src.typeName);
2256    type.refCount = 1;
2257
2258    if(src.kind == enumType)
2259    {
2260       NamedLink64 member;
2261
2262       type.members.Clear();
2263       // This must have been a mistake: member = **type**.members.first
2264       for(member = src.members.first; member; member = member.next)
2265       {
2266          type.members.Add(NamedLink64 { name = CopyString(member.name), data = member.data });
2267       }
2268       type.enumName = CopyString(src.enumName);
2269    }
2270    else if(src.kind == structType || src.kind == unionType)
2271    {
2272       Type member;
2273       // Tricky stuff... will be removed from list only when ref count reaches 0
2274       for(member = type.members.first; member; member = member.next)
2275          member.refCount++;
2276       type.enumName = CopyString(src.enumName);
2277    }
2278    else if(src.kind == functionType)
2279    {
2280       Type param;
2281       type.returnType.refCount++;
2282       for(param = type.params.first; param; param = param.next)
2283          param.refCount++;
2284    }
2285    else if(src.kind == pointerType || src.kind == arrayType)
2286    {
2287       type.type.refCount++;
2288       if(src.kind == arrayType)
2289       {
2290          if(type.arraySizeExp)
2291             type.arraySizeExp = CopyExpression(type.arraySizeExp);
2292       }
2293    }
2294 }
2295
2296 static Type ProcessTypeSpecs(OldList specs, bool assumeEllipsis, bool keepTypeName)
2297 {
2298    Type specType { refCount = 1, kind = intType, isSigned = true };
2299    if(specs != null)
2300    {
2301       bool isTypedef = false;
2302       Specifier spec;
2303       bool isLong = false;
2304       for(spec = specs.first; spec; spec = spec.next)
2305       {
2306          if(spec.type == extendedSpecifier)
2307          {
2308             ExtDecl extDecl = spec.extDecl;
2309             if(extDecl.type == extDeclString)
2310             {
2311                if(!strcmp(spec.extDecl.s, "__declspec(dllexport)") || !strcmp(spec.extDecl.s, "dllexport"))
2312                   specType.dllExport = true;
2313                else if(!strcmp(spec.extDecl.s, "__declspec(stdcall)") || !strcmp(spec.extDecl.s, "stdcall"))
2314                   specType.attrStdcall = true;
2315             }
2316             else if(extDecl.type == extDeclAttrib)
2317             {
2318                OldList * attribs = extDecl.attr.attribs;
2319                if(attribs)
2320                {
2321                   Attribute attr;
2322                   for(attr = attribs->first; attr; attr = attr.next)
2323                   {
2324                      String s = attr.attr;
2325                      if(s)
2326                      {
2327                         if(!strcmp(s, "dllexport"))
2328                            specType.dllExport = true;
2329                         else if(!strcmp(s, "stdcall"))
2330                            specType.attrStdcall = true;
2331                      }
2332                   }
2333                }
2334                specType.keepCast = true;
2335             }
2336          }
2337
2338          if(spec.specifier != CONST && (specType.kind == structType || specType.kind == unionType))
2339          {
2340             FreeType(specType);
2341             specType = { kind = intType, isSigned = true, refCount = 1 };
2342          }
2343
2344          if(isTypedef && keepTypeName)
2345          {
2346             specType.kind = dummyType;
2347             return specType;
2348          }
2349          else if(spec.type == baseSpecifier)
2350          {
2351             if(spec.specifier == TYPEDEF)
2352                isTypedef = true;
2353             else if(spec.specifier == VOID) specType.kind = voidType;
2354             else if(spec.specifier == CHAR) specType.kind = charType;
2355             else if(spec.specifier == INT) { if(specType.kind != shortType && specType.kind != longType && !isLong) specType.kind = intType; }
2356             else if(spec.specifier == _BOOL || spec.specifier == BOOL)
2357                specType.kind = _BoolType;
2358             else if(spec.specifier == UINT) { if(specType.kind != shortType && specType.kind != longType) specType.kind = intType; specType.isSigned = false; }
2359             else if(spec.specifier == INT64) specType.kind = int64Type;
2360             else if(spec.specifier == VALIST)
2361                specType.kind = vaListType;
2362             else if(spec.specifier == SHORT) specType.kind = shortType;
2363             else if(spec.specifier == LONG)
2364             {
2365                if(isLong || (targetBits == 64 && targetPlatform != win32))
2366                   specType.kind = int64Type;
2367                else
2368                   specType.kind = intType;
2369                specType.isLong = true;
2370                isLong = true;
2371             }
2372             else if(spec.specifier == FLOAT) specType.kind = floatType;
2373             else if(spec.specifier == DOUBLE) specType.kind = doubleType;
2374             else if(spec.specifier == SIGNED) specType.isSigned = true;
2375             else if(spec.specifier == UNSIGNED) specType.isSigned = false;
2376             else if(spec.specifier == CONST)
2377                specType.constant = true;
2378             else if(spec.specifier == TYPED_OBJECT || spec.specifier == ANY_OBJECT || spec.specifier == CLASS)
2379             {
2380                switch(spec.specifier)
2381                {
2382                   case TYPED_OBJECT:   specType.classObjectType = typedObject;   break;
2383                   case ANY_OBJECT:     specType.classObjectType = anyObject;     break;
2384                   case CLASS:          specType.classObjectType = classPointer;  break;
2385                }
2386                specType.kind = classType;
2387                specType._class = FindClass("class");
2388             }
2389             else if(spec.specifier == THISCLASS)
2390                specType.kind = thisClassType;
2391          }
2392          else if(spec.type == nameSpecifier)
2393          {
2394             if(spec.name && (!strcmp(spec.name, "intptr") || !strcmp(spec.name, "uintptr")))
2395             {
2396                specType.kind = intPtrType;
2397                if(!strcmp(spec.name, "uintptr"))
2398                   specType.isSigned = false;
2399             }
2400             else if(spec.name && (!strcmp(spec.name, "uintsize") || !strcmp(spec.name, "intsize")))
2401             {
2402                specType.kind = intSizeType;
2403                if(!strcmp(spec.name, "uintsize"))
2404                   specType.isSigned = false;
2405             }
2406             else
2407             {
2408                Symbol symbol = spec.name ? FindType(curContext, spec.name) : null;
2409                if(symbol && symbol.type)
2410                {
2411                   // Keep constant qualifier
2412                   bool isConstant = specType.constant;
2413                   // Free Type Contents:
2414                   Type dummy { };
2415                   *dummy = *specType;
2416                   FreeType(dummy);
2417
2418                   CopyTypeInto(specType, symbol.type);
2419                   specType.constant = isConstant;
2420                   delete specType.typeName;
2421                   specType.typeName = CopyString(symbol.type.name);
2422                }
2423                else if(!isTypedef) // !specType.kind)    // TESTING THIS FOR enum / typedef problem
2424                {
2425                   // key.sym enum values need FindClass:
2426                   specType._class = spec.name ? FindClass(spec.name) : null;
2427                   specType.kind = classType;
2428                   if(!specType._class)
2429                      specType.kind = intType;
2430                }
2431             }
2432          }
2433          else if(spec.type == enumSpecifier)
2434          {
2435             specType.kind = enumType;
2436             specType.enumName = spec.id ? CopyString(spec.id.string) : null;
2437
2438             if(spec.list)
2439             {
2440                Enumerator e;
2441                for(e = spec.list->first; e; e = e.next)
2442                {
2443                   NamedLink64 i { name = CopyString(e.id.string) };
2444                   if(e.exp && e.exp.type == constantExp && e.exp.constant)
2445                      i.data = strtoll(e.exp.constant, null, 0);
2446                   specType.members.Add(i);
2447                }
2448             }
2449          }
2450          else if(spec.type == templateTypeSpecifier)
2451          {
2452             specType.kind = templateType;
2453             specType.templateParameter = spec.templateParameter;
2454          }
2455          else if(spec.type == structSpecifier || spec.type == unionSpecifier)
2456          {
2457             Symbol _class = spec.id ? FindClass(spec.id.string) : null;
2458             if(_class)
2459             {
2460                specType.declaredWithStruct = true;
2461                if(!_class.registered || _class.registered.type != structClass)
2462                   specType.directClassAccess = true;     // TODO: Need to clarify what 'directClassAccess' is about
2463                specType._class = _class;
2464                specType.kind = classType;
2465                break;
2466             }
2467             specType.members.Clear();
2468             if(spec.type == structSpecifier)
2469                specType.kind = structType;
2470             else if(spec.type == unionSpecifier)
2471                specType.kind = unionType;
2472             if(spec.id)
2473             {
2474                // TESTING THIS HERE... Had 0 type size
2475                if(!spec.definitions && !isTypedef)
2476                {
2477                   Symbol symbol = spec.id.string ? FindSymbol(spec.id.string, curContext, globalContext, true, false) : null;
2478                   if(symbol && symbol.type)
2479                   {
2480                      specType = *symbol.type;
2481                      specType.name = CopyString(symbol.type.name);
2482                      specType.typeName = CopyString(spec.name);
2483                      specType.enumName = CopyString(symbol.type.enumName);
2484                      specType.refCount = 1;
2485
2486                      if(symbol.type.kind == enumType)
2487                      {
2488                         NamedLink64 member;
2489
2490                         specType.members.Clear();
2491                         for(member = symbol.type.members.first; member; member = member.next)
2492                         {
2493                            NamedLink64 item { name = CopyString(member.name), data = member.data };
2494                            specType.members.Add(item);
2495                         }
2496                      }
2497                      else if(symbol.type.kind == structType || symbol.type.kind == unionType)
2498                      {
2499                         Type member;
2500                         // Tricky stuff... will be removed from list only when ref count reaches 0
2501                         for(member = specType.members.first; member; member = member.next)
2502                            member.refCount++;
2503                      }
2504                      else if(symbol.type.kind == functionType)
2505                      {
2506                         Type param;
2507                         specType.returnType.refCount++;
2508                         for(param = specType.params.first; param; param = param.next)
2509                            param.refCount++;
2510                      }
2511                      else if(symbol.type.kind == pointerType || symbol.type.kind == arrayType)
2512                      {
2513                         specType.type.refCount++;
2514                         if(symbol.type.kind == arrayType)
2515                         {
2516                            if(specType.arraySizeExp)
2517                               specType.arraySizeExp = CopyExpression(specType.arraySizeExp);
2518                         }
2519
2520                      }
2521                   }
2522                   else
2523                      specType.enumName = CopyString(spec.id.string);
2524                }
2525                else
2526                   specType.enumName = CopyString(spec.id.string);
2527             }
2528
2529             if(spec.definitions)
2530             {
2531                ClassDef def;
2532                for(def = spec.definitions->first; def; def = def.next)
2533                {
2534                   if(def.type == declarationClassDef && def.decl.type == structDeclaration)
2535                   {
2536                      Declaration decl = def.decl;
2537                      if(decl.declarators)
2538                      {
2539                         Declarator d;
2540                         for(d = decl.declarators->first; d; d = d.next)
2541                         {
2542                            Type memberType = ProcessType(decl.specifiers, d);
2543                            specType.members.Add(memberType);
2544                         }
2545                      }
2546                      else if(decl.specifiers)
2547                      {
2548                         Type memberType = ProcessType(decl.specifiers, null);
2549                         specType.members.Add(memberType);
2550                      }
2551                   }
2552                }
2553             }
2554             break;
2555          }
2556          else if(spec.type == subClassSpecifier)
2557          {
2558             specType.kind = subClassType;
2559             specType._class = spec._class.symbol;
2560          }
2561       }
2562    }
2563    else if(assumeEllipsis)
2564       specType.kind = ellipsisType;
2565    return specType;
2566 }
2567
2568 static Type ProcessTypeDecls(OldList specs, Declarator decl, Type parentType)
2569 {
2570    Type type = parentType;
2571    Declarator subDecl = decl ? decl.declarator : null;
2572    if(!parentType)
2573       type = ProcessTypeSpecs(specs, decl == null, (decl && decl.type == extendedDeclaratorEnd) ? true : false);
2574    if(decl)
2575    {
2576       switch(decl.type)
2577       {
2578          case bracketsDeclarator: break;
2579          case extendedDeclarator:
2580          case extendedDeclaratorEnd:
2581          {
2582             ExtDecl extDecl = decl.extended.extended;
2583             if(extDecl)
2584             {
2585                switch(extDecl.type)
2586                {
2587                   case extDeclString:
2588                   {
2589                      String s = extDecl.s;
2590                      if(s)
2591                      {
2592                         if(!strcmp(s, "__declspec(dllexport)") || !strcmp(s, "dllexport"))
2593                            type.dllExport = true;
2594                         else if(!strcmp(s, "__declspec(stdcall)") || !strcmp(s, "stdcall"))
2595                            type.attrStdcall = true;
2596                      }
2597                      break;
2598                   }
2599                   case extDeclAttrib:
2600                   {
2601                      OldList * attribs = extDecl.attr.attribs;
2602                      if(attribs)
2603                      {
2604                         Attribute attr;
2605                         for(attr = attribs->first; attr; attr = attr.next)
2606                         {
2607                            String s = attr.attr;
2608                            if(s)
2609                            {
2610                               if(!strcmp(s, "dllexport"))
2611                                  type.dllExport = true;
2612                               else if(!strcmp(s, "stdcall"))
2613                                  type.attrStdcall = true;
2614                            }
2615                         }
2616                      }
2617                      type.keepCast = true;
2618                      break;
2619                   }
2620                }
2621             }
2622             break;
2623          }
2624          case structDeclarator:
2625          {
2626             Expression exp = decl.structDecl.exp;
2627             if(exp)
2628             {
2629                ProcessExpressionType(exp);
2630                ComputeExpression(exp);
2631                if(exp.type == constantExp)
2632                   type.bitFieldCount = (uint)strtoul(exp.constant, null, 0);
2633             }
2634             break;
2635          }
2636          case functionDeclarator:
2637          {
2638             type = { refCount = 1, kind = functionType, returnType = type, dllExport = type.dllExport, attrStdcall = type.attrStdcall };
2639             if(decl.function.parameters)
2640             {
2641                TypeName param;
2642                for(param = decl.function.parameters->first; param; param = param.next)
2643                   type.params.Add(ProcessType(param.qualifiers, param.declarator));
2644             }
2645             break;
2646          }
2647          case arrayDeclarator:
2648          {
2649             type = { refCount = 1, kind = arrayType, arraySizeExp = CopyExpression(decl.array.exp), freeExp = true, type = type, dllExport = type.dllExport, attrStdcall = type.attrStdcall };
2650             if(decl.array.enumClass)
2651                type.enumClass = decl.array.enumClass.symbol;
2652             break;
2653          }
2654          case pointerDeclarator:
2655          {
2656             Pointer pointer = decl.pointer.pointer;
2657             while(pointer)
2658             {
2659                OldList * qualifiers = pointer.qualifiers;
2660                if(type.classObjectType)
2661                   type.byReference = true;
2662                else
2663                   type = { refCount = 1, kind = pointerType, type = type, dllExport = type.dllExport, attrStdcall = type.attrStdcall };
2664                if(qualifiers)
2665                {
2666                   Specifier spec;
2667                   for(spec = qualifiers->first; spec; spec = spec.next)
2668                   {
2669                      if(spec.type == baseSpecifier && spec.specifier == CONST)
2670                         type.constant = true;
2671                   }
2672                }
2673                pointer = pointer.pointer;
2674             }
2675             break;
2676          }
2677          case identifierDeclarator:
2678          {
2679             Identifier id = decl.identifier;
2680             Specifier _class = id._class;
2681             delete type.name;
2682             type.name = CopyString(id.string);
2683             if(_class)
2684             {
2685                if(_class.type == templateTypeSpecifier)
2686                {
2687                   type.thisClassTemplate = _class.templateParameter;
2688                   type.extraParam = true;
2689                }
2690                else
2691                {
2692                   String name = _class.name;
2693                   if(!name)
2694                      type.staticMethod = true;
2695                   else
2696                   {
2697                      if(!id.classSym)
2698                         id.classSym = _class.symbol; // FindClass(_class.name);
2699                      /* TODO: Name Space Fix ups
2700                         id.nameSpace = eSystem_FindNameSpace(privateModule, _class.name);
2701                      */
2702
2703                      if(name[strlen(name)-1] == '&')
2704                      {
2705                         type.thisClass = FindClass("class");
2706                         type.byReference = true;
2707                      }
2708                      else
2709                         type.thisClass = _class.symbol;
2710
2711                      if(type.thisClass && strcmp(type.thisClass.string, "class"))
2712                         type.extraParam = true;
2713                      else if(!strcmp(name, "any_object"))
2714                      {
2715                         type.extraParam = true;
2716                         type.thisClass = FindClass("class");
2717                      }
2718                      else if(!strcmp(name, "class"))
2719                      {
2720                         type.thisClass = FindClass("class");
2721                         type.classObjectType = classPointer;   // This is used for class properties
2722                      }
2723                      else if(!strcmp(name, "typed_object") || !strcmp(name, "typed_object&"))
2724                      {
2725                         type.thisClass = FindClass("class");
2726                         type.classObjectType = typedObject;
2727                      }
2728                   }
2729                }
2730             }
2731             break;
2732          }
2733          default:
2734             PrintLn("Unhandled Declarator Type: ", decl.type);
2735       }
2736    }
2737    if(subDecl)
2738    {
2739       Type curType = type;
2740       type = ProcessTypeDecls(null, subDecl, type);
2741       if(curType && type.kind != functionType)
2742       {
2743          curType.thisClassTemplate = type.thisClassTemplate;
2744          curType.extraParam = type.extraParam;
2745          curType.staticMethod = type.staticMethod;
2746          curType.thisClass = type.thisClass;
2747          curType.byReference = type.byReference;
2748          curType.classObjectType = type.classObjectType;
2749       }
2750    }
2751    return type;
2752 }
2753
2754 public Type ProcessType(OldList specs, Declarator decl)
2755 {
2756    return ProcessTypeDecls(specs, decl, null);
2757 }
2758
2759 public Type ProcessTypeString(const char * string, bool staticMethod)
2760 {
2761    OldList * specs = MkList();
2762    Declarator decl = SpecDeclFromString(string, specs, null);
2763    Type type = ProcessType(specs, decl);
2764    if(type && !type.thisClass && staticMethod) type.staticMethod = true;
2765    FreeList(specs, FreeSpecifier);
2766    if(decl) FreeDeclarator(decl);
2767    return type;
2768 }
2769
2770 Type MkClassTypeSymbol(Symbol symbol)
2771 {
2772    if(symbol)
2773    {
2774       Type type { kind = classType, _class = symbol };
2775       if(!type._class)
2776       {
2777          // Defaults to an int instead...
2778          type.kind = intType;
2779       }
2780       type.refCount = 1;
2781       return type;
2782    }
2783    return null;
2784 }
2785
2786 public Type MkClassType(const char * name)
2787 {
2788    if(name)
2789    {
2790       Type type { kind = classType, _class = FindClass(name) };
2791       if(!type._class)
2792       {
2793          // Defaults to an int instead...
2794          type.kind = intType;
2795       }
2796       type.refCount = 1;
2797       return type;
2798    }
2799    return null;
2800 }
2801
2802 AsmField MkAsmField(char * command, Expression expression, Identifier symbolic)
2803 {
2804    return { command = command, expression = expression, symbolic = symbolic };
2805 }
2806
2807 Statement MkAsmStmt(Specifier spec, char * statements, OldList inputFields, OldList outputFields, OldList clobberedFields)
2808 {
2809    return { type = asmStmt, asmStmt.spec = spec, asmStmt.statements = statements,
2810       asmStmt.inputFields = inputFields, asmStmt.outputFields = outputFields,
2811       asmStmt.clobberedFields = clobberedFields };
2812 }
2813
2814 ClassDef MkClassDefPropertyWatch(PropertyWatch watcher)
2815 {
2816    return { type = propertyWatchClassDef, propertyWatch = watcher };
2817 }
2818
2819 Statement MkFireWatchersStmt(Expression object, OldList watches)
2820 {
2821    return { type = fireWatchersStmt, _watch.object = object, _watch.watches = watches };
2822 }
2823
2824 Statement MkStopWatchingStmt(Expression watcher, Expression object, OldList watches)
2825 {
2826    return { type = stopWatchingStmt, _watch.watcher = watcher, _watch.object = object, _watch.watches = watches };
2827 }
2828
2829 Statement MkWatchStmt(Expression watcher, Expression object, OldList watches)
2830 {
2831    return { type = watchStmt, _watch.watcher = watcher, _watch.object = object, _watch.watches = watches };
2832 }
2833
2834 PropertyWatch MkDeleteWatch(Statement compound)
2835 {
2836    return { compound = compound, deleteWatch = true };
2837 }
2838
2839 PropertyWatch MkPropertyWatch(OldList properties, Statement compound)
2840 {
2841    return { compound = compound, properties = properties };
2842 }
2843
2844 Expression MkExpClass(OldList * specifiers, Declarator decl)
2845 {
2846    return { type = classExp, _classExp.specifiers = specifiers, _classExp.decl = decl };
2847 }
2848
2849 Expression MkExpClassData(Identifier id)
2850 {
2851    return { type = classDataExp, classData.id = id };
2852 }
2853
2854
2855 External MkExternalDBTable(DBTableDef table)
2856 {
2857    return { type = dbtableExternal, table = table };
2858 }
2859
2860 DBTableDef MkDBTableDef(char * name, Symbol symbol, OldList * definitions)
2861 {
2862    return { name = name, symbol = symbol, definitions = definitions };
2863 }
2864
2865 DBTableEntry MkDBFieldEntry(TypeName type, Identifier id, char * name)
2866 {
2867    return { type = fieldEntry, dataType = type, id = id, name = name };
2868 }
2869
2870 DBIndexItem MkDBIndexItem(Identifier id, Order order)
2871 {
2872    return { id = id, order = order };
2873 }
2874
2875 DBTableEntry MkDBIndexEntry(OldList * items, Identifier id)
2876 {
2877    return { type = indexEntry, items = items, id = id };
2878 }
2879
2880 Expression MkExpDBOpen(Expression ds, Expression dbName)
2881 {
2882    return { type = dbopenExp, dbopen.ds = ds, dbopen.name = dbName };
2883 }
2884
2885 Expression MkExpDBField(char * table, Identifier id)
2886 {
2887    return { type = dbfieldExp, db.table = table, db.id = id };
2888 }
2889
2890 Expression MkExpDBIndex(char * table, Identifier id)
2891 {
2892    return { type = dbindexExp, db.table = table, db.id = id };
2893 }
2894
2895 Expression MkExpDBTable(char * table)
2896 {
2897    return { type = dbtableExp, db.table = table };
2898 }
2899
2900 Expression MkExpArray(OldList * expressions)
2901 {
2902    return { type = arrayExp, list = expressions };
2903 }
2904
2905 Expression GetTemplateArgExpByName(const char * paramName, Class curClass, TemplateParameterType tplType)
2906 {
2907    Expression argExp = null;
2908    Class _class = curClass ? curClass : ((curExternal && curExternal.type == functionExternal && curExternal.function) ? curExternal.function._class : null);
2909    if(_class)
2910    {
2911       int id = 0;
2912       ClassTemplateParameter curParam;
2913       Class sClass;
2914       for(sClass = _class; sClass; sClass = sClass.base)
2915       {
2916          id = 0;
2917          for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
2918          {
2919             if(!strcmp(curParam.name, paramName))
2920             {
2921                for(sClass = sClass.base; sClass; sClass = sClass.base)
2922                   id += sClass.templateParams.count;
2923                break;
2924             }
2925             id++;
2926          }
2927          if(curParam) break;
2928       }
2929
2930       if(curParam && curParam.type != tplType)
2931          curParam = null;
2932
2933       if(curParam)
2934       {
2935          char idString[32];
2936          char className[1024];
2937
2938          sprintf(idString, "%d", id);
2939          strcpy(className, "__ecereClass_");
2940          FullClassNameCat(className, _class.fullName, true);
2941          DeclareClass(curExternal, FindClass(_class.fullName), className);
2942
2943          argExp = MkExpIndex((/*pointer ? MkExpPointer : */MkExpMember)
2944                (MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class")) /*MkExpIdentifier(MkIdentifier(className))*/,
2945                MkIdentifier("templateArgs")), MkListOne(MkExpConstant(idString)));
2946       }
2947    }
2948    return argExp;
2949 }
2950
2951 Expression GetTemplateArgExp(TemplateParameter param, Class curClass, bool pointer)
2952 {
2953    return param.identifier ? GetTemplateArgExpByName(param.identifier.string, curClass, type) : null;
2954 }
2955
2956 /*char * CreateMsgID(const char * string, const char * context)
2957 {
2958    int lenString = strlen(string), lenContext = strlen(context);
2959    char * msgid = new char[lenString + lenContext + 20];
2960    memcpy(msgid, string, lenString);
2961    memcpy(msgid+lenString, " [msgctxt: ", 11);
2962    memcpy(msgid+lenString+11, context, lenContext);
2963    memcpy(msgid+lenString+11+lenContext, "]", 2);
2964    return msgid;
2965 }*/
2966
2967 public void OutputIntlStrings()
2968 {
2969    if(intlStrings.count)
2970    {
2971       const char * srcFile = GetSourceFile();
2972       const char * objFile = GetOutputFile();
2973       char srcFileFixed[MAX_LOCATION];
2974       char potFile[MAX_LOCATION];
2975       File f;
2976       ChangeExtension(objFile, "bowl", potFile);
2977       f = FileOpen(potFile, write);
2978       if(f)
2979       {
2980          const char * filePrefix = "";
2981          if(!(srcFile[0] && (srcFile[1] == ':' || srcFile[0] == '/')))
2982             filePrefix = "./"; //(__runtimePlatform == win32) ? ".\\" : "./";
2983          // GetSystemPathBuffer(srcFileFixed, srcFile);
2984          GetSlashPathBuffer(srcFileFixed, srcFile);
2985
2986          for(s : intlStrings)
2987          {
2988             // TOFIX: (#654) ContextStringPair * pair = &s;
2989             ContextStringPair pair = &s;
2990             for(l : s)
2991                f.Printf("#: %s%s:%d\n", filePrefix, srcFileFixed, l.start.line);
2992              // PoEdit now preserves and distinguish msgctxt
2993             if(pair.context)
2994                f.Printf("msgctxt \"%s\"\n", pair.context);
2995             f.Printf("msgid \"%s\"\n", pair.string);
2996             f.Printf("msgstr \"%s\"\n\n", pair.string);
2997          }
2998          delete f;
2999       }
3000       intlStrings.Free();
3001    }
3002 }
3003
3004 default extern OldList * ast;
3005 default extern int yyparse ();
3006 default extern int yylex ();
3007
3008 public void SetAST(OldList * list) { ast = list; }
3009 public OldList * GetAST() { return ast; }
3010 public void ParseEc()
3011 {
3012    yyparse();
3013 }
3014
3015 public int LexEc()
3016 {
3017    return yylex();
3018 }
3019
3020 public const char * GetYYText()
3021 {
3022    return yytext;
3023 }