9b56913e3ac84f5d2708cbcd35183a941a556e16
[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
1989    if(inIDE)
1990    {
1991       // Help out the Debugger with Windows files until we improve the parser
1992       if(!strcmp(text, "WINAPI"))
1993          return EXT_DECL;
1994       else if(!strcmp(text, "BOOL") || !strcmp(text, "WINUSERAPI"))
1995          return TYPE_NAME;
1996    }
1997
1998    if(FindTemplateTypeParameter(curContext, text))
1999    {
2000 #ifdef _TIMINGS
2001       checkTypeTotalTime += GetTime() - startTime;
2002 #endif
2003       return TYPE_NAME;
2004    }
2005    if(FindType(curContext, text))
2006    {
2007 #ifdef _TIMINGS
2008       checkTypeTotalTime += GetTime() - startTime;
2009 #endif
2010       return TYPE_NAME;
2011    }
2012    if(FindClass(text))
2013    {
2014 #ifdef _TIMINGS
2015       checkTypeTotalTime += GetTime() - startTime;
2016 #endif
2017       return TYPE_NAME; //CLASS_NAME;
2018    }
2019 #ifdef _TIMINGS
2020    checkTypeTotalTime += GetTime() - startTime;
2021 #endif
2022    return IDENTIFIER;
2023 }
2024
2025 int check_type()
2026 {
2027    return CheckType(yytext);
2028 }
2029
2030 Context PushContext()
2031 {
2032    Context ctx { parent = curContext };
2033    curContext = ctx;
2034    return ctx;
2035 }
2036
2037 void PopContext(Context ctx)
2038 {
2039    curContext = ctx.parent;
2040 }
2041
2042 Symbol FindType(Context ctx, const char * name)
2043 {
2044    Symbol type = null;
2045    if(ctx)
2046    {
2047       //char output[8192];
2048       type = (Symbol)ctx.types.FindString(name);
2049       /*if(!strcmp(name, "intptr_t") && !type)
2050       {
2051          ctx.types.Print(output, depthOrder);
2052          puts(output);
2053       }*/
2054       if(!type && ctx.parent)
2055          type = FindType(ctx.parent, name);
2056    }
2057    return type;
2058 }
2059
2060 Symbol FindStruct(Context ctx, const char * name)
2061 {
2062    Symbol type = null;
2063    if(ctx)
2064    {
2065       type = (Symbol)ctx.structSymbols.FindString(name);
2066       if(!type && ctx.parent)
2067          type = FindStruct(ctx.parent, name);
2068    }
2069    return type;
2070 }
2071
2072 TemplatedType FindTemplateTypeParameter(Context ctx, const char * name)
2073 {
2074    TemplatedType templatedType = null;
2075    if(curContext)
2076    {
2077       templatedType = (TemplatedType)ctx.templateTypes.FindString(name);
2078       if(!templatedType && ctx.parent)
2079          templatedType = FindTemplateTypeParameter(ctx.parent, name);
2080    }
2081    return templatedType;
2082 }
2083
2084 bool ModuleAccess(Module searchIn, Module searchFor)
2085 {
2086    SubModule subModule;
2087
2088    if(searchFor == searchIn)
2089       return true;
2090
2091    for(subModule = searchIn.modules.first; subModule; subModule = subModule.next)
2092    {
2093       if(subModule.importMode == publicAccess /*|| searchIn == searchIn.application*/)
2094       {
2095          if(ModuleAccess(subModule.module, searchFor))
2096             return true;
2097       }
2098    }
2099    return false;
2100 }
2101
2102 ModuleImport FindModule(Module moduleToFind)
2103 {
2104    ModuleImport module;
2105    if(!moduleToFind.name)
2106       return mainModule;
2107    for(module = imports->first; module; module = module.next)
2108       if(module.name && !strcmp(module.name, moduleToFind.name))
2109          break;
2110    if(!module)
2111    {
2112       module = ModuleImport
2113       {
2114          name = CopyString(moduleToFind.name), importType = moduleToFind.importType,
2115          importAccess = ModuleAccess(privateModule, moduleToFind) ? publicAccess : privateAccess
2116       };
2117       imports->Add(module);
2118    }
2119    return module;
2120 }
2121
2122 /*
2123 // TO REMOVE: OBSOLETE...
2124 static void GetFullClassNameSpace(NameSpace * ns, char * name)
2125 {
2126    if(ns->parent)
2127    {
2128       GetFullClassNameSpace(ns->parent, name);
2129       strcat(name, ns->name);
2130       strcat(name, "::");
2131    }
2132 }
2133
2134 static char * GetFullClassName(Class c, char * name)
2135 {
2136    NameSpace * nameSpace;
2137    name[0] = 0;
2138    GetFullClassNameSpace(c.nameSpace, name);
2139    strcat(name, c.name);
2140    return name;
2141 }
2142 */
2143
2144 public Symbol FindClass(const char * name)
2145 {
2146 #ifdef _TIMINGS
2147    Time startTime = GetTime();
2148 #endif
2149    Symbol cl = null;
2150    Class _class;
2151    bool global = false;
2152    char fullName[1024];
2153
2154    if(name[0] == ':' && name[1] == ':')
2155    {
2156       global = true;
2157       name += 2;
2158    }
2159
2160    if(!global && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
2161    {
2162       int len = 0, stringLen;
2163       if(defaultNameSpace)
2164       {
2165          memcpy(fullName, defaultNameSpace, defaultNameSpaceLen);
2166          len += defaultNameSpaceLen;
2167          fullName[len++] = ':';
2168          fullName[len++] = ':';
2169       }
2170       if(currentNameSpace)
2171       {
2172          memcpy(fullName + len, currentNameSpace, currentNameSpaceLen);
2173          len += currentNameSpaceLen;
2174          fullName[len++] = ':';
2175          fullName[len++] = ':';
2176       }
2177       stringLen = strlen(name);
2178       memcpy(fullName + len, name, stringLen);
2179       len += stringLen;
2180       fullName[len] = 0;
2181       cl = globalContext ? (Symbol)globalContext.classes.FindString(fullName) : null;
2182    }
2183
2184    if(!cl)
2185       cl = globalContext ? (Symbol)globalContext.classes.FindString(name) : null;
2186
2187    if(!cl && !global)
2188    {
2189 #ifdef _TIMINGS
2190       Time startTime = GetTime();
2191 #endif
2192       // Ignore name space name when searching
2193       for(cl = globalContext ? (Symbol)globalContext.classes.first : null; cl; cl = (Symbol)((BTNode)cl).next)
2194       {
2195          /*
2196          int start = 0, c;
2197          char * string = cl.string;
2198          char ch;
2199          for(c = 0; (ch = string[c]); c++)
2200          {
2201             if(ch == '.' || (ch == ':' && string[c+1] == ':'))
2202             {
2203                if(ch == ':') c++;
2204                start = c+1;
2205             }
2206          }
2207          if(start && c - start)
2208          {
2209             if(!strcmp(string + start, name))
2210                break;
2211          }
2212          */
2213          if(cl.shortName && !strcmp(cl.shortName, name))
2214             break;
2215       }
2216 #ifdef _TIMINGS
2217       findClassIgnoreNSTotalTime += GetTime() - startTime;
2218 #endif
2219    }
2220    if(!cl)
2221    {
2222       _class = null;
2223       if(!global && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
2224          _class = eSystem_FindClass(privateModule, fullName);
2225       if(!_class)
2226          _class = eSystem_FindClass(privateModule, name);
2227
2228       if(_class)
2229       {
2230          name = _class.fullName;
2231
2232          cl = (Symbol)globalContext.classes.FindString(name);
2233          if(!cl)
2234          {
2235             cl = Symbol
2236             {
2237                string = CopyString(name);
2238                registered = _class;
2239                notYetDeclared = true;
2240                imported = true;
2241             };
2242             _class.symbol = cl;
2243             if(_class.module)
2244                cl.module = FindModule(_class.module);
2245             else
2246                cl.module = mainModule;
2247             if(!globalContext.classes.Add((BTNode)cl))
2248                excludedSymbols->Add(cl);
2249             if(strcmp(name, _class.name))
2250                cl.shortName = CopyString(_class.name);
2251          }
2252       }
2253    }
2254 #ifdef _TIMINGS
2255    findClassTotalTime += GetTime() - startTime;
2256 #endif
2257    return cl;
2258 }
2259
2260 void CopyTypeInto(Type type, Type src)
2261 {
2262    type = *src;
2263
2264    type.name = CopyString(src.name);
2265    type.typeName = CopyString(src.typeName);
2266    type.refCount = 1;
2267
2268    if(src.kind == enumType)
2269    {
2270       NamedLink64 member;
2271
2272       type.members.Clear();
2273       // This must have been a mistake: member = **type**.members.first
2274       for(member = src.members.first; member; member = member.next)
2275       {
2276          type.members.Add(NamedLink64 { name = CopyString(member.name), data = member.data });
2277       }
2278       type.enumName = CopyString(src.enumName);
2279    }
2280    else if(src.kind == structType || src.kind == unionType)
2281    {
2282       Type member;
2283       // Tricky stuff... will be removed from list only when ref count reaches 0
2284       for(member = type.members.first; member; member = member.next)
2285          member.refCount++;
2286       type.enumName = CopyString(src.enumName);
2287    }
2288    else if(src.kind == functionType)
2289    {
2290       Type param;
2291       type.returnType.refCount++;
2292       for(param = type.params.first; param; param = param.next)
2293          param.refCount++;
2294    }
2295    else if(src.kind == pointerType || src.kind == arrayType)
2296    {
2297       type.type.refCount++;
2298       if(src.kind == arrayType)
2299       {
2300          if(type.arraySizeExp)
2301             type.arraySizeExp = CopyExpression(type.arraySizeExp);
2302       }
2303    }
2304 }
2305
2306 static Type ProcessTypeSpecs(OldList specs, bool assumeEllipsis, bool keepTypeName)
2307 {
2308    Type specType { refCount = 1, kind = intType, isSigned = true };
2309    if(specs != null)
2310    {
2311       bool isTypedef = false;
2312       Specifier spec;
2313       bool isLong = false;
2314       for(spec = specs.first; spec; spec = spec.next)
2315       {
2316          if(spec.type == extendedSpecifier)
2317          {
2318             ExtDecl extDecl = spec.extDecl;
2319             if(extDecl.type == extDeclString)
2320             {
2321                if(!strcmp(spec.extDecl.s, "__declspec(dllexport)") || !strcmp(spec.extDecl.s, "dllexport"))
2322                   specType.dllExport = true;
2323                else if(!strcmp(spec.extDecl.s, "__declspec(stdcall)") || !strcmp(spec.extDecl.s, "stdcall"))
2324                   specType.attrStdcall = true;
2325             }
2326             else if(extDecl.type == extDeclAttrib)
2327             {
2328                OldList * attribs = extDecl.attr.attribs;
2329                if(attribs)
2330                {
2331                   Attribute attr;
2332                   for(attr = attribs->first; attr; attr = attr.next)
2333                   {
2334                      String s = attr.attr;
2335                      if(s)
2336                      {
2337                         if(!strcmp(s, "dllexport"))
2338                            specType.dllExport = true;
2339                         else if(!strcmp(s, "stdcall"))
2340                            specType.attrStdcall = true;
2341                      }
2342                   }
2343                }
2344                specType.keepCast = true;
2345             }
2346          }
2347
2348          if(spec.specifier != CONST && (specType.kind == structType || specType.kind == unionType))
2349          {
2350             FreeType(specType);
2351             specType = { kind = intType, isSigned = true, refCount = 1 };
2352          }
2353
2354          if(isTypedef && keepTypeName)
2355          {
2356             specType.kind = dummyType;
2357             return specType;
2358          }
2359          else if(spec.type == baseSpecifier)
2360          {
2361             if(spec.specifier == TYPEDEF)
2362                isTypedef = true;
2363             else if(spec.specifier == VOID) specType.kind = voidType;
2364             else if(spec.specifier == CHAR) specType.kind = charType;
2365             else if(spec.specifier == INT) { if(specType.kind != shortType && specType.kind != longType && !isLong) specType.kind = intType; }
2366             else if(spec.specifier == _BOOL || spec.specifier == BOOL)
2367                specType.kind = _BoolType;
2368             else if(spec.specifier == UINT) { if(specType.kind != shortType && specType.kind != longType) specType.kind = intType; specType.isSigned = false; }
2369             else if(spec.specifier == INT64) specType.kind = int64Type;
2370             else if(spec.specifier == VALIST)
2371                specType.kind = vaListType;
2372             else if(spec.specifier == SHORT) specType.kind = shortType;
2373             else if(spec.specifier == LONG)
2374             {
2375                if(isLong || (targetBits == 64 && targetPlatform != win32))
2376                   specType.kind = int64Type;
2377                else
2378                   specType.kind = intType;
2379                specType.isLong = true;
2380                isLong = true;
2381             }
2382             else if(spec.specifier == FLOAT) specType.kind = floatType;
2383             else if(spec.specifier == DOUBLE) specType.kind = doubleType;
2384             else if(spec.specifier == SIGNED) specType.isSigned = true;
2385             else if(spec.specifier == UNSIGNED) specType.isSigned = false;
2386             else if(spec.specifier == CONST)
2387                specType.constant = true;
2388             else if(spec.specifier == TYPED_OBJECT || spec.specifier == ANY_OBJECT || spec.specifier == CLASS)
2389             {
2390                switch(spec.specifier)
2391                {
2392                   case TYPED_OBJECT:   specType.classObjectType = typedObject;   break;
2393                   case ANY_OBJECT:     specType.classObjectType = anyObject;     break;
2394                   case CLASS:          specType.classObjectType = classPointer;  break;
2395                }
2396                specType.kind = classType;
2397                specType._class = FindClass("class");
2398             }
2399             else if(spec.specifier == THISCLASS)
2400                specType.kind = thisClassType;
2401          }
2402          else if(spec.type == nameSpecifier)
2403          {
2404             if(spec.name && (!strcmp(spec.name, "intptr") || !strcmp(spec.name, "uintptr")))
2405             {
2406                specType.kind = intPtrType;
2407                if(!strcmp(spec.name, "uintptr"))
2408                   specType.isSigned = false;
2409             }
2410             else if(spec.name && (!strcmp(spec.name, "uintsize") || !strcmp(spec.name, "intsize")))
2411             {
2412                specType.kind = intSizeType;
2413                if(!strcmp(spec.name, "uintsize"))
2414                   specType.isSigned = false;
2415             }
2416             else
2417             {
2418                Symbol symbol = spec.name ? FindType(curContext, spec.name) : null;
2419                if(symbol && symbol.type)
2420                {
2421                   // Keep constant qualifier
2422                   bool isConstant = specType.constant;
2423                   // Free Type Contents:
2424                   Type dummy { };
2425                   *dummy = *specType;
2426                   FreeType(dummy);
2427
2428                   CopyTypeInto(specType, symbol.type);
2429                   specType.constant = isConstant;
2430                   delete specType.typeName;
2431                   specType.typeName = CopyString(symbol.type.name);
2432                }
2433                else if(!isTypedef) // !specType.kind)    // TESTING THIS FOR enum / typedef problem
2434                {
2435                   // key.sym enum values need FindClass:
2436                   specType._class = spec.name ? FindClass(spec.name) : null;
2437                   specType.kind = classType;
2438                   if(!specType._class)
2439                      specType.kind = intType;
2440                }
2441             }
2442          }
2443          else if(spec.type == enumSpecifier)
2444          {
2445             specType.kind = enumType;
2446             specType.enumName = spec.id ? CopyString(spec.id.string) : null;
2447
2448             if(spec.list)
2449             {
2450                Enumerator e;
2451                for(e = spec.list->first; e; e = e.next)
2452                {
2453                   NamedLink64 i { name = CopyString(e.id.string) };
2454                   if(e.exp && e.exp.type == constantExp && e.exp.constant)
2455                      i.data = strtoll(e.exp.constant, null, 0);
2456                   specType.members.Add(i);
2457                }
2458             }
2459          }
2460          else if(spec.type == templateTypeSpecifier)
2461          {
2462             specType.kind = templateType;
2463             specType.templateParameter = spec.templateParameter;
2464          }
2465          else if(spec.type == structSpecifier || spec.type == unionSpecifier)
2466          {
2467             Symbol _class = spec.id ? FindClass(spec.id.string) : null;
2468             if(_class)
2469             {
2470                specType.declaredWithStruct = true;
2471                if(!_class.registered || _class.registered.type != structClass)
2472                   specType.directClassAccess = true;     // TODO: Need to clarify what 'directClassAccess' is about
2473                specType._class = _class;
2474                specType.kind = classType;
2475                break;
2476             }
2477             specType.members.Clear();
2478             if(spec.type == structSpecifier)
2479                specType.kind = structType;
2480             else if(spec.type == unionSpecifier)
2481                specType.kind = unionType;
2482             if(spec.id)
2483             {
2484                // TESTING THIS HERE... Had 0 type size
2485                if(!spec.definitions && !isTypedef)
2486                {
2487                   Symbol symbol = spec.id.string ? FindSymbol(spec.id.string, curContext, globalContext, true, false) : null;
2488                   if(symbol && symbol.type)
2489                   {
2490                      specType = *symbol.type;
2491                      specType.name = CopyString(symbol.type.name);
2492                      specType.typeName = CopyString(spec.name);
2493                      specType.enumName = CopyString(symbol.type.enumName);
2494                      specType.refCount = 1;
2495
2496                      if(symbol.type.kind == enumType)
2497                      {
2498                         NamedLink64 member;
2499
2500                         specType.members.Clear();
2501                         for(member = symbol.type.members.first; member; member = member.next)
2502                         {
2503                            NamedLink64 item { name = CopyString(member.name), data = member.data };
2504                            specType.members.Add(item);
2505                         }
2506                      }
2507                      else if(symbol.type.kind == structType || symbol.type.kind == unionType)
2508                      {
2509                         Type member;
2510                         // Tricky stuff... will be removed from list only when ref count reaches 0
2511                         for(member = specType.members.first; member; member = member.next)
2512                            member.refCount++;
2513                      }
2514                      else if(symbol.type.kind == functionType)
2515                      {
2516                         Type param;
2517                         specType.returnType.refCount++;
2518                         for(param = specType.params.first; param; param = param.next)
2519                            param.refCount++;
2520                      }
2521                      else if(symbol.type.kind == pointerType || symbol.type.kind == arrayType)
2522                      {
2523                         specType.type.refCount++;
2524                         if(symbol.type.kind == arrayType)
2525                         {
2526                            if(specType.arraySizeExp)
2527                               specType.arraySizeExp = CopyExpression(specType.arraySizeExp);
2528                         }
2529
2530                      }
2531                   }
2532                   else
2533                      specType.enumName = CopyString(spec.id.string);
2534                }
2535                else
2536                   specType.enumName = CopyString(spec.id.string);
2537             }
2538
2539             if(spec.definitions)
2540             {
2541                ClassDef def;
2542                for(def = spec.definitions->first; def; def = def.next)
2543                {
2544                   if(def.type == declarationClassDef && def.decl.type == structDeclaration)
2545                   {
2546                      Declaration decl = def.decl;
2547                      if(decl.declarators)
2548                      {
2549                         Declarator d;
2550                         for(d = decl.declarators->first; d; d = d.next)
2551                         {
2552                            Type memberType = ProcessType(decl.specifiers, d);
2553                            specType.members.Add(memberType);
2554                         }
2555                      }
2556                      else if(decl.specifiers)
2557                      {
2558                         Type memberType = ProcessType(decl.specifiers, null);
2559                         specType.members.Add(memberType);
2560                      }
2561                   }
2562                }
2563             }
2564             break;
2565          }
2566          else if(spec.type == subClassSpecifier)
2567          {
2568             specType.kind = subClassType;
2569             specType._class = spec._class.symbol;
2570          }
2571       }
2572    }
2573    else if(assumeEllipsis)
2574       specType.kind = ellipsisType;
2575    return specType;
2576 }
2577
2578 static Type ProcessTypeDecls(OldList specs, Declarator decl, Type parentType)
2579 {
2580    Type type = parentType;
2581    Declarator subDecl = decl ? decl.declarator : null;
2582    if(!parentType)
2583       type = ProcessTypeSpecs(specs, decl == null, (decl && decl.type == extendedDeclaratorEnd) ? true : false);
2584    if(decl)
2585    {
2586       switch(decl.type)
2587       {
2588          case bracketsDeclarator: break;
2589          case extendedDeclarator:
2590          case extendedDeclaratorEnd:
2591          {
2592             ExtDecl extDecl = decl.extended.extended;
2593             if(extDecl)
2594             {
2595                switch(extDecl.type)
2596                {
2597                   case extDeclString:
2598                   {
2599                      String s = extDecl.s;
2600                      if(s)
2601                      {
2602                         if(!strcmp(s, "__declspec(dllexport)") || !strcmp(s, "dllexport"))
2603                            type.dllExport = true;
2604                         else if(!strcmp(s, "__declspec(stdcall)") || !strcmp(s, "stdcall"))
2605                            type.attrStdcall = true;
2606                      }
2607                      break;
2608                   }
2609                   case extDeclAttrib:
2610                   {
2611                      OldList * attribs = extDecl.attr.attribs;
2612                      if(attribs)
2613                      {
2614                         Attribute attr;
2615                         for(attr = attribs->first; attr; attr = attr.next)
2616                         {
2617                            String s = attr.attr;
2618                            if(s)
2619                            {
2620                               if(!strcmp(s, "dllexport"))
2621                                  type.dllExport = true;
2622                               else if(!strcmp(s, "stdcall"))
2623                                  type.attrStdcall = true;
2624                            }
2625                         }
2626                      }
2627                      type.keepCast = true;
2628                      break;
2629                   }
2630                }
2631             }
2632             break;
2633          }
2634          case structDeclarator:
2635          {
2636             Expression exp = decl.structDecl.exp;
2637             if(exp)
2638             {
2639                ProcessExpressionType(exp);
2640                ComputeExpression(exp);
2641                if(exp.type == constantExp)
2642                   type.bitFieldCount = (uint)strtoul(exp.constant, null, 0);
2643             }
2644             break;
2645          }
2646          case functionDeclarator:
2647          {
2648             type = { refCount = 1, kind = functionType, returnType = type, dllExport = type.dllExport, attrStdcall = type.attrStdcall };
2649             if(decl.function.parameters)
2650             {
2651                TypeName param;
2652                for(param = decl.function.parameters->first; param; param = param.next)
2653                   type.params.Add(ProcessType(param.qualifiers, param.declarator));
2654             }
2655             break;
2656          }
2657          case arrayDeclarator:
2658          {
2659             type = { refCount = 1, kind = arrayType, arraySizeExp = CopyExpression(decl.array.exp), freeExp = true, type = type, dllExport = type.dllExport, attrStdcall = type.attrStdcall };
2660             if(decl.array.enumClass)
2661                type.enumClass = decl.array.enumClass.symbol;
2662             break;
2663          }
2664          case pointerDeclarator:
2665          {
2666             Pointer pointer = decl.pointer.pointer;
2667             while(pointer)
2668             {
2669                OldList * qualifiers = pointer.qualifiers;
2670                if(type.classObjectType)
2671                   type.byReference = true;
2672                else
2673                   type = { refCount = 1, kind = pointerType, type = type, dllExport = type.dllExport, attrStdcall = type.attrStdcall };
2674                if(qualifiers)
2675                {
2676                   Specifier spec;
2677                   for(spec = qualifiers->first; spec; spec = spec.next)
2678                   {
2679                      if(spec.type == baseSpecifier && spec.specifier == CONST)
2680                         type.constant = true;
2681                   }
2682                }
2683                pointer = pointer.pointer;
2684             }
2685             break;
2686          }
2687          case identifierDeclarator:
2688          {
2689             Identifier id = decl.identifier;
2690             Specifier _class = id._class;
2691             delete type.name;
2692             type.name = CopyString(id.string);
2693             if(_class)
2694             {
2695                if(_class.type == templateTypeSpecifier)
2696                {
2697                   type.thisClassTemplate = _class.templateParameter;
2698                   type.extraParam = true;
2699                }
2700                else
2701                {
2702                   String name = _class.name;
2703                   if(!name)
2704                      type.staticMethod = true;
2705                   else
2706                   {
2707                      if(!id.classSym)
2708                         id.classSym = _class.symbol; // FindClass(_class.name);
2709                      /* TODO: Name Space Fix ups
2710                         id.nameSpace = eSystem_FindNameSpace(privateModule, _class.name);
2711                      */
2712
2713                      if(name[strlen(name)-1] == '&')
2714                      {
2715                         type.thisClass = FindClass("class");
2716                         type.byReference = true;
2717                      }
2718                      else
2719                         type.thisClass = _class.symbol;
2720
2721                      if(type.thisClass && strcmp(type.thisClass.string, "class"))
2722                         type.extraParam = true;
2723                      else if(!strcmp(name, "any_object"))
2724                      {
2725                         type.extraParam = true;
2726                         type.thisClass = FindClass("class");
2727                      }
2728                      else if(!strcmp(name, "class"))
2729                      {
2730                         type.thisClass = FindClass("class");
2731                         type.classObjectType = classPointer;   // This is used for class properties
2732                      }
2733                      else if(!strcmp(name, "typed_object") || !strcmp(name, "typed_object&"))
2734                      {
2735                         type.thisClass = FindClass("class");
2736                         type.classObjectType = typedObject;
2737                      }
2738                   }
2739                }
2740             }
2741             break;
2742          }
2743          default:
2744             PrintLn("Unhandled Declarator Type: ", decl.type);
2745       }
2746    }
2747    if(subDecl)
2748    {
2749       Type curType = type;
2750       type = ProcessTypeDecls(null, subDecl, type);
2751       if(curType && type.kind != functionType)
2752       {
2753          curType.thisClassTemplate = type.thisClassTemplate;
2754          curType.extraParam = type.extraParam;
2755          curType.staticMethod = type.staticMethod;
2756          curType.thisClass = type.thisClass;
2757          curType.byReference = type.byReference;
2758          curType.classObjectType = type.classObjectType;
2759       }
2760    }
2761    return type;
2762 }
2763
2764 public Type ProcessType(OldList specs, Declarator decl)
2765 {
2766    return ProcessTypeDecls(specs, decl, null);
2767 }
2768
2769 public Type ProcessTypeString(const char * string, bool staticMethod)
2770 {
2771    OldList * specs = MkList();
2772    Declarator decl = SpecDeclFromString(string, specs, null);
2773    Type type = ProcessType(specs, decl);
2774    if(type && !type.thisClass && staticMethod) type.staticMethod = true;
2775    FreeList(specs, FreeSpecifier);
2776    if(decl) FreeDeclarator(decl);
2777    return type;
2778 }
2779
2780 Type MkClassTypeSymbol(Symbol symbol)
2781 {
2782    if(symbol)
2783    {
2784       Type type { kind = classType, _class = symbol };
2785       if(!type._class)
2786       {
2787          // Defaults to an int instead...
2788          type.kind = intType;
2789       }
2790       type.refCount = 1;
2791       return type;
2792    }
2793    return null;
2794 }
2795
2796 public Type MkClassType(const char * name)
2797 {
2798    if(name)
2799    {
2800       Type type { kind = classType, _class = FindClass(name) };
2801       if(!type._class)
2802       {
2803          // Defaults to an int instead...
2804          type.kind = intType;
2805       }
2806       type.refCount = 1;
2807       return type;
2808    }
2809    return null;
2810 }
2811
2812 AsmField MkAsmField(char * command, Expression expression, Identifier symbolic)
2813 {
2814    return { command = command, expression = expression, symbolic = symbolic };
2815 }
2816
2817 Statement MkAsmStmt(Specifier spec, char * statements, OldList inputFields, OldList outputFields, OldList clobberedFields)
2818 {
2819    return { type = asmStmt, asmStmt.spec = spec, asmStmt.statements = statements,
2820       asmStmt.inputFields = inputFields, asmStmt.outputFields = outputFields,
2821       asmStmt.clobberedFields = clobberedFields };
2822 }
2823
2824 ClassDef MkClassDefPropertyWatch(PropertyWatch watcher)
2825 {
2826    return { type = propertyWatchClassDef, propertyWatch = watcher };
2827 }
2828
2829 Statement MkFireWatchersStmt(Expression object, OldList watches)
2830 {
2831    return { type = fireWatchersStmt, _watch.object = object, _watch.watches = watches };
2832 }
2833
2834 Statement MkStopWatchingStmt(Expression watcher, Expression object, OldList watches)
2835 {
2836    return { type = stopWatchingStmt, _watch.watcher = watcher, _watch.object = object, _watch.watches = watches };
2837 }
2838
2839 Statement MkWatchStmt(Expression watcher, Expression object, OldList watches)
2840 {
2841    return { type = watchStmt, _watch.watcher = watcher, _watch.object = object, _watch.watches = watches };
2842 }
2843
2844 PropertyWatch MkDeleteWatch(Statement compound)
2845 {
2846    return { compound = compound, deleteWatch = true };
2847 }
2848
2849 PropertyWatch MkPropertyWatch(OldList properties, Statement compound)
2850 {
2851    return { compound = compound, properties = properties };
2852 }
2853
2854 Expression MkExpClass(OldList * specifiers, Declarator decl)
2855 {
2856    return { type = classExp, _classExp.specifiers = specifiers, _classExp.decl = decl };
2857 }
2858
2859 Expression MkExpClassData(Identifier id)
2860 {
2861    return { type = classDataExp, classData.id = id };
2862 }
2863
2864
2865 External MkExternalDBTable(DBTableDef table)
2866 {
2867    return { type = dbtableExternal, table = table };
2868 }
2869
2870 DBTableDef MkDBTableDef(char * name, Symbol symbol, OldList * definitions)
2871 {
2872    return { name = name, symbol = symbol, definitions = definitions };
2873 }
2874
2875 DBTableEntry MkDBFieldEntry(TypeName type, Identifier id, char * name)
2876 {
2877    return { type = fieldEntry, dataType = type, id = id, name = name };
2878 }
2879
2880 DBIndexItem MkDBIndexItem(Identifier id, Order order)
2881 {
2882    return { id = id, order = order };
2883 }
2884
2885 DBTableEntry MkDBIndexEntry(OldList * items, Identifier id)
2886 {
2887    return { type = indexEntry, items = items, id = id };
2888 }
2889
2890 Expression MkExpDBOpen(Expression ds, Expression dbName)
2891 {
2892    return { type = dbopenExp, dbopen.ds = ds, dbopen.name = dbName };
2893 }
2894
2895 Expression MkExpDBField(char * table, Identifier id)
2896 {
2897    return { type = dbfieldExp, db.table = table, db.id = id };
2898 }
2899
2900 Expression MkExpDBIndex(char * table, Identifier id)
2901 {
2902    return { type = dbindexExp, db.table = table, db.id = id };
2903 }
2904
2905 Expression MkExpDBTable(char * table)
2906 {
2907    return { type = dbtableExp, db.table = table };
2908 }
2909
2910 Expression MkExpArray(OldList * expressions)
2911 {
2912    return { type = arrayExp, list = expressions };
2913 }
2914
2915 Expression GetTemplateArgExpByName(const char * paramName, Class curClass, TemplateParameterType tplType)
2916 {
2917    Expression argExp = null;
2918    Class _class = curClass ? curClass : ((curExternal && curExternal.type == functionExternal && curExternal.function) ? curExternal.function._class : null);
2919    if(_class)
2920    {
2921       int id = 0;
2922       ClassTemplateParameter curParam;
2923       Class sClass;
2924       for(sClass = _class; sClass; sClass = sClass.base)
2925       {
2926          id = 0;
2927          for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
2928          {
2929             if(!strcmp(curParam.name, paramName))
2930             {
2931                for(sClass = sClass.base; sClass; sClass = sClass.base)
2932                   id += sClass.templateParams.count;
2933                break;
2934             }
2935             id++;
2936          }
2937          if(curParam) break;
2938       }
2939
2940       if(curParam && curParam.type != tplType)
2941          curParam = null;
2942
2943       if(curParam)
2944       {
2945          char idString[32];
2946          char className[1024];
2947
2948          sprintf(idString, "%d", id);
2949          strcpy(className, "__ecereClass_");
2950          FullClassNameCat(className, _class.fullName, true);
2951          DeclareClass(curExternal, FindClass(_class.fullName), className);
2952
2953          argExp = MkExpIndex((/*pointer ? MkExpPointer : */MkExpMember)
2954                (MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class")) /*MkExpIdentifier(MkIdentifier(className))*/,
2955                MkIdentifier("templateArgs")), MkListOne(MkExpConstant(idString)));
2956       }
2957    }
2958    return argExp;
2959 }
2960
2961 Expression GetTemplateArgExp(TemplateParameter param, Class curClass, bool pointer)
2962 {
2963    return param.identifier ? GetTemplateArgExpByName(param.identifier.string, curClass, type) : null;
2964 }
2965
2966 /*char * CreateMsgID(const char * string, const char * context)
2967 {
2968    int lenString = strlen(string), lenContext = strlen(context);
2969    char * msgid = new char[lenString + lenContext + 20];
2970    memcpy(msgid, string, lenString);
2971    memcpy(msgid+lenString, " [msgctxt: ", 11);
2972    memcpy(msgid+lenString+11, context, lenContext);
2973    memcpy(msgid+lenString+11+lenContext, "]", 2);
2974    return msgid;
2975 }*/
2976
2977 public void OutputIntlStrings()
2978 {
2979    if(intlStrings.count)
2980    {
2981       const char * srcFile = GetSourceFile();
2982       const char * objFile = GetOutputFile();
2983       char srcFileFixed[MAX_LOCATION];
2984       char potFile[MAX_LOCATION];
2985       File f;
2986       ChangeExtension(objFile, "bowl", potFile);
2987       f = FileOpen(potFile, write);
2988       if(f)
2989       {
2990          const char * filePrefix = "";
2991          if(!(srcFile[0] && (srcFile[1] == ':' || srcFile[0] == '/')))
2992             filePrefix = "./"; //(__runtimePlatform == win32) ? ".\\" : "./";
2993          // GetSystemPathBuffer(srcFileFixed, srcFile);
2994          GetSlashPathBuffer(srcFileFixed, srcFile);
2995
2996          for(s : intlStrings)
2997          {
2998             // TOFIX: (#654) ContextStringPair * pair = &s;
2999             ContextStringPair pair = &s;
3000             for(l : s)
3001                f.Printf("#: %s%s:%d\n", filePrefix, srcFileFixed, l.start.line);
3002              // PoEdit now preserves and distinguish msgctxt
3003             if(pair.context)
3004                f.Printf("msgctxt \"%s\"\n", pair.context);
3005             f.Printf("msgid \"%s\"\n", pair.string);
3006             f.Printf("msgstr \"%s\"\n\n", pair.string);
3007          }
3008          delete f;
3009       }
3010       intlStrings.Free();
3011    }
3012 }
3013
3014 default extern OldList * ast;
3015 default extern int yyparse ();
3016 default extern int yylex ();
3017
3018 public void SetAST(OldList * list) { ast = list; }
3019 public OldList * GetAST() { return ast; }
3020 public void ParseEc()
3021 {
3022    yyparse();
3023 }
3024
3025 public int LexEc()
3026 {
3027    return yylex();
3028 }
3029
3030 public const char * GetYYText()
3031 {
3032    return yytext;
3033 }