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