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