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