compiler/libec: Fixed memory leak on class context when pre-declaring a class and...
[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    if(symbol.ctx)
1608    {
1609       FreeContext(symbol.ctx);
1610       delete symbol.ctx;
1611    }
1612    symbol.ctx = curContext;
1613    classDef = { symbol = symbol, _class = MkSpecifierName /*MkClassName*/(symbol.string), baseSpecs = baseSpecs, definitions = definitions, nameLoc = symbol.nameLoc };
1614    curContext.classDef = classDef;
1615    return classDef;
1616 }
1617
1618 Expression MkExpInstance(Instantiation inst)
1619 {
1620    return { type = instanceExp, instance = inst };
1621 }
1622
1623 External MkExternalClass(ClassDefinition _class)
1624 {
1625    return { type = classExternal, _class = _class, symbol = _class.symbol };
1626 }
1627
1628 PropertyDef MkProperty(OldList specs, Declarator decl, Identifier id, Statement setStmt, Statement getStmt)
1629 {
1630    PropertyDef prop
1631    {
1632       specifiers = specs;
1633       declarator = decl;
1634       setStmt = setStmt;
1635       getStmt = getStmt;
1636    };
1637    Symbol symbol;
1638    Type type = ProcessType(specs, decl);
1639    if(!id)
1640    {
1641       char typeString[1024];
1642       typeString[0] = '\0';
1643       PrintType(type, typeString, false, true);
1644       id = MkIdentifier(typeString);
1645       prop.conversion = true;
1646    }
1647    prop.id = id;
1648
1649    symbol = Symbol
1650    {
1651       string = CopyString(id.string);
1652       type = type;
1653    };
1654    symbol.idCode = symbol.id = globalContext.nextID++;
1655    excludedSymbols->Add(symbol);
1656    globalContext.nextID++;
1657    globalContext.nextID++;
1658    prop.symbol = symbol;
1659    return prop;
1660 }
1661
1662 ClassDef MkClassDefProperty(PropertyDef propertyDef)
1663 {
1664    return { type = propertyClassDef, propertyDef = propertyDef };
1665 }
1666
1667 ClassDef MkClassDefClassProperty(PropertyDef propertyDef)
1668 {
1669    return { type = classPropertyClassDef, propertyDef = propertyDef };
1670 }
1671
1672 ClassDef MkClassDefClassPropertyValue(Identifier id, Initializer initializer)
1673 {
1674    return { type = classPropertyValueClassDef, id = id, initializer = initializer };
1675 }
1676
1677 int CheckType(char * text)
1678 {
1679 #ifdef _TIMINGS
1680    Time startTime = GetTime();
1681 #endif
1682    if(FindTemplateTypeParameter(curContext, text))
1683    {
1684 #ifdef _TIMINGS
1685       checkTypeTotalTime += GetTime() - startTime;
1686 #endif
1687       return TYPE_NAME;
1688    }
1689    if(FindType(curContext, text))
1690    {
1691 #ifdef _TIMINGS
1692       checkTypeTotalTime += GetTime() - startTime;
1693 #endif
1694       return TYPE_NAME;
1695    }
1696    if(FindClass(text))
1697    {
1698 #ifdef _TIMINGS
1699       checkTypeTotalTime += GetTime() - startTime;
1700 #endif
1701       return TYPE_NAME; //CLASS_NAME;
1702    }
1703 #ifdef _TIMINGS
1704    checkTypeTotalTime += GetTime() - startTime;
1705 #endif
1706    return IDENTIFIER;
1707 }
1708
1709 int check_type()
1710 {
1711    return CheckType(yytext);
1712 }
1713
1714 Context PushContext()
1715 {
1716    Context ctx { parent = curContext };
1717    curContext = ctx;
1718    return ctx;
1719 }
1720
1721 void PopContext(Context ctx)
1722 {
1723    curContext = ctx.parent;
1724 }
1725
1726 Symbol FindType(Context ctx, char * name)
1727 {
1728    Symbol type = null;
1729    if(curContext)
1730    {
1731       type = (Symbol)ctx.types.FindString(name);
1732       if(!type && ctx.parent)
1733          type = FindType(ctx.parent, name);
1734    }
1735    return type;
1736 }
1737
1738 TemplatedType FindTemplateTypeParameter(Context ctx, char * name)
1739 {
1740    TemplatedType templatedType = null;
1741    if(curContext)
1742    {
1743       templatedType = (TemplatedType)ctx.templateTypes.FindString(name);
1744       if(!templatedType && ctx.parent)
1745          templatedType = FindTemplateTypeParameter(ctx.parent, name);
1746    }
1747    return templatedType;
1748 }
1749
1750 bool ModuleAccess(Module searchIn, Module searchFor)
1751 {
1752    SubModule subModule;
1753    
1754    if(searchFor == searchIn)
1755       return true;
1756
1757    for(subModule = searchIn.modules.first; subModule; subModule = subModule.next)
1758    {
1759       if(subModule.importMode == publicAccess /*|| searchIn == searchIn.application*/)
1760       {
1761          if(ModuleAccess(subModule.module, searchFor))
1762             return true;
1763       }
1764    }
1765    return false;
1766 }
1767
1768 ModuleImport FindModule(Module moduleToFind)
1769 {
1770    ModuleImport module;
1771    if(!moduleToFind.name)
1772       return mainModule;
1773    for(module = imports->first; module; module = module.next)
1774       if(module.name && !strcmp(module.name, moduleToFind.name))
1775          break;
1776    if(!module)
1777    {
1778       module = ModuleImport 
1779       { 
1780          name = CopyString(moduleToFind.name), importType = moduleToFind.importType,
1781          importAccess = ModuleAccess(privateModule, moduleToFind) ? publicAccess : privateAccess
1782       };
1783       imports->Add(module);
1784    }
1785    return module;
1786 }
1787
1788 /*
1789 // TO REMOVE: OBSOLETE...
1790 static void GetFullClassNameSpace(NameSpace * ns, char * name)
1791 {
1792    if(ns->parent)
1793    {
1794       GetFullClassNameSpace(ns->parent, name);
1795       strcat(name, ns->name);
1796       strcat(name, "::");      
1797    }
1798 }
1799
1800 static char * GetFullClassName(Class c, char * name)
1801 {
1802    NameSpace * nameSpace;
1803    name[0] = 0;
1804    GetFullClassNameSpace(c.nameSpace, name);
1805    strcat(name, c.name);
1806    return name;
1807 }
1808 */
1809
1810 public Symbol FindClass(char * name)
1811 {
1812 #ifdef _DEBUG
1813    Time startTime = GetTime();
1814 #endif
1815    Symbol cl = null;
1816    Class _class;
1817    bool global = false;
1818    char fullName[1024];
1819
1820    if(name[0] == ':' && name[1] == ':')
1821    {
1822       global = true;
1823       name += 2;
1824    }
1825
1826    if(!global && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
1827    {
1828       int len = 0, stringLen;
1829       if(defaultNameSpace)
1830       {
1831          memcpy(fullName, defaultNameSpace, defaultNameSpaceLen);
1832          len += defaultNameSpaceLen;
1833          fullName[len++] = ':';
1834          fullName[len++] = ':';
1835       }
1836       if(currentNameSpace)
1837       {
1838          memcpy(fullName + len, currentNameSpace, currentNameSpaceLen);
1839          len += currentNameSpaceLen;
1840          fullName[len++] = ':';
1841          fullName[len++] = ':';
1842       }
1843       stringLen = strlen(name);
1844       memcpy(fullName + len, name, stringLen);
1845       len += stringLen;
1846       fullName[len] = 0;
1847       cl = globalContext ? (Symbol)globalContext.classes.FindString(fullName) : null;
1848    }
1849
1850    if(!cl)
1851       cl = globalContext ? (Symbol)globalContext.classes.FindString(name) : null;
1852
1853    if(!cl && !global)
1854    {
1855 #ifdef _TIMINGS
1856       Time startTime = GetTime();
1857 #endif
1858       // Ignore name space name when searching
1859       for(cl = globalContext ? (Symbol)globalContext.classes.first : null; cl; cl = (Symbol)((BTNode)cl).next)
1860       {
1861          /*
1862          int start = 0, c;
1863          char * string = cl.string;
1864          char ch;
1865          for(c = 0; (ch = string[c]); c++)
1866          {
1867             if(ch == '.' || (ch == ':' && string[c+1] == ':'))
1868             {
1869                if(ch == ':') c++;
1870                start = c+1;
1871             }
1872          }
1873          if(start && c - start)
1874          {
1875             if(!strcmp(string + start, name))
1876                break;
1877          }
1878          */
1879          if(cl.shortName && !strcmp(cl.shortName, name))
1880             break;            
1881       }
1882 #ifdef _TIMINGS
1883       findClassIgnoreNSTotalTime += GetTime() - startTime;
1884 #endif
1885    }
1886    if(!cl)
1887    {
1888       _class = null;
1889       if(!global && (currentNameSpace || defaultNameSpace) && declMode != defaultAccess && defaultDeclMode != defaultAccess)
1890          _class = eSystem_FindClass(privateModule, fullName);
1891       if(!_class)
1892          _class = eSystem_FindClass(privateModule, name);
1893
1894       if(_class)
1895       {
1896          name = _class.fullName;
1897
1898          cl = (Symbol)globalContext.classes.FindString(name);
1899          if(!cl)
1900          {
1901             cl = Symbol
1902             {
1903                string = CopyString(name);
1904                registered = _class;
1905                id = MAXINT;
1906                idCode = MAXINT;
1907                imported = true;
1908             };
1909             _class.symbol = cl;
1910             if(_class.module)
1911                cl.module = FindModule(_class.module);
1912             else
1913                cl.module = mainModule;
1914             if(!globalContext.classes.Add((BTNode)cl))
1915                excludedSymbols->Add(cl);
1916             if(strcmp(name, _class.name))
1917                cl.shortName = CopyString(_class.name);
1918          }
1919       }
1920    }
1921 #ifdef _TIMINGS
1922    findClassTotalTime += GetTime() - startTime;
1923 #endif
1924    return cl;
1925 }
1926
1927 void CopyTypeInto(Type type, Type src)
1928 {
1929    type = *src;
1930    type.name = CopyString(src.name);
1931    type.enumName = CopyString(src.enumName);
1932    type.refCount = 1;
1933
1934    if(src.kind == enumType)
1935    {
1936       NamedLink member;
1937
1938       type.members.Clear();
1939       // This must have been a mistake: member = **type**.members.first
1940       for(member = src.members.first; member; member = member.next)
1941       {
1942          type.members.Add(NamedLink { name = CopyString(member.name), data = member.data });
1943       }
1944    }
1945    else if(src.kind == structType || src.kind == unionType)
1946    {
1947       Type member;
1948       // Tricky stuff... will be removed from list only when ref count reaches 0
1949       for(member = type.members.first; member; member = member.next)
1950          member.refCount++;
1951    }
1952    else if(src.kind == functionType)
1953    {
1954       Type param;
1955       type.returnType.refCount++;
1956       for(param = type.params.first; param; param = param.next)
1957          param.refCount++;
1958    }
1959    else if(src.kind == pointerType || src.kind == arrayType)
1960    {
1961       type.type.refCount++;
1962       if(src.kind == arrayType)
1963       {
1964          if(type.arraySizeExp)
1965             type.arraySizeExp = CopyExpression(type.arraySizeExp);
1966       }
1967
1968    }
1969 }
1970
1971 public Type ProcessType(OldList specs, Declarator decl)
1972 {
1973    Type type = null;
1974    bool isTypedef = false;
1975    if(!specs || specs.first)
1976    {
1977       Declarator funcDecl = GetFuncDecl(decl);
1978       Type specType { };
1979       bool dllExport = false;
1980
1981       specType.kind = intType;
1982       specType.isSigned = true;   
1983       specType.refCount = 1;
1984
1985       type = Type { refCount = 1 };
1986
1987       while(decl && (decl.type == structDeclarator || decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd))
1988       {
1989          if(decl.type == structDeclarator && decl.structDecl.exp)
1990          {
1991             ProcessExpressionType(decl.structDecl.exp);
1992             ComputeExpression(decl.structDecl.exp);
1993             if(decl.structDecl.exp.type == constantExp)
1994                specType.bitFieldCount = strtoul(decl.structDecl.exp.constant, null, 0);
1995          }
1996          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended && 
1997             (!strcmp(decl.extended.extended, "__declspec(dllexport)") || !strcmp(decl.extended.extended, "dllexport")))
1998          {
1999             dllExport = true;
2000          }
2001          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended && 
2002             (strstr(decl.extended.extended, "__attribute__")))
2003          {
2004             specType.keepCast = true;
2005          }
2006          decl = decl.declarator;
2007       }
2008
2009       // If we'll be using the specType
2010       if(funcDecl || !decl || decl.type == identifierDeclarator)
2011       {
2012          Specifier spec;
2013          if(specs != null)
2014          {
2015             bool isLong = false;
2016             for(spec = specs.first; spec; spec = spec.next)
2017             {
2018                if(spec.type == extendedSpecifier && (!strcmp(spec.name, "__declspec(dllexport)") || !strcmp(spec.name, "dllexport")))
2019                {
2020                   dllExport = true;
2021                }
2022                if(spec.type == extendedSpecifier && strstr(spec.name, "__attribute__"))
2023                {
2024                   specType.keepCast = true;
2025                }
2026
2027                if(spec.specifier != CONST && (specType.kind == structType || specType.kind == unionType))
2028                {
2029                   FreeType(specType);
2030                   specType = { kind = intType, isSigned = true, refCount = 1 };
2031                }
2032
2033                if(spec.type == baseSpecifier)
2034                {
2035                   if(spec.specifier == TYPEDEF) isTypedef = true;
2036                   else if(spec.specifier == VOID) specType.kind = voidType;
2037                   else if(spec.specifier == CHAR) specType.kind = charType;
2038                   else if(spec.specifier == INT) { if(specType.kind != shortType && specType.kind != longType) specType.kind = intType; }
2039                   else if(spec.specifier == UINT) { if(specType.kind != shortType && specType.kind != longType) specType.kind = intType; specType.isSigned = false; }
2040                   else if(spec.specifier == INT64) specType.kind = int64Type;
2041                   else if(spec.specifier == VALIST) 
2042                      specType.kind = vaListType;
2043                   else if(spec.specifier == SHORT) specType.kind = shortType;
2044                   else if(spec.specifier == LONG) 
2045                   {
2046                      if(isLong)
2047                         specType.kind = int64Type;
2048                      else
2049                         specType.kind = intType;
2050                      isLong = true;
2051                      // specType.kind = longType;
2052                   }
2053                   else if(spec.specifier == FLOAT) specType.kind = floatType;
2054                   else if(spec.specifier == DOUBLE) specType.kind = doubleType;
2055                   else if(spec.specifier == SIGNED) specType.isSigned = true;
2056                   else if(spec.specifier == UNSIGNED) specType.isSigned = false;
2057                   else if(spec.specifier == CONST) specType.constant = true;
2058                   else if(spec.specifier == TYPED_OBJECT) 
2059                   { 
2060                      specType.classObjectType = typedObject; specType.kind = classType; specType._class = FindClass("class"); 
2061                   }
2062                   else if(spec.specifier == ANY_OBJECT) 
2063                   { 
2064                      specType.classObjectType = anyObject; specType.kind = classType; specType._class = FindClass("class"); 
2065                   }
2066                   else if(spec.specifier == CLASS)
2067                   {
2068                      specType.classObjectType = classPointer; specType.kind = classType; specType._class = FindClass("class");
2069                   }
2070                   else if(spec.specifier == THISCLASS)
2071                      specType.kind = thisClassType;
2072                }
2073                else if(spec.type == nameSpecifier)
2074                {
2075                   Symbol symbol = spec.name ? FindType(curContext, spec.name) : null;
2076                   if(symbol && symbol.type)
2077                   {
2078                      // Free Type Contents:
2079                      Type dummy { };
2080                      *dummy = *specType;
2081                      FreeType(dummy);
2082
2083                      CopyTypeInto(specType, symbol.type);
2084                      specType.typeName = CopyString(symbol.type.name);
2085                   }
2086                   else if(!isTypedef) // !specType.kind)    // TESTING THIS FOR enum / typedef problem
2087                   {
2088                      // key.sym enum values need FindClass:
2089                      specType._class = spec.name ? FindClass(spec.name) : null;
2090                      // specType._class = spec.symbol; 
2091                      specType.kind = classType;
2092                      if(!specType._class)
2093                         specType.kind = intType;
2094                   }
2095                }
2096                else if(spec.type == enumSpecifier)
2097                {
2098
2099                   specType.kind = enumType;
2100                   specType.enumName = spec.id ? CopyString(spec.id.string) : null;
2101
2102                   if(spec.list)
2103                   {
2104                      Enumerator e;
2105                      int nextValue = 0;
2106                      for(e = spec.list->first; e; e = e.next)
2107                      {
2108                         // TOFIX: NamedItem i { } causes cryptic error, bad .c!
2109                         NamedLink i { name = CopyString(e.id.string) };
2110                         specType.members.Add(i);
2111                         /*
2112                         if(e.exp && ComputeExpression(e.exp), e.exp.isConstant && e.exp.expType.kind == intType)
2113                            value.data = (void *) nextValue = strtol(e.exp.string, null, 0);
2114                         else
2115                            value.data = (void *)nextValue++;
2116                         */
2117                      }
2118                   }
2119                   /*
2120                   if(spec.list)
2121                   {
2122                      Declaration decl;
2123                      for(enumerator = spec.list->first; enumerator; enumerator = enumerator.next)
2124                         if(decl.declarators)
2125                         {
2126                            Declarator d;
2127                            for(d = decl.declarators.first; d; d = d.next)
2128                            {
2129                               Type memberType = ProcessType(decl.specifiers, d);
2130                               specType.members.Add(memberType);
2131                            }
2132                         }
2133                         else if(decl.specifiers)
2134                         {
2135                            Type memberType = ProcessType(decl.specifiers, null);
2136                            specType.members.Add(memberType);
2137                         }
2138                   }
2139                   */
2140                }
2141                else if(spec.type == templateTypeSpecifier)
2142                {
2143                   /*
2144                   printf("spec %x\n", spec);
2145                   printf("template param %x\n", spec.templateParameter);
2146                   printf("identifier %x\n", spec.templateParameter.identifier);
2147                   printf("string %x\n", spec.templateParameter.identifier.string);
2148                   */
2149                   specType.kind = templateType;
2150                   specType.templateParameter = spec.templateParameter;
2151                }
2152                else if(spec.type == structSpecifier || spec.type == unionSpecifier)
2153                {
2154                   Symbol _class = spec.id ? FindClass(spec.id.string) : null;
2155                   if(_class)
2156                   {
2157                      if(!_class.registered || _class.registered.type != structClass)
2158                         specType.directClassAccess = true;
2159                      specType._class = _class;
2160                      specType.kind = classType;
2161                      break;
2162                   }
2163                   if(spec.type == structSpecifier)
2164                      specType.kind = structType;
2165                   else if(spec.type == unionSpecifier)
2166                      specType.kind = unionType;
2167                   if(spec.id)
2168                   {
2169                      // TESTING THIS HERE... Had 0 type size 
2170                      if(!spec.definitions && !isTypedef)
2171                      {
2172                         Symbol symbol = spec.id.string ? FindSymbol(spec.id.string, curContext, globalContext, true, false) : null;
2173                         if(symbol && symbol.type)
2174                         {
2175                            specType = *symbol.type;
2176                            specType.name = CopyString(symbol.type.name);
2177                            specType.typeName = CopyString(spec.name);
2178                            specType.enumName = CopyString(symbol.type.enumName);
2179                            specType.refCount = 1;
2180
2181                            if(symbol.type.kind == enumType)
2182                            {
2183                               NamedLink member;
2184
2185                               specType.members.Clear();
2186                               for(member = symbol.type.members.first; member; member = member.next)
2187                               {
2188                                  NamedLink item { name = CopyString(member.name), data = member.data };
2189                                  specType.members.Add(item);
2190                               }
2191                            }
2192                            else if(symbol.type.kind == structType || symbol.type.kind == unionType)
2193                            {
2194                               Type member;
2195                               // Tricky stuff... will be removed from list only when ref count reaches 0
2196                               for(member = specType.members.first; member; member = member.next)
2197                                  member.refCount++;
2198                            }
2199                            else if(symbol.type.kind == functionType)
2200                            {
2201                               Type param;
2202                               specType.returnType.refCount++;
2203                               for(param = specType.params.first; param; param = param.next)
2204                                  param.refCount++;
2205                            }
2206                            else if(symbol.type.kind == pointerType || symbol.type.kind == arrayType)
2207                            {
2208                               specType.type.refCount++;
2209                               if(symbol.type.kind == arrayType)
2210                               {
2211                                  if(specType.arraySizeExp)
2212                                     specType.arraySizeExp = CopyExpression(specType.arraySizeExp);
2213                               }
2214
2215                            }
2216                         }
2217                         else
2218                            specType.enumName = CopyString(spec.id.string);
2219                      }
2220                      else
2221                         specType.enumName = CopyString(spec.id.string);
2222                   }
2223
2224                   if(spec.definitions)
2225                   {
2226                      ClassDef def;
2227                      for(def = spec.definitions->first; def; def = def.next)
2228                      {
2229                         if(def.type == declarationClassDef && def.decl.type == structDeclaration)
2230                         {
2231                            Declaration decl = def.decl;
2232                            if(decl.declarators)
2233                            {
2234                               Declarator d;
2235                               for(d = decl.declarators->first; d; d = d.next)
2236                               {
2237                                  Type memberType = ProcessType(decl.specifiers, d);
2238                                  specType.members.Add(memberType);
2239                               }
2240                            }
2241                            else if(decl.specifiers)
2242                            {
2243                               Type memberType = ProcessType(decl.specifiers, null);
2244                               specType.members.Add(memberType);
2245                            }
2246                         }
2247                      }
2248                   }
2249                   break;
2250                }
2251                else if(spec.type == subClassSpecifier)
2252                {
2253                   specType.kind = specType.kind = subClassType;
2254                   specType._class = spec._class.symbol; // FindClass(spec._class.name);
2255                }
2256                /*
2257                else if(spec.type == classSpecifier)
2258                {
2259                   specType._class = FindClass(spec.name);
2260                   specType.kind = classType;
2261                }
2262                */
2263             }
2264          }
2265          else if(!decl)
2266             specType.kind = ellipsisType;
2267       }
2268
2269       if(funcDecl)
2270       {
2271          Declarator d = funcDecl.declarator;
2272          Type funcType { };
2273          TypeName param;
2274
2275          funcType.kind = functionType;
2276          funcType.refCount = 1;
2277          if(funcDecl.function.parameters)
2278          {
2279             for(param = funcDecl.function.parameters->first; param; param = param.next)
2280             {
2281                /*
2282                if(param.typedObject)
2283                {
2284                   Type typedObjectType
2285                   {
2286                      refCount = 1;
2287                      byReference = param.byReference;
2288                      kind = TypeTypedObject;
2289                   };
2290                   funcType.params.Add(typedObjectType);
2291                }
2292                else*/
2293                   funcType.params.Add(ProcessType(param.qualifiers, param.declarator));
2294             }
2295          }
2296
2297          // Function returning a pointer...
2298          if(decl.type == pointerDeclarator)
2299          {
2300             Pointer pointer = decl.pointer.pointer;
2301             Type ptrType { };
2302             funcType.returnType = ptrType;
2303             funcType.returnType.refCount = 1;
2304             while(pointer)
2305             {
2306                ptrType.kind = pointerType;
2307                pointer = pointer.pointer;
2308                if(pointer)
2309                {
2310                   ptrType.type = Type { refCount = 1 };
2311                   ptrType = ptrType.type;
2312                }
2313             }
2314             ptrType.type = Type { refCount = 1 };
2315             *ptrType.type = specType;
2316          }
2317          else
2318          {
2319             funcType.returnType = Type { refCount = 1 };
2320             *funcType.returnType = specType;
2321          }
2322
2323          // TESTING: Added extendedDeclarator here
2324          while(d && (d.type == bracketsDeclarator || d.type == extendedDeclarator || d.type == extendedDeclaratorEnd))
2325          {
2326             if((d.type == extendedDeclarator || d.type == extendedDeclaratorEnd) && d.extended.extended && 
2327                (!strcmp(d.extended.extended, "__declspec(dllexport)") || !strcmp(d.extended.extended, "dllexport")))
2328             {
2329                dllExport = true;            
2330             }
2331             d = d.declarator;
2332          }
2333
2334          funcType.dllExport = dllExport;
2335
2336          if(d && d.type == pointerDeclarator)
2337          {
2338             Type ptrType;
2339             Identifier id;
2340
2341             if(d.declarator && d.declarator.type == arrayDeclarator)
2342             {
2343                // Arrays of pointers to functions (extremely tricky :()
2344                Pointer pointer = d.pointer.pointer;
2345
2346                // TO WORK ON: Fixed the order for the array...
2347                type.kind = arrayType;
2348                type.arraySizeExp = CopyExpression(d.declarator.array.exp);
2349                type.freeExp = true;
2350                if(d.declarator.array.enumClass)
2351                   type.enumClass = d.declarator.array.enumClass.symbol; // FindClass(d.declarator.array.enumClass.name);
2352                if(d.declarator.declarator && d.declarator.declarator.type == arrayDeclarator)
2353                {
2354                   Type tmpType = type;
2355                   Type inType;
2356                   type = ProcessType(null, d.declarator.declarator);
2357                   inType = type.type;
2358                   type.type = tmpType;
2359                   tmpType.type = inType;
2360                }
2361                else
2362                   type.type = ProcessType(null, d.declarator.declarator);
2363
2364                for(ptrType = type.type; ptrType && ptrType.kind && ptrType.type; ptrType = ptrType.type);
2365
2366                while(pointer)
2367                {
2368                   ptrType.kind = pointerType;
2369                   pointer = pointer.pointer;
2370                   if(pointer)
2371                   {
2372                      ptrType.type = Type { refCount = 1 };
2373                      ptrType = ptrType.type;
2374                   }
2375                }
2376                ptrType.type = ProcessType(specs, null);
2377             }
2378             else
2379             {
2380                // WARNING: Not caring if this declarator contains a declarator between
2381                //          the pointer and the function other than brackets (like in the case of array of pointers to functions)...
2382                // *********** Could it ever go in here???  Yes: void (* converters_table[10]) (); ***********
2383                Pointer pointer = d.pointer.pointer;
2384
2385                ptrType = type;
2386                while(pointer)
2387                {
2388                   ptrType.kind = pointerType;
2389                   ptrType.type = Type { refCount = 1 };
2390                   pointer = pointer.pointer;
2391                   if(pointer)
2392                      ptrType = ptrType.type;
2393                }
2394             }
2395
2396             *ptrType.type = funcType;
2397             id = GetDeclId(d);
2398             if(id)
2399             {
2400                if(id._class && !id._class.name)
2401                   ptrType.type.staticMethod =  true;
2402                else 
2403                {
2404                   // TODO : Ensure classSym has been resolved here... (Is this gonna cause problems? Supposed to do this later...)
2405                   if(!id.classSym)
2406                   {
2407                      if(id._class && id._class.name)
2408                      {
2409                         id.classSym = id._class.symbol; // FindClass(id._class.name);
2410                         /* TODO: Name Space Fix ups
2411                         if(!id.classSym)
2412                            id.nameSpace = eSystem_FindNameSpace(privateModule, id._class.name);
2413                         */
2414                      }
2415                   }
2416
2417                   ptrType.type.thisClass = id.classSym;
2418                   if(ptrType.type.thisClass && strcmp(ptrType.type.thisClass.string, "class"))
2419                      ptrType.type.extraParam = true;
2420                   else if(id._class && id._class.name && !strcmp(id._class.name, "any_object"))
2421                   {
2422                      ptrType.type.extraParam = true;
2423                      ptrType.type.thisClass = FindClass("class");
2424                   }
2425                }
2426
2427                type.name = CopyString(id.string);
2428             }
2429          }
2430          else if(!d || d.type == identifierDeclarator)
2431          {
2432
2433             *type = funcType;
2434             if(d)
2435             {
2436                if(d.identifier._class && d.identifier._class.type == templateTypeSpecifier)
2437                {
2438                   type.thisClassTemplate = d.identifier._class.templateParameter;
2439                   type.extraParam = true;
2440                }
2441                else
2442                {
2443                   if(d.identifier._class && !d.identifier._class.name)
2444                      type.staticMethod = true;
2445                   else
2446                   {
2447                      if(d.identifier._class && d.identifier._class.name && d.identifier._class.name[strlen(d.identifier._class.name)-1] == '&')
2448                      {
2449                         type.thisClass = FindClass("class");
2450                         type.byReference = true;
2451                      }
2452                      else
2453                         type.thisClass = d.identifier._class ? d.identifier._class.symbol /*FindClass(d.identifier._class.name)*/ : null;
2454                      if(type.thisClass && strcmp(type.thisClass.string, "class"))
2455                      {
2456                         type.extraParam = true;
2457                      }
2458                      else if(d.identifier._class && d.identifier._class.name && !strcmp(d.identifier._class.name, "any_object"))
2459                      {
2460                         type.extraParam = true;
2461                         type.thisClass = FindClass("class");
2462                      }
2463                      else if(d.identifier._class && d.identifier._class.name && !strcmp(d.identifier._class.name, "class"))
2464                      {
2465                         //type.extraParam = true;
2466                         type.thisClass = FindClass("class");
2467                         type.classObjectType = classPointer;
2468                      }
2469                   }
2470                }
2471                type.name = CopyString(d.identifier.string);
2472             }
2473          }
2474          delete funcType;
2475       }
2476       else if(decl && decl.type == pointerDeclarator)
2477       {
2478          if(decl.declarator && decl.declarator.type == arrayDeclarator)
2479          {
2480             // Arrays of pointers (tricky :))
2481             Identifier id;
2482             Pointer pointer = decl.pointer.pointer;
2483             Type ptrType;
2484
2485             // TO WORK ON: Fixed the order for the array...
2486             type.kind = arrayType;
2487             type.arraySizeExp = CopyExpression(decl.declarator.array.exp);
2488             type.freeExp = true;
2489             if(decl.declarator.array.enumClass)
2490                type.enumClass = decl.declarator.array.enumClass.symbol; // FindClass(decl.declarator.array.enumClass.name);
2491             if(decl.declarator.declarator && decl.declarator.declarator.type == arrayDeclarator)
2492             {
2493                Type tmpType = type;
2494                Type inType;
2495                type = ProcessType(null, decl.declarator.declarator);
2496                inType = type.type;
2497                type.type = tmpType;
2498                tmpType.type = inType;
2499             }
2500             else
2501                type.type = ProcessType(null, decl.declarator.declarator);
2502             /*
2503             type.type = ProcessType(null, decl.declarator.declarator);
2504             type.kind = arrayType;
2505             type.arraySizeExp = CopyExpression(decl.declarator.array.exp);
2506             type.arraySizeExp.freeExp = true;
2507             if(decl.array.enumClass)
2508                type.enumClass = FindClass(decl.array.enumClass.name);
2509             */
2510
2511             for(ptrType = type.type; ptrType && ptrType.kind && ptrType.type; ptrType = ptrType.type);
2512
2513             while(pointer)
2514             {
2515                ptrType.kind = pointerType;
2516                pointer = pointer.pointer;
2517                if(pointer)
2518                {
2519                   ptrType.type = Type { refCount = 1 };
2520                   ptrType = ptrType.type;
2521                }
2522             }
2523             ptrType.type = ProcessType(specs, null);
2524             id = GetDeclId(decl);
2525             if(id) type.name = CopyString(id.string);
2526          }
2527          else
2528          {
2529             Identifier id;
2530             Pointer pointer = decl.pointer.pointer;
2531             Type ptrType = type;
2532
2533             if(type.classObjectType)
2534             {
2535                type.byReference = true;
2536             }
2537             else
2538             {
2539                while(pointer)
2540                {
2541                   ptrType.kind = pointerType;
2542                   pointer = pointer.pointer;
2543                   if(pointer)
2544                   {
2545                      ptrType.type = Type { refCount = 1 };
2546                      ptrType = ptrType.type;
2547                   }
2548                }
2549                ptrType.type = ProcessType(specs, decl.declarator);
2550
2551                if(type.type.classObjectType)
2552                {
2553                   Type subType = type.type;
2554                   type.classObjectType = subType.classObjectType;
2555                   type.kind = subType.kind;
2556                   type._class = subType._class;
2557                   type.byReference = true;
2558
2559                   FreeType(subType);
2560                }
2561                id = GetDeclId(decl);
2562                if(id) type.name = CopyString(id.string);
2563             }
2564          }
2565       }
2566       else if(decl && decl.type == arrayDeclarator)
2567       {
2568          Identifier id;
2569
2570          type.kind = arrayType;
2571          
2572          type.arraySizeExp = CopyExpression(decl.array.exp);
2573          type.freeExp = true;
2574          if(decl.array.enumClass)
2575             type.enumClass = decl.array.enumClass.symbol; // FindClass(decl.array.enumClass.name);
2576          id = GetDeclId(decl);
2577
2578          // TO WORK ON: Fixed the order for the array...
2579          if(decl.declarator && decl.declarator.type == arrayDeclarator)
2580          {
2581             Type tmpType = type;
2582             Type inType;
2583             type = ProcessType(specs, decl.declarator);
2584             inType = type.type;
2585             type.type = tmpType;
2586             tmpType.type = inType;
2587          }
2588          else
2589             type.type = ProcessType(specs, decl.declarator);
2590
2591          if(id)
2592          {
2593             delete type.name;
2594             type.name = CopyString(id.string);
2595          }
2596       }
2597       else
2598       {
2599          if(!decl || decl.type == identifierDeclarator)
2600          {
2601             *type = specType;
2602             delete type.name;
2603             type.name = decl ? CopyString(decl.identifier.string) : null;
2604
2605          }   
2606       }
2607       delete specType;
2608    }
2609    return type;
2610 }
2611
2612 public Type ProcessTypeString(char * string, bool staticMethod)
2613 {
2614    OldList * specs = MkList();
2615    Declarator decl = SpecDeclFromString(string, specs, null);
2616    Type type = ProcessType(specs, decl);
2617    if(type && !type.thisClass && staticMethod) type.staticMethod = true;
2618    FreeList(specs, FreeSpecifier);
2619    if(decl) FreeDeclarator(decl);
2620    return type;
2621 }
2622
2623 Type MkClassTypeSymbol(Symbol symbol)
2624 {
2625    if(symbol)
2626    {
2627       Type type { kind = classType, _class = symbol };
2628       if(!type._class)
2629       {
2630          // Defaults to an int instead...
2631          type.kind = intType;
2632       }
2633       type.refCount = 1;
2634       return type;
2635    }
2636    return null;
2637 }
2638
2639 public Type MkClassType(char * name)
2640 {
2641    if(name)
2642    {
2643       Type type { kind = classType, _class = FindClass(name) };
2644       if(!type._class)
2645       {
2646          // Defaults to an int instead...
2647          type.kind = intType;
2648       }
2649       type.refCount = 1;
2650       return type;
2651    }
2652    return null;
2653 }
2654
2655 AsmField MkAsmField(char * command, Expression expression)
2656 {
2657    return { command = command, expression = expression };
2658 }
2659
2660 Statement MkAsmStmt(Specifier spec, char * statements, OldList inputFields, OldList outputFields, OldList clobberedFields)
2661 {
2662    return { type = asmStmt, asmStmt.spec = spec, asmStmt.statements = statements, 
2663       asmStmt.inputFields = inputFields, asmStmt.outputFields = outputFields, 
2664       asmStmt.clobberedFields = clobberedFields };
2665 }
2666
2667 ClassDef MkClassDefPropertyWatch(PropertyWatch watcher)
2668 {
2669    return { type = propertyWatchClassDef, propertyWatch = watcher };
2670 }
2671
2672 Statement MkFireWatchersStmt(Expression object, OldList watches)
2673 {
2674    return { type = fireWatchersStmt, _watch.object = object, _watch.watches = watches };
2675 }
2676
2677 Statement MkStopWatchingStmt(Expression watcher, Expression object, OldList watches)
2678 {
2679    return { type = stopWatchingStmt, _watch.watcher = watcher, _watch.object = object, _watch.watches = watches };
2680 }
2681
2682 Statement MkWatchStmt(Expression watcher, Expression object, OldList watches)
2683 {
2684    return { type = watchStmt, _watch.watcher = watcher, _watch.object = object, _watch.watches = watches };
2685 }
2686
2687 PropertyWatch MkDeleteWatch(Statement compound)
2688 {
2689    return { compound = compound, deleteWatch = true };
2690 }
2691
2692 PropertyWatch MkPropertyWatch(OldList properties, Statement compound)
2693 {
2694    return { compound = compound, properties = properties };
2695 }
2696
2697 Expression MkExpClass(OldList * specifiers, Declarator decl)
2698 {
2699    return { type = classExp, _classExp.specifiers = specifiers, _classExp.decl = decl };
2700 }
2701
2702 Expression MkExpClassData(Identifier id)
2703 {
2704    return { type = classDataExp, classData.id = id };
2705 }
2706
2707
2708 External MkExternalDBTable(DBTableDef table)
2709 {
2710    return { type = dbtableExternal, table = table };
2711 }
2712
2713 DBTableDef MkDBTableDef(char * name, Symbol symbol, OldList * definitions)
2714 {
2715    return { name = name, symbol = symbol, definitions = definitions };
2716 }
2717
2718 DBTableEntry MkDBFieldEntry(TypeName type, Identifier id, char * name)
2719 {
2720    return { type = fieldEntry, dataType = type, id = id, name = name };
2721 }
2722
2723 DBIndexItem MkDBIndexItem(Identifier id, Order order)
2724 {
2725    return { id = id, order = order };
2726 }
2727
2728 DBTableEntry MkDBIndexEntry(OldList * items, Identifier id)
2729 {
2730    return { type = indexEntry, items = items, id = id };
2731 }
2732
2733 Expression MkExpDBOpen(Expression ds, Expression dbName)
2734 {
2735    return { type = dbopenExp, dbopen.ds = ds, dbopen.name = dbName };
2736 }
2737
2738 Expression MkExpDBField(char * table, Identifier id)
2739 {
2740    return { type = dbfieldExp, db.table = table, db.id = id };
2741 }
2742
2743 Expression MkExpDBIndex(char * table, Identifier id)
2744 {
2745    return { type = dbindexExp, db.table = table, db.id = id };
2746 }
2747
2748 Expression MkExpDBTable(char * table)
2749 {
2750    return { type = dbtableExp, db.table = table };
2751 }
2752
2753 Expression MkExpArray(OldList * expressions)
2754 {
2755    return { type = arrayExp, list = expressions };
2756 }
2757
2758 Expression GetTemplateArgExpByName(char * paramName, Class curClass, TemplateParameterType tplType)
2759 {
2760    Expression argExp = null;
2761    Class _class = curClass ? curClass : ((curExternal && curExternal.type == functionExternal && curExternal.function) ? curExternal.function._class : null);
2762    if(_class)
2763    {
2764       int id = 0;
2765       ClassTemplateParameter curParam;
2766       Class sClass;
2767       for(sClass = _class; sClass; sClass = sClass.base)
2768       {
2769          id = 0;
2770          for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
2771          {
2772             if(!strcmp(curParam.name, paramName))
2773             {
2774                for(sClass = sClass.base; sClass; sClass = sClass.base)
2775                   id += sClass.templateParams.count;
2776                break;
2777             }
2778             id++;
2779          }
2780          if(curParam) break;
2781       }
2782
2783       if(curParam && curParam.type != tplType)
2784          curParam = null;
2785
2786       if(curParam)
2787       {
2788          char idString[32];
2789          char className[1024];
2790          Expression classExp;
2791          
2792          sprintf(idString, "%d", id);
2793          strcpy(className, "__ecereClass_");
2794          FullClassNameCat(className, _class.fullName, true);
2795          MangleClassName(className);
2796          DeclareClass(FindClass(_class.fullName), className);
2797
2798          argExp = MkExpIndex((/*pointer ? MkExpPointer : */MkExpMember)
2799                (MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class")) /*MkExpIdentifier(MkIdentifier(className))*/, 
2800                MkIdentifier("templateArgs")), MkListOne(MkExpConstant(idString)));
2801       }
2802    }
2803    return argExp; 
2804 }
2805
2806 Expression GetTemplateArgExp(TemplateParameter param, Class curClass, bool pointer)
2807 {
2808    return param.identifier ? GetTemplateArgExpByName(param.identifier.string, curClass, type) : null;
2809 }
2810
2811 /*char * CreateMsgID(char * string, char * context)
2812 {
2813    int lenString = strlen(string), lenContext = strlen(context);
2814    char * msgid = new char[lenString + lenContext + 20];
2815    memcpy(msgid, string, lenString);
2816    memcpy(msgid+lenString, " [msgctxt: ", 11);
2817    memcpy(msgid+lenString+11, context, lenContext);
2818    memcpy(msgid+lenString+11+lenContext, "]", 2);
2819    return msgid;
2820 }*/
2821
2822 public void OutputIntlStrings()
2823 {
2824    if(intlStrings.count)
2825    {
2826       char * srcFile = GetSourceFile();
2827       char * objFile = GetOutputFile();
2828       char srcFileFixed[MAX_LOCATION];
2829       char potFile[MAX_LOCATION];
2830       File f;
2831       ChangeExtension(objFile, "bowl", potFile);
2832       f = FileOpen(potFile, write);
2833       if(f)
2834       {
2835          char * filePrefix = "";
2836          if(!(srcFile[0] && (srcFile[1] == ':' || srcFile[0] == '/')))
2837             filePrefix = (GetRuntimePlatform() == win32) ? ".\\" : "./";
2838          GetSystemPathBuffer(srcFileFixed, srcFile);
2839          for(s : intlStrings)
2840          {
2841             // TOFIX: (#654) ContextStringPair * pair = &s;
2842             ContextStringPair pair = &s;
2843             for(l : s)
2844                f.Printf("#: %s%s:%d\n", filePrefix, srcFileFixed, l.start.line);
2845              // PoEdit now preserves and distinguish msgctxt
2846             if(pair.context)
2847                f.Printf("msgctxt \"%s\"\n", pair.context);
2848             f.Printf("msgid \"%s\"\n", pair.string);
2849             f.Printf("msgstr \"%s\"\n\n", pair.string);
2850          }
2851          delete f;
2852       }
2853       intlStrings.Free();
2854    }
2855 }
2856
2857 default extern OldList * ast;
2858 default extern int yyparse ();
2859
2860 public void SetAST(OldList * list) { ast = list; }
2861 public OldList * GetAST() { return ast; }
2862 public void ParseEc()
2863 {
2864    yyparse();
2865 }