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