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