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