Initial git commit -- Transition from CodeGuard repository
[sdk] / compiler / libec / src / output.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4
5 #include "grammar.eh"
6
7 int outputLine;
8
9 bool memoryGuard = false;
10 public void SetMemoryGuard(bool b) { memoryGuard = b; } public bool GetMemoryGuard() { return memoryGuard; }
11
12 static void OutputIdentifier(Identifier id, File f)
13 {
14    if(id)
15    {
16       /*
17       TODO: Name Space Fix ups
18       if(id.nameSpace && id.nameSpace->name)
19       {
20          f.Puts(id.nameSpace->name);
21       }
22       else */if(id._class)
23       {
24          if(id._class.type == templateTypeSpecifier)
25          {
26             if(id._class.templateParameter && id._class.templateParameter.identifier && id._class.templateParameter.identifier.string)
27                f.Puts(id._class.templateParameter.identifier.string);
28          }
29          else
30          {
31             if(id._class.name)
32             {
33                if(!strcmp(id._class.name, "class"))
34                   f.Puts("typed_object");
35                else
36                   f.Puts(id._class.name);
37             }
38          }
39          f.Puts("::");
40       }
41    }
42    f.Puts((id && id.string) ? id.string : "(null identifier)");
43 }
44
45 static void OutputOperator(int op, File f)
46 {
47    switch(op)
48    {
49       case INC_OP: f.Puts("++"); break;
50       case DEC_OP: f.Puts("--");break;
51       case SIZEOF: f.Puts("sizeof "); break;
52       case LEFT_OP: f.Puts("<<"); break;
53       case RIGHT_OP: f.Puts(">>"); break;
54       case LE_OP: f.Puts("<="); break;
55       case GE_OP: f.Puts(">="); break;
56       case EQ_OP: f.Puts("=="); break;
57       case NE_OP: f.Puts("!="); break;
58       case AND_OP: f.Puts("&&"); break;
59       case OR_OP: f.Puts("||"); break;
60            case MUL_ASSIGN: f.Puts("*="); break;
61            case DIV_ASSIGN: f.Puts("/="); break;
62            case MOD_ASSIGN: f.Puts("%="); break;
63            case ADD_ASSIGN: f.Puts("+="); break;
64            case SUB_ASSIGN: f.Puts("-="); break;
65            case LEFT_ASSIGN: f.Puts("<<="); break;
66            case RIGHT_ASSIGN: f.Puts(">>="); break;
67            case AND_ASSIGN: f.Puts("&="); break;
68            case XOR_ASSIGN: f.Puts("^="); break;
69            case OR_ASSIGN: f.Puts("|="); break;
70       case '&': case '*': case '+': case '-': case '~': case '!': case '/': case '%':
71       case '<': case '>': case '|': case '^': case '=':
72          f.Putc((char)op);
73          break;
74       case DELETE: f.Puts("delete "); break;
75    }
76 }
77
78 public void OutputTypeName(TypeName type, File f)
79 {
80    /*if(type.typedObject) 
81    {
82       //f.Puts("Class * class, void *");
83       f.Puts("class");
84    }
85    else */if(type.qualifiers)
86    {
87       Specifier spec;
88       for(spec = type.qualifiers->first; spec; spec = spec.next)
89       {
90          OutputSpecifier(spec, f);
91          if(spec.next) f.Puts(" ");
92       }
93    }
94    if(type.declarator) 
95    {
96       f.Puts(" ");
97       OutputDeclarator(type.declarator, f);
98    }
99
100    if(/*!type.typedObject && */!type.qualifiers && !type.declarator)
101       f.Puts("...");
102
103 }
104
105 public void OutputExpression(Expression exp, File f)
106 {
107    switch(exp.type)
108    {
109       case classExp:
110          f.Puts("class(");
111          if(exp._classExp.specifiers)
112          {
113             Specifier spec;
114             for(spec = exp._classExp.specifiers->first; spec; spec = spec.next)
115             {
116                OutputSpecifier(spec, f);
117                if(spec.next) f.Puts(" ");
118             }
119             if(exp._classExp.decl) 
120             {
121                f.Puts(" ");
122                OutputDeclarator(exp._classExp.decl, f);
123             }
124             f.Puts(")");
125          }
126          break;
127       case extensionCompoundExp:
128          f.Puts("__extension__ (");
129          OutputStatement(exp.compound, f);
130          f.Puts(")");
131          break;
132       case newExp:
133          f.Puts("new ");
134          f.Puts(" ");
135          OutputTypeName(exp._renew.typeName, f);
136          f.Puts("[");
137          OutputExpression(exp._renew.size, f);
138          f.Puts("]");
139          break;
140       case new0Exp:
141          f.Puts("new0 ");
142          f.Puts(" ");
143          OutputTypeName(exp._renew.typeName, f);
144          f.Puts("[");
145          OutputExpression(exp._renew.size, f);
146          f.Puts("]");
147          break;
148       case renewExp:
149          f.Puts("renew ");
150          OutputExpression(exp._renew.exp, f);
151          f.Puts(" ");
152          OutputTypeName(exp._renew.typeName, f);
153          f.Puts("[");
154          OutputExpression(exp._renew.size, f);
155          f.Puts("]");
156          break;
157       case renew0Exp:
158          f.Puts("renew0 ");
159          OutputExpression(exp._renew.exp, f);
160          f.Puts(" ");
161          OutputTypeName(exp._renew.typeName, f);
162          f.Puts("[");
163          OutputExpression(exp._renew.size, f);
164          f.Puts("]");
165          break;
166       case identifierExp:
167          if(exp.identifier)
168             OutputIdentifier(exp.identifier, f);
169          break;
170       case instanceExp:
171          if(exp.instance)
172             OutputInstance(exp.instance, f);
173          break;
174       case constantExp:
175          if(exp.constant)
176             f.Puts(exp.constant);
177          else
178             printf("");
179          break;
180       case stringExp:
181          if(exp.string)
182             f.Puts(exp.string);
183          break;
184       case opExp:
185          if(exp.op.exp1)
186          {
187             OutputExpression(exp.op.exp1, f);
188             if(exp.op.exp2)
189                f.Puts(" ");
190          }
191          OutputOperator(exp.op.op, f);
192          if(exp.op.exp2)
193          {
194             if(exp.op.exp1 || (exp.op.exp2.type == opExp && !exp.op.exp2.op.exp1 && exp.op.exp2.op.op == exp.op.op))
195                f.Puts(" ");
196             OutputExpression(exp.op.exp2, f);
197          }
198          break;
199       case extensionExpressionExp: 
200       case bracketsExp:
201       {
202          Expression expression;
203          if(exp.type == extensionExpressionExp)
204             f.Puts("__extension__ (");
205          f.Puts("(");
206          if(exp.list)
207          {
208             for(expression = exp.list->first; expression; expression = expression.next)
209             {
210                OutputExpression(expression, f);
211                if(expression.next) f.Puts(", ");
212             }
213          }
214          f.Puts(")");
215          break;
216       }
217       case indexExp:
218       {
219          Expression expression;
220          if(exp.index.exp)
221             OutputExpression(exp.index.exp, f);
222          f.Puts("[");
223          if(exp.index.index)
224             for(expression = exp.index.index->first; expression; expression = expression.next)
225             {
226                OutputExpression(expression, f);
227                if(expression.next) f.Puts(", ");
228             }
229          f.Puts("]");
230          break;
231       }
232       case callExp:
233       {
234          OutputExpression(exp.call.exp, f);
235          f.Puts("(");
236          if(exp.call.arguments)
237          {
238             Expression expression;
239             for(expression = exp.call.arguments->first; expression; expression = expression.next)
240             {
241                OutputExpression(expression, f);
242                if(expression.next) f.Puts(", ");
243             }
244          }
245          f.Puts(")");
246          break;
247       }
248       case memberExp:
249          if(exp.member.exp)
250             OutputExpression(exp.member.exp, f);
251          f.Puts(".");
252          if(exp.member.member)
253             OutputIdentifier(exp.member.member, f);
254          break;
255       case pointerExp:
256          OutputExpression(exp.member.exp, f);
257          f.Puts("->");
258          OutputIdentifier(exp.member.member, f);
259          break;
260       case typeSizeExp:
261          f.Puts("sizeof(");
262          OutputTypeName(exp.typeName, f);
263          f.Puts(")");
264          break;
265       case extensionInitializerExp:
266          f.Puts("__extension__ (");
267          if(exp.initializer.typeName)
268             OutputTypeName(exp.initializer.typeName, f);
269          f.Puts(")");
270          if(exp.initializer.initializer)
271             OutputInitializer(exp.initializer.initializer, f);
272          break;
273       case castExp:
274          f.Puts("(");
275          OutputTypeName(exp.cast.typeName, f);
276          f.Puts(")");
277          if(exp.cast.exp)
278             OutputExpression(exp.cast.exp, f);
279          break;
280       case conditionExp:
281          OutputExpression(exp.cond.cond, f);
282          f.Puts(" ? ");
283          {
284             Expression expression;
285             for(expression = exp.cond.exp->first; expression; expression = expression.next)
286             {
287                OutputExpression(expression, f);
288                if(expression.next) f.Puts(", ");
289             }
290          }
291          f.Puts(" : ");
292          OutputExpression(exp.cond.elseExp, f);
293          break;
294       case vaArgExp:
295          f.Puts("__builtin_va_arg(");
296          OutputExpression(exp.vaArg.exp, f);
297          f.Puts(", ");
298          OutputTypeName(exp.vaArg.typeName, f);
299          f.Puts(")");
300          break;
301       case arrayExp:
302          f.Puts("[");
303          if(exp.list)
304          {
305             Expression expression;
306             for(expression = exp.list->first; expression; expression = expression.next)
307             {
308                OutputExpression(expression, f);
309                if(expression.next) f.Puts(", ");
310             }
311          }
312          f.Puts("]");
313          break;
314    }
315 }
316
317 static void OutputAsmField(AsmField field, File f)
318 {
319    f.Puts(field.command);
320    if(field.expression)
321    {
322       f.Puts("(");
323       OutputExpression(field.expression, f);
324       f.Puts(")");
325    }
326 }
327
328 static void OutputStatement(Statement stmt, File f)
329 {
330    char name[MAX_FILENAME] = "";
331    char origName[MAX_FILENAME] = "";
332
333    /*
334    if(sourceFile)
335       eString_GetLastDirectory(sourceFile, name);
336    */
337
338    if(inCompiler)
339    {
340       if(yylloc.start.included)
341       {
342          //GetWorkingDir(name, sizeof(name));
343          PathCat(name, GetIncludeFileFromID(yylloc.start.included));
344       }
345       else if(sourceFile)
346       {
347          //GetWorkingDir(name, sizeof(name));
348          PathCat(name, sourceFile);
349       }
350       ChangeCh(name, '\\', '/');
351
352       //GetWorkingDir(origName, sizeof(origName));
353       PathCat(origName, outputFile);
354       ChangeCh(origName, '\\', '/');
355    }
356
357
358    if(inCompiler && outputLineNumbers && stmt.loc.start.line) 
359    {
360       /*if(stmt.loc.start.line == 1)
361          printf("bug");*/
362       f.Printf("\n#line %d \"%s\"\n", stmt.loc.start.line, name);
363       outputLine += 2;
364    }
365
366    switch(stmt.type)
367    {
368       case labeledStmt:
369          OutputIdentifier(stmt.labeled.id, f);
370          f.Puts(":\n");
371          outputLine ++;
372          OutputStatement(stmt.labeled.stmt, f);
373          break;
374       case caseStmt:
375          if(stmt.caseStmt.exp)
376          {
377             f.Puts("case ");
378             OutputExpression(stmt.caseStmt.exp, f);
379             f.Puts(":\n");
380             outputLine ++;
381          }
382          else
383          {
384             f.Puts("default:\n");
385             outputLine ++;
386          }
387          if(stmt.caseStmt.stmt)
388             OutputStatement(stmt.caseStmt.stmt, f);
389          break;
390       case compoundStmt:
391       {
392          f.Puts("{\n");
393          outputLine ++;
394          if(stmt.compound.declarations)
395          {
396             Declaration decl;
397             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
398             {
399                OutputDeclaration(decl, f);
400
401             }
402          }
403          if(stmt.compound.statements)
404          {
405             Statement statement;
406             if(stmt.compound.declarations)
407             {
408                f.Puts("\n");
409                outputLine ++;
410             }
411             for(statement = stmt.compound.statements->first; statement; statement = statement.next)
412             {
413                OutputStatement(statement, f);
414                f.Puts("\n");
415                outputLine ++;
416             }
417          }
418          if(inCompiler && outputLineNumbers && stmt.loc.end.line) 
419          {
420             /*if(stmt.loc.end.line == 1)
421                printf("bug");*/
422
423             f.Printf("\n#line %d \"%s\"\n", stmt.loc.end.line, name);
424             outputLine += 2;
425          }
426
427          f.Puts("}");
428          break;
429       }
430       case expressionStmt:
431       {
432          if(stmt.expressions)
433          {
434             Expression exp;
435             for(exp = stmt.expressions->first; exp; exp = exp.next)
436             {
437                OutputExpression(exp, f);
438                if(exp.next) f.Puts(", ");
439             }
440          }
441          f.Puts(";");
442          break;
443       }
444       case ifStmt:
445       {
446          Expression exp;
447          f.Puts("if(");
448          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
449          {
450             OutputExpression(exp, f);
451             if(exp.next) f.Puts(", ");
452          }
453          f.Puts(")\n");
454          outputLine ++;
455          if(stmt.ifStmt.stmt)
456             OutputStatement(stmt.ifStmt.stmt, f);
457          if(stmt.ifStmt.elseStmt)
458          {
459             f.Puts("\n");
460             outputLine ++;
461             f.Puts("else");
462             if(stmt.ifStmt.elseStmt.type != ifStmt)
463             {
464                f.Puts("\n");
465                outputLine ++;
466             }
467             else
468                f.Puts(" ");
469             OutputStatement(stmt.ifStmt.elseStmt, f);
470          }
471          break;
472       }
473       case switchStmt:
474       {
475          Expression exp;
476          f.Puts("switch(");
477          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
478          {
479             OutputExpression(exp, f);
480             if(exp.next) f.Puts(", ");
481          }
482          f.Puts(")\n");
483          outputLine ++;
484          OutputStatement(stmt.switchStmt.stmt, f);
485          break;
486       }
487       case whileStmt:
488       {
489          Expression exp;
490          f.Puts("while(");
491          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
492          {
493             OutputExpression(exp, f);
494             if(exp.next) f.Puts(", ");
495          }
496          f.Puts(")\n");
497          outputLine ++;
498          OutputStatement(stmt.whileStmt.stmt, f);
499          break;
500       }
501       case doWhileStmt:
502       {
503          Expression exp;
504          f.Puts("do\n");
505          outputLine ++;
506          OutputStatement(stmt.whileStmt.stmt, f);
507          f.Puts("while(");
508          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
509          {
510             OutputExpression(exp, f);
511             if(exp.next) f.Puts(", ");
512          }
513          f.Puts(");");
514          break;
515       }
516       case forStmt:
517       {
518          Expression exp;
519          f.Puts("for(");
520          OutputStatement(stmt.forStmt.init, f);
521          f.Puts(" ");
522          OutputStatement(stmt.forStmt.check, f);
523          f.Puts(" ");
524          if(stmt.forStmt.increment)
525          {
526             // TESTING THIS HERE FOR FOR INCREMENT
527             if(inCompiler && outputLineNumbers && stmt.loc.end.line) 
528             {
529                /*if(stmt.loc.end.line == 1)
530                   printf("bug");*/
531
532                f.Printf("\n#line %d \"%s\"\n", stmt.loc.end.line, name);
533                outputLine += 2;
534             }
535
536             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
537             {
538                OutputExpression(exp, f);
539                if(exp.next) f.Puts(", ");
540             }
541          }
542          f.Puts(")\n");
543          outputLine ++;
544          OutputStatement(stmt.forStmt.stmt, f);
545          break;
546       }
547       case gotoStmt:
548       {
549          f.Puts("goto ");
550          OutputIdentifier(stmt.gotoStmt.id, f);
551          f.Puts(";");
552          break;
553       }
554       case continueStmt:
555          f.Puts("continue;");
556          break;
557       case breakStmt:
558          f.Puts("break;");
559          break;
560       case returnStmt:
561       {
562          Expression exp;
563
564          if(inCompiler && memoryGuard)
565          {
566             Expression exp = stmt.expressions ? stmt.expressions->last : null;
567             f.Printf("{ ");
568             if(exp && exp.expType)
569             {
570                
571                char string[1024] = "";
572                OldList * specs = MkList();
573                Declarator decl;
574                TypeName typeName;
575                if(exp.expType.kind == templateType)
576                {
577                   if(exp.expType.templateParameter.dataTypeString)
578                      decl = SpecDeclFromString(exp.expType.templateParameter.dataTypeString, specs,
579                         MkDeclaratorIdentifier(MkIdentifier("__ecereReturnVal")));
580                   else if(exp.expType.templateParameter.dataType)
581                   {
582                      delete specs;
583                      specs = CopyList(exp.expType.templateParameter.dataType.specifiers, CopySpecifier);
584                      decl = PlugDeclarator(/*CopyDeclarator(*/exp.expType.templateParameter.dataType.decl/*)*/, 
585                         MkDeclaratorIdentifier(MkIdentifier("__ecereReturnVal")));
586                   }
587                   else
588                   {
589                      ListAdd(specs, MkSpecifierName("uint64"));
590                      decl = MkDeclaratorIdentifier(MkIdentifier("__ecereReturnVal"));
591                   }
592                }
593                else
594                {
595                   PrintType(exp.expType, string, true, true);
596                   decl = SpecDeclFromString(string, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereReturnVal")));
597                }
598
599                typeName = MkTypeName(specs, decl);
600                InstDeclPassTypeName(typeName, false);
601                OutputTypeName(typeName, f);
602                f.Printf(";");
603                FreeTypeName(typeName);
604             }
605          }
606          if(!memoryGuard)
607             f.Puts("return ");
608          else 
609          {
610             Expression exp = stmt.expressions ? stmt.expressions->last : null;
611             if(exp && exp.expType)
612                f.Printf("__ecereReturnVal = ");
613          }
614
615          if(stmt.expressions)
616          {
617             for(exp = stmt.expressions->first; exp; exp = exp.next)
618             {
619                OutputExpression(exp, f);
620                if(exp.next) f.Puts(", ");
621             }
622          }
623          f.Puts(";");
624
625          if(inCompiler && memoryGuard)
626          {
627             Expression exp = stmt.expressions ? (Expression)stmt.expressions->last : null;
628             f.Printf(" __ecereNameSpace__ecere__com__MemoryGuard_PopLoc();");
629             if(exp && exp.expType)
630                f.Printf("return __ecereReturnVal;");
631             else
632                f.Printf("return;");
633
634             f.Printf("}");
635          }
636
637          break;
638       }
639       case asmStmt:
640       {
641          AsmField field;
642          f.Puts("__asm__ ");
643          if(stmt.asmStmt.spec)
644             OutputSpecifier(stmt.asmStmt.spec, f);
645          f.Puts("(");
646          f.Puts(stmt.asmStmt.statements);
647
648          if(stmt.asmStmt.inputFields || stmt.asmStmt.outputFields || stmt.asmStmt.clobberedFields)
649          {
650             f.Puts(":");
651             if(stmt.asmStmt.inputFields)
652             {
653                for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
654                {
655                   if(field.prev) f.Puts(",");
656                   OutputAsmField(field, f);
657                }
658             }
659          }
660          if(stmt.asmStmt.outputFields || stmt.asmStmt.clobberedFields)
661          {
662             f.Puts(":");
663             if(stmt.asmStmt.outputFields)
664             {
665                for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
666                {
667                   if(field.prev) f.Puts(",");
668                   OutputAsmField(field, f);
669                }
670             }
671          }
672          if(stmt.asmStmt.clobberedFields)
673          {
674             f.Puts(":");
675             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
676             {
677                if(field.prev) f.Puts(",");
678                OutputAsmField(field, f);
679             }
680          }
681          f.Puts(");\n");
682          break;
683       }
684    }
685
686    if(inCompiler && outputLineNumbers && stmt.loc.start.line) 
687    {
688       f.Printf("\n#line %d \"%s\"\n", outputLine+2, origName);
689       outputLine += 2;
690    }
691 }
692
693 static void OutputPointer(Pointer ptr, File f)
694 {
695    f.Puts("*");
696    if(ptr.qualifiers)
697    {
698       Specifier spec;
699       f.Puts(" ");
700       for(spec = ptr.qualifiers->first; spec; spec = spec.next)
701       {
702          OutputSpecifier(spec, f);
703          if(spec.next) f.Puts(" ");
704       }
705    }
706    if(ptr.pointer)
707    {
708       OutputPointer(ptr.pointer, f);
709    }
710 }
711
712 static void OutputDeclarator(Declarator decl, File f)
713 {
714    switch(decl.type)
715    {
716       case structDeclarator:
717          if(decl.declarator)
718          {
719             OutputDeclarator(decl.declarator, f);
720          }
721          if(decl.structDecl.exp)
722          {
723             f.Puts(" : ");
724             OutputExpression(decl.structDecl.exp, f);
725          }
726          if(decl.structDecl.posExp)
727          {
728             f.Puts(" : ");
729             OutputExpression(decl.structDecl.posExp, f);
730          }
731          if(decl.structDecl.attrib)
732          {
733             f.Puts(" ");
734             f.Puts(decl.structDecl.attrib);
735          }
736          break;
737       case identifierDeclarator:
738          OutputIdentifier(decl.identifier, f);
739          break;
740       case bracketsDeclarator:
741          f.Puts("(");
742          OutputDeclarator(decl.declarator, f);
743          f.Puts(")");
744          break;
745       case extendedDeclarator:
746          f.Puts(decl.extended.extended);
747          f.Puts(" ");
748          OutputDeclarator(decl.declarator, f);
749          break;
750       case extendedDeclaratorEnd:
751          OutputDeclarator(decl.declarator, f);
752          f.Puts(" ");
753          f.Puts(decl.extended.extended);
754          break;
755       case arrayDeclarator:
756          if(decl.declarator)
757          {
758             OutputDeclarator(decl.declarator, f);
759          }
760          f.Puts("[");
761          if(decl.array.exp)
762          {
763             // Hacked this here
764             ProcessExpressionType(decl.array.exp);
765             ComputeExpression(decl.array.exp);
766
767             OutputExpression(decl.array.exp, f);
768          }
769          else if(decl.array.enumClass)
770          {
771             Symbol _class = decl.array.enumClass.symbol; // FindClass(decl.array.enumClass.name);
772             if(_class && _class.registered)
773             {
774                f.Printf("%d", eClass_GetProperty(_class.registered, "enumSize"));
775             }            
776          }
777          f.Puts("]");
778          break;
779       case functionDeclarator:
780       {
781          TypeName param;
782
783          if(decl.declarator)
784             OutputDeclarator(decl.declarator, f);
785          f.Puts("(");
786          if(decl.function.parameters && decl.function.parameters->first)
787          {
788             for(param = decl.function.parameters->first; param; param = param.next)
789             {
790                OutputTypeName(param, f);
791                if(param.next)
792                   f.Puts(", ");
793             }
794          }
795          f.Puts(")");
796          break;
797       }
798       case pointerDeclarator:
799          if(decl.pointer.pointer) OutputPointer(decl.pointer.pointer, f);
800          if(decl.declarator) 
801          {
802             f.Puts(" ");
803             OutputDeclarator(decl.declarator, f);
804          }
805          break;
806    }
807 }
808
809 static void OutputEnumerator(Enumerator enumerator, File f)
810 {
811    OutputIdentifier(enumerator.id, f);
812    if(enumerator.exp)
813    {
814       f.Puts(" = ");
815       OutputExpression(enumerator.exp, f);
816    }
817 }
818
819 static void OutputSpecifier(Specifier spec, File f)
820 {
821    switch(spec.type)
822    {
823       case baseSpecifier:
824          switch(spec.specifier)
825          {
826             // Storage Class
827             case TYPEDEF:
828                f.Puts("typedef");
829                break;
830             case EXTERN:
831                f.Puts("extern");
832                break;
833             case STATIC:
834                f.Puts("static");
835                break;
836             case AUTO:
837                f.Puts("auto");
838                break;
839             case REGISTER:
840                f.Puts("register");
841                break;
842
843             // Qualifier
844             case CONST:
845                f.Puts("const");
846                break;
847             case VOLATILE:
848                f.Puts("volatile");
849                break;
850
851             // Type Specifier
852             case VOID:
853                f.Puts("void");
854                break;
855             case CHAR:
856                f.Puts("char");
857                break;
858             case SHORT:
859                f.Puts("short");
860                break;
861             case INT:
862                f.Puts("int");
863                break;
864             case UINT:
865                f.Puts("unsigned int");
866                break;
867             case INT64:
868                //f.Puts("__int64");
869                //f.Puts("int64");
870                f.Puts("long long");
871                break;
872             case VALIST:
873                f.Puts("__builtin_va_list");
874                break;
875             case LONG:
876                f.Puts("long");
877                break;
878             case FLOAT:
879                f.Puts("float");
880                break;
881             case DOUBLE:
882                f.Puts("double");
883                break;
884             case SIGNED:
885                f.Puts("signed");
886                break;
887             case UNSIGNED:
888                f.Puts("unsigned");
889                break;
890             case TYPED_OBJECT:
891                f.Puts("typed_object");
892                break;
893             case ANY_OBJECT:
894                f.Puts("any_object");
895                break;
896             case CLASS:
897                f.Puts("class");
898                break;
899             case THISCLASS:
900                f.Puts("thisclass");
901                break;
902          }
903          break;
904       case extendedSpecifier:
905       case nameSpecifier:
906       //case classSpecifier:
907          if(spec.name && !strcmp(spec.name, "class"))
908          {
909             f.Puts("typed_object");
910          }
911          else
912          {
913             Symbol symbol = spec.symbol; // FindClass(spec.name);
914             // WILL HAVE TO VERIFY THESE ELSEWHERE...
915             if(!symbol && spec.name)
916                symbol = FindClass(spec.name);
917             if(symbol)
918             {
919                f.Puts(symbol.string ? symbol.string : "(null)");
920             }
921             else if(spec.name)
922                f.Puts(spec.name);
923          }
924          break;
925       case enumSpecifier:
926       {
927          f.Puts("enum");
928          if(spec.id)
929          {
930             f.Puts(" ");
931             OutputIdentifier(spec.id, f);
932          }
933          if(spec.list)
934          {
935             Enumerator enumerator;
936             f.Puts("\n{\n");
937             outputLine += 2;
938             for(enumerator = spec.list->first; enumerator; enumerator = enumerator.next)
939             {
940                OutputEnumerator(enumerator, f);
941                if(enumerator.next) f.Puts(", ");
942             }
943             f.Puts("\n}");
944             outputLine ++;
945          }
946          break;
947       }
948       case structSpecifier:
949       case unionSpecifier:
950       {
951          f.Puts((spec.type == structSpecifier) ? "struct" : "union");
952          if(spec.id)
953          {
954             f.Puts(" ");
955             OutputIdentifier(spec.id, f);
956          }
957          if(spec.definitions)
958          {
959             ClassDef def;
960             f.Puts("\n{\n");
961             outputLine += 2;
962             for(def = spec.definitions->first; def; def = def.next)
963             {
964                //OutputDeclaration(decl, f);
965                OutputClassDef(def, f);
966             }
967             f.Puts("}");
968          }
969          break;
970       }
971       case typeOfSpecifier:
972          f.Puts("__typeof(");
973          OutputExpression(spec.expression, f);
974          f.Puts(")");                  
975          break;
976       case subClassSpecifier:
977          f.Puts("subclass(");
978          OutputSpecifier(spec._class, f);
979          f.Puts(")");                  
980          break;
981       case templateTypeSpecifier:
982          OutputIdentifier(spec.templateParameter.identifier, f);
983          break;
984    }
985 }
986
987 static void OutputInitializer(Initializer initializer, File f)
988 {
989    char name[MAX_FILENAME] = "";
990    char origName[MAX_FILENAME] = "";
991
992    /*
993    if(sourceFile)
994       eString_GetLastDirectory(sourceFile, name);
995    */
996
997    if(inCompiler)
998    {
999       if(yylloc.start.included)
1000       {
1001          //GetWorkingDir(name, sizeof(name));
1002          PathCat(name, GetIncludeFileFromID(yylloc.start.included));
1003       }
1004       else if(sourceFile)
1005       {
1006          //GetWorkingDir(name, sizeof(name));
1007          PathCat(name, sourceFile);
1008       }
1009       ChangeCh(name, '\\', '/');
1010
1011       //GetWorkingDir(origName, sizeof(origName));
1012       PathCat(origName, outputFile);
1013       ChangeCh(origName, '\\', '/');
1014    }
1015
1016    switch(initializer.type)
1017    {
1018       case listInitializer:
1019       {
1020          Initializer init;
1021          f.Puts("\n{\n");
1022          outputLine += 2;
1023
1024          if(inCompiler && outputLineNumbers && initializer.loc.start.line) 
1025          {
1026             /*if(initializer.loc.start.line == 1)
1027                printf("bug");*/
1028
1029             f.Printf("\n#line %d \"%s\"\n", initializer.loc.start.line, name);
1030             outputLine += 2;
1031          }
1032
1033          for(init = initializer.list->first; init; init = init.next)
1034          {
1035             OutputInitializer(init, f);
1036             if(init.next) f.Puts(", ");
1037          }
1038          f.Puts("\n}");
1039
1040          if(inCompiler && outputLineNumbers && initializer.loc.start.line) 
1041          {
1042             /*if(initializer.loc.start.line == 1)
1043                printf("bug");*/
1044
1045             f.Printf("\n#line %d \"%s\"\n", initializer.loc.start.line, name);
1046             outputLine += 2;
1047          }
1048
1049          outputLine ++;
1050          break;
1051       }
1052       case expInitializer:
1053          if(initializer.exp)
1054             OutputExpression(initializer.exp, f);
1055          break;
1056    }
1057 }
1058
1059 static void OutputInitDeclarator(InitDeclarator decl, File f)
1060 {
1061    OutputDeclarator(decl.declarator, f);
1062    if(decl.initializer)
1063    {
1064       f.Puts(" = ");
1065       OutputInitializer(decl.initializer, f);
1066    }
1067 }
1068
1069 static void OutputDeclaration(Declaration decl, File f)
1070 {
1071    Specifier spec;
1072    char origName[MAX_FILENAME] = "";
1073
1074    switch(decl.type)
1075    {
1076       case initDeclaration:
1077       {
1078          InitDeclarator d;
1079
1080          //GetWorkingDir(origName, sizeof(origName));
1081          if(inCompiler)
1082          {
1083             PathCat(origName, outputFile);
1084             ChangeCh(origName, '\\', '/');
1085          }
1086
1087          if(decl.declarators && decl.declarators->first)
1088          {
1089             for(d = decl.declarators->first; d; d = d.next)
1090                if(d.initializer)
1091                {
1092                   char name[MAX_FILENAME] = "";
1093                   /*
1094                   if(sourceFile)
1095                      GetLastDirectory(sourceFile, name);
1096                   */
1097
1098                   if(yylloc.start.included)
1099                   {
1100                      //GetWorkingDir(name, sizeof(name));
1101                      PathCat(name, GetIncludeFileFromID(yylloc.start.included));
1102                   }
1103                   else if(sourceFile)
1104                   {
1105                      //GetWorkingDir(name, sizeof(name));
1106                      PathCat(name, sourceFile);
1107                   }
1108                   ChangeCh(name, '\\', '/');
1109
1110                   if(inCompiler && outputLineNumbers && decl.loc.start.line) 
1111                   {
1112                      /*if(decl.loc.start.line == 1)
1113                         printf("bug");*/
1114
1115                      f.Printf("\n#line %d \"%s\"\n", decl.loc.start.line, name);
1116                      outputLine += 2;
1117                   }
1118                   break;
1119                }
1120          }
1121
1122          if(decl.specifiers)
1123          {
1124             for(spec = decl.specifiers->first; spec; spec = spec.next)
1125             {
1126                OutputSpecifier(spec, f);
1127                if(spec.next) f.Puts(" ");
1128             }
1129          }
1130          if(decl.declarators && decl.declarators->first)
1131          {
1132             f.Puts(" ");
1133
1134             for(d = decl.declarators->first; d; d = d.next)
1135             {
1136                OutputInitDeclarator(d, f);
1137                if(d.next) f.Puts(", ");
1138             }   
1139          }
1140          break;
1141       }
1142       case structDeclaration:
1143       {
1144          if(decl.specifiers)
1145          {
1146             for(spec = decl.specifiers->first; spec; spec = spec.next)
1147             {
1148                OutputSpecifier(spec, f);
1149                if(spec.next) f.Puts(" ");
1150             }
1151          }
1152          if(decl.declarators)
1153          {
1154             Declarator d;
1155             f.Puts(" ");
1156
1157             for(d = decl.declarators->first; d; d = d.next)
1158             {
1159                OutputDeclarator(d, f);
1160                if(d.next) f.Puts(", ");
1161             }   
1162          }
1163          if(decl.extStorage)
1164          {
1165             f.Puts(" ");
1166             OutputSpecifier(decl.extStorage, f);
1167          }
1168          break;
1169       }
1170       case instDeclaration:
1171          if(decl.inst)
1172          {
1173             OutputInstance(decl.inst, f);
1174          }
1175          break;
1176       case defineDeclaration:
1177          return; // Skip semicolon
1178    }
1179    f.Puts(";\n");
1180    outputLine ++;
1181    if(inCompiler && outputLineNumbers && decl.loc.start.line && decl.type == initDeclaration) 
1182    {
1183       f.Printf("\n#line %d \"%s\"\n", outputLine+2, origName);
1184       outputLine += 2;
1185    }
1186 }
1187
1188 static FunctionDefinition curFunction;
1189
1190 static void OutputFunction(FunctionDefinition func, File f)
1191 {
1192    FunctionDefinition oldFunc = curFunction;
1193    curFunction = func;
1194    if(func.specifiers) 
1195    {
1196       Specifier spec;
1197       for(spec = func.specifiers->first; spec; spec = spec.next)
1198       {
1199          OutputSpecifier(spec, f);
1200          if(spec.next) f.Puts(" ");
1201       }
1202       f.Puts(" ");
1203    }
1204    if(func.declarator) OutputDeclarator(func.declarator, f);
1205    f.Puts("\n");
1206    outputLine ++;
1207    if(func.declarations)
1208    {
1209       Declaration decl;
1210       for(decl = func.declarations->first; decl; decl = decl.next)
1211       {
1212          OutputDeclaration(decl, f);
1213       }
1214       f.Puts("\n");
1215       outputLine ++;
1216    }
1217    if(func.body)
1218    {
1219       if(inCompiler && memoryGuard)
1220       {
1221          char name[1024] = "";
1222          Identifier id = GetDeclId(func.declarator);
1223
1224          if(yylloc.start.included)
1225          {
1226             //GetWorkingDir(name, sizeof(name));
1227             PathCat(name, GetIncludeFileFromID(yylloc.start.included));
1228          }
1229          else if(sourceFile)
1230          {
1231             //GetWorkingDir(name, sizeof(name));
1232             PathCat(name, sourceFile);
1233          }
1234          ChangeCh(name, '\\', '/');
1235
1236          f.Printf("{\n");
1237          f.Printf("   __ecereNameSpace__ecere__com__MemoryGuard_PushLoc(\"%s:%s\");\n", name, id.string);
1238          outputLine += 2;
1239       }
1240       OutputStatement(func.body, f);
1241       if(inCompiler && memoryGuard)
1242       {
1243          f.Printf("   __ecereNameSpace__ecere__com__MemoryGuard_PopLoc();\n");
1244          f.Printf("}\n");
1245          outputLine += 2;
1246       }
1247       f.Puts("\n");
1248       outputLine ++;
1249    }
1250    curFunction = oldFunc;
1251 }
1252
1253 static void OutputMemberInit(MemberInit init, File f)
1254 {
1255    if(init.identifiers)
1256    {
1257       if(init.identifiers->count > 1)
1258       {
1259          Identifier id;
1260          //f.Puts("[");
1261          for(id = init.identifiers->first; id; id = id.next)
1262          {
1263             OutputIdentifier(id, f);
1264             if(id.next)
1265                f.Puts(".");
1266          }
1267          //f.Puts("]");
1268       }
1269       else if(init.identifiers->first)
1270          OutputIdentifier(init.identifiers->first, f);
1271       f.Puts(" = ");
1272    }
1273    if(init.initializer)
1274       OutputInitializer(init.initializer, f);
1275 }
1276
1277 static void OutputMembersInit(MembersInit init, File f)
1278 {
1279    switch(init.type)
1280    {
1281       case dataMembersInit:
1282       {
1283          MemberInit member;
1284          if(init.dataMembers)
1285          {
1286             for(member = init.dataMembers->first; member; member = member.next)
1287             {
1288                OutputMemberInit(member, f);
1289                if(member.next) f.Puts(", ");
1290             }
1291          }
1292          break;
1293       }
1294       case methodMembersInit:
1295          OutputClassFunction(init.function, f);
1296          break;
1297    }
1298 }
1299
1300 static void OutputInstance(Instantiation inst, File f)
1301 {
1302    if(inst._class)
1303       OutputSpecifier(inst._class, f);
1304    if(inst.exp)
1305    {
1306       f.Puts(" ");
1307       OutputExpression(inst.exp, f);
1308    }
1309    if(inst.members && inst.members->count > 1)
1310    {
1311       f.Puts("\n{\n");
1312       outputLine += 2;
1313    }
1314    else if(inst.members)
1315       f.Puts(" { ");
1316    else
1317       f.Puts("{");
1318    if(inst.members)
1319    {
1320       MembersInit init;
1321       for(init = inst.members->first; init; init = init.next)
1322       {
1323          OutputMembersInit(init, f);
1324          if(init.type == dataMembersInit && init.next)
1325          {
1326             f.Puts(";\n");
1327             outputLine ++;
1328          }
1329       }
1330    }
1331    if(inst.members)
1332       f.Puts(" }");
1333    else
1334       f.Puts("}");
1335 }
1336
1337 static void OutputClassFunction(ClassFunction func, File f)
1338 {
1339    if(func.specifiers) 
1340    {
1341       Specifier spec;
1342       for(spec = func.specifiers->first; spec; spec = spec.next)
1343       {
1344          OutputSpecifier(spec, f);
1345          if(spec.next) f.Puts(" ");
1346       }
1347       f.Puts(" ");
1348    }
1349    /*if(func.class)
1350    {
1351       //if(func.class != (void *)-1)
1352       if(func.class)
1353          OutputSpecifier(func.class, f);
1354       f.Puts("::");
1355    }*/
1356    if(func.declarator) OutputDeclarator(func.declarator, f);
1357    f.Puts("\n");
1358    outputLine ++;
1359    if(func.declarations)
1360    {
1361       Declaration decl;
1362       for(decl = func.declarations->first; decl; decl = decl.next)
1363       {
1364          OutputDeclaration(decl, f);
1365       }
1366       f.Puts("\n");
1367       outputLine ++;
1368    }
1369    if(func.body)
1370    {
1371       OutputStatement(func.body, f);
1372       f.Puts("\n");
1373       outputLine ++;
1374    }
1375    else
1376       f.Puts(";");
1377 }
1378
1379 static void OutputClassDef(ClassDef def, File f)
1380 {
1381    switch(def.type)
1382    {
1383       case declarationClassDef:
1384          if(def.decl)
1385          {
1386             OutputDeclaration(def.decl, f);
1387             if(def.next && def.next.type != declarationClassDef)
1388             {
1389                f.Puts("\n");
1390                outputLine ++;
1391             }
1392          }
1393          break;
1394       case defaultPropertiesClassDef:
1395       {
1396          MemberInit init;
1397          for(init = def.defProperties->first; init; init = init.next)
1398          {
1399             OutputMemberInit(init, f);
1400             if(init.next) f.Puts(", ");
1401          }
1402          f.Puts(";\n\n");
1403          outputLine += 2;
1404          break;
1405       }
1406       case functionClassDef:
1407          OutputClassFunction(def.function, f);
1408          f.Puts("\n");
1409          outputLine ++;
1410          break;
1411    }
1412 }
1413
1414 static void OutputClass(ClassDefinition _class, File f)
1415 {
1416    f.Puts("class ");
1417    OutputSpecifier(_class._class, f);
1418    if(_class.baseSpecs)
1419    {
1420       Specifier spec;
1421
1422       f.Puts(" : ");
1423       for(spec = _class.baseSpecs->first; spec; spec = spec.next)
1424       {
1425          OutputSpecifier(spec, f);
1426       }
1427    }
1428    if(_class.definitions)
1429    {
1430       ClassDef def;
1431       f.Puts("\n{\n");
1432       outputLine += 2;
1433       for(def = _class.definitions->first; def; def = def.next)
1434       {
1435          OutputClassDef(def, f);
1436       }
1437       f.Puts("}\n");
1438       outputLine ++;
1439    }
1440    else
1441       f.Puts(";");
1442 }
1443
1444 public void OutputTree(OldList ast, File f)
1445 {
1446    External external;
1447
1448    outputLine = 11;
1449
1450    for(external = ast.first; external; external = external.next)
1451    {
1452       switch(external.type)
1453       {
1454          case functionExternal: 
1455             OutputFunction(external.function, f); 
1456             f.Puts("\n");
1457             outputLine ++;
1458             break;
1459          case declarationExternal: 
1460             OutputDeclaration(external.declaration, f);
1461             f.Puts("\n");   
1462             outputLine ++;
1463             break;
1464          case classExternal: 
1465             OutputClass(external._class, f);
1466             f.Puts("\n");   
1467             outputLine ++;
1468             break;
1469       }
1470    }
1471 }
1472
1473 public char * StringFromSpecDecl(OldList specs, Declarator decl)
1474 {
1475    char * string;
1476    TypeName typeName { };
1477    File f = TempFile { };
1478    FileSize size;
1479
1480    typeName.qualifiers = specs;
1481    typeName.declarator = decl;
1482
1483    OutputTypeName(typeName, f);
1484
1485    delete typeName;
1486
1487    size = f.GetSize();
1488    string = new char[size + 1];
1489    f.Seek(0, start);
1490    f.Read(string, 1, size);
1491    string[size] = '\0';
1492    TrimRSpaces(string, string);
1493
1494    delete f;
1495
1496    return string;
1497 }