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