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