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