compiler/libec; ide: Fixed debugging of Bison and Flex files (#15)
[sdk] / compiler / libec / src / output.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4
5 #include "grammar.h"
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, bool typeName)
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, typeName);
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, false);
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, false);
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, false);
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, false);
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, false);
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, false);
263          f.Puts(")");
264          break;
265       case typeAlignExp:
266          f.Puts("__alignof__(");
267          OutputTypeName(exp.typeName, f, false);
268          f.Puts(")");
269          break;
270       case extensionInitializerExp:
271          f.Puts("__extension__ (");
272          if(exp.initializer.typeName)
273             OutputTypeName(exp.initializer.typeName, f, false);
274          f.Puts(")");
275          if(exp.initializer.initializer)
276             OutputInitializer(exp.initializer.initializer, f);
277          break;
278       case castExp:
279          f.Puts("(");
280          OutputTypeName(exp.cast.typeName, f, false);
281          f.Puts(")");
282          if(exp.cast.exp)
283             OutputExpression(exp.cast.exp, f);
284          break;
285       case conditionExp:
286          OutputExpression(exp.cond.cond, f);
287          f.Puts(" ? ");
288          {
289             Expression expression;
290             for(expression = exp.cond.exp->first; expression; expression = expression.next)
291             {
292                OutputExpression(expression, f);
293                if(expression.next) f.Puts(", ");
294             }
295          }
296          f.Puts(" : ");
297          OutputExpression(exp.cond.elseExp, f);
298          break;
299       case vaArgExp:
300          f.Puts("__builtin_va_arg(");
301          OutputExpression(exp.vaArg.exp, f);
302          f.Puts(", ");
303          OutputTypeName(exp.vaArg.typeName, f, false);
304          f.Puts(")");
305          break;
306       case arrayExp:
307          f.Puts("[");
308          if(exp.list)
309          {
310             Expression expression;
311             for(expression = exp.list->first; expression; expression = expression.next)
312             {
313                OutputExpression(expression, f);
314                if(expression.next) f.Puts(", ");
315             }
316          }
317          f.Puts("]");
318          break;
319    }
320 }
321
322 static void OutputAsmField(AsmField field, File f)
323 {
324    f.Puts(field.command);
325    if(field.expression)
326    {
327       f.Puts("(");
328       OutputExpression(field.expression, f);
329       f.Puts(")");
330    }
331 }
332
333 static void GetSourceName(char * name, const char * src)
334 {
335    name[0] = 0;
336    if(src)
337    {
338       if(!strchr(src, '/') && !strchr(src, '\\'))
339          StripLastDirectory(sourceFile, name);
340       PathCat(name, src);
341    }
342    else if(sourceFile)
343       PathCat(name, sourceFile);
344    ChangeCh(name, '\\', '/');
345 }
346
347 static void OutputStatement(Statement stmt, File f)
348 {
349    char name[MAX_FILENAME] = "";
350    char origName[MAX_FILENAME] = "";
351
352    if(inCompiler)
353    {
354       GetSourceName(name, stmt.loc.start.included ? GetIncludeFileFromID(stmt.loc.start.included) : null);
355
356       PathCat(origName, outputFile);
357       ChangeCh(origName, '\\', '/');
358    }
359
360
361    if(inCompiler && outputLineNumbers && stmt.loc.start.line) 
362    {
363       /*if(stmt.loc.start.line == 1)
364          printf("bug");*/
365       f.Printf("\n#line %d \"%s\"\n", stmt.loc.start.line, name);
366       outputLine += 2;
367    }
368
369    switch(stmt.type)
370    {
371       case badDeclarationStmt:
372          OutputDeclaration(stmt.decl, f);
373          break;
374       case labeledStmt:
375          OutputIdentifier(stmt.labeled.id, f);
376          f.Puts(":\n");
377          outputLine ++;
378          OutputStatement(stmt.labeled.stmt, f);
379          break;
380       case caseStmt:
381          if(stmt.caseStmt.exp)
382          {
383             f.Puts("case ");
384             OutputExpression(stmt.caseStmt.exp, f);
385             f.Puts(":\n");
386             outputLine ++;
387          }
388          else
389          {
390             f.Puts("default:\n");
391             outputLine ++;
392          }
393          if(stmt.caseStmt.stmt)
394             OutputStatement(stmt.caseStmt.stmt, f);
395          break;
396       case compoundStmt:
397       {
398          f.Puts("{\n");
399          outputLine ++;
400          if(stmt.compound.declarations)
401          {
402             Declaration decl;
403             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
404             {
405                OutputDeclaration(decl, f);
406
407             }
408          }
409          if(stmt.compound.statements)
410          {
411             Statement statement;
412             if(stmt.compound.declarations)
413             {
414                f.Puts("\n");
415                outputLine ++;
416             }
417             for(statement = stmt.compound.statements->first; statement; statement = statement.next)
418             {
419                OutputStatement(statement, f);
420                f.Puts("\n");
421                outputLine ++;
422             }
423          }
424          if(inCompiler && outputLineNumbers && stmt.loc.end.line) 
425          {
426             /*if(stmt.loc.end.line == 1)
427                printf("bug");*/
428
429             f.Printf("\n#line %d \"%s\"\n", stmt.loc.end.line, name);
430             outputLine += 2;
431          }
432
433          f.Puts("}");
434          break;
435       }
436       case expressionStmt:
437       {
438          if(stmt.expressions)
439          {
440             Expression exp;
441             for(exp = stmt.expressions->first; exp; exp = exp.next)
442             {
443                OutputExpression(exp, f);
444                if(exp.next) f.Puts(", ");
445             }
446          }
447          f.Puts(";");
448          break;
449       }
450       case ifStmt:
451       {
452          Expression exp;
453          f.Puts("if(");
454          for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
455          {
456             OutputExpression(exp, f);
457             if(exp.next) f.Puts(", ");
458          }
459          f.Puts(")\n");
460          outputLine ++;
461          if(stmt.ifStmt.stmt)
462             OutputStatement(stmt.ifStmt.stmt, f);
463          if(stmt.ifStmt.elseStmt)
464          {
465             f.Puts("\n");
466             outputLine ++;
467             f.Puts("else");
468             if(stmt.ifStmt.elseStmt.type != ifStmt)
469             {
470                f.Puts("\n");
471                outputLine ++;
472             }
473             else
474                f.Puts(" ");
475             OutputStatement(stmt.ifStmt.elseStmt, f);
476          }
477          break;
478       }
479       case switchStmt:
480       {
481          Expression exp;
482          f.Puts("switch(");
483          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
484          {
485             OutputExpression(exp, f);
486             if(exp.next) f.Puts(", ");
487          }
488          f.Puts(")\n");
489          outputLine ++;
490          OutputStatement(stmt.switchStmt.stmt, f);
491          break;
492       }
493       case whileStmt:
494       {
495          Expression exp;
496          f.Puts("while(");
497          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
498          {
499             OutputExpression(exp, f);
500             if(exp.next) f.Puts(", ");
501          }
502          f.Puts(")\n");
503          outputLine ++;
504          OutputStatement(stmt.whileStmt.stmt, f);
505          break;
506       }
507       case doWhileStmt:
508       {
509          Expression exp;
510          f.Puts("do\n");
511          outputLine ++;
512          OutputStatement(stmt.whileStmt.stmt, f);
513          f.Puts("while(");
514          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
515          {
516             OutputExpression(exp, f);
517             if(exp.next) f.Puts(", ");
518          }
519          f.Puts(");");
520          break;
521       }
522       case forStmt:
523       {
524          Expression exp;
525          f.Puts("for(");
526          OutputStatement(stmt.forStmt.init, f);
527          f.Puts(" ");
528          OutputStatement(stmt.forStmt.check, f);
529          f.Puts(" ");
530          if(stmt.forStmt.increment)
531          {
532             // TESTING THIS HERE FOR FOR INCREMENT
533             if(inCompiler && outputLineNumbers && stmt.loc.end.line) 
534             {
535                /*if(stmt.loc.end.line == 1)
536                   printf("bug");*/
537
538                f.Printf("\n#line %d \"%s\"\n", stmt.loc.end.line, name);
539                outputLine += 2;
540             }
541
542             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
543             {
544                OutputExpression(exp, f);
545                if(exp.next) f.Puts(", ");
546             }
547          }
548          f.Puts(")\n");
549          outputLine ++;
550          OutputStatement(stmt.forStmt.stmt, f);
551          break;
552       }
553       case gotoStmt:
554       {
555          f.Puts("goto ");
556          OutputIdentifier(stmt.gotoStmt.id, f);
557          f.Puts(";");
558          break;
559       }
560       case continueStmt:
561          f.Puts("continue;");
562          break;
563       case breakStmt:
564          f.Puts("break;");
565          break;
566       case returnStmt:
567       {
568          Expression exp;
569
570          if(inCompiler && memoryGuard)
571          {
572             Expression exp = stmt.expressions ? stmt.expressions->last : null;
573             f.Printf("{ ");
574             if(exp && exp.expType)
575             {
576                
577                char string[1024] = "";
578                OldList * specs = MkList();
579                Declarator decl;
580                TypeName typeName;
581                if(exp.expType.kind == templateType)
582                {
583                   if(exp.expType.templateParameter.dataTypeString)
584                      decl = SpecDeclFromString(exp.expType.templateParameter.dataTypeString, specs,
585                         MkDeclaratorIdentifier(MkIdentifier("__ecereReturnVal")));
586                   else if(exp.expType.templateParameter.dataType)
587                   {
588                      delete specs;
589                      specs = CopyList(exp.expType.templateParameter.dataType.specifiers, CopySpecifier);
590                      decl = PlugDeclarator(/*CopyDeclarator(*/exp.expType.templateParameter.dataType.decl/*)*/, 
591                         MkDeclaratorIdentifier(MkIdentifier("__ecereReturnVal")));
592                   }
593                   else
594                   {
595                      ListAdd(specs, MkSpecifierName("uint64"));
596                      decl = MkDeclaratorIdentifier(MkIdentifier("__ecereReturnVal"));
597                   }
598                }
599                else
600                {
601                   // Printing 'name' as a hack when we're dealing with typedefs with extended attributes
602                   PrintTypeNoConst(exp.expType, string, exp.expType.kind == dummyType ? true : false, true);
603                   decl = SpecDeclFromString(string, specs, MkDeclaratorIdentifier(MkIdentifier("__ecereReturnVal")));
604                }
605
606                typeName = MkTypeName(specs, decl);
607                InstDeclPassTypeName(typeName, false);
608                OutputTypeName(typeName, f, false);
609                f.Printf(";");
610                FreeTypeName(typeName);
611             }
612          }
613          if(!memoryGuard)
614             f.Puts("return ");
615          else 
616          {
617             Expression exp = stmt.expressions ? stmt.expressions->last : null;
618             if(exp && exp.expType)
619                f.Printf("__ecereReturnVal = ");
620          }
621
622          if(stmt.expressions)
623          {
624             for(exp = stmt.expressions->first; exp; exp = exp.next)
625             {
626                OutputExpression(exp, f);
627                if(exp.next) f.Puts(", ");
628             }
629          }
630          f.Puts(";");
631
632          if(inCompiler && memoryGuard)
633          {
634             Expression exp = stmt.expressions ? (Expression)stmt.expressions->last : null;
635             f.Printf(" __ecereNameSpace__ecere__com__MemoryGuard_PopLoc();");
636             if(exp && exp.expType)
637                f.Printf("return __ecereReturnVal;");
638             else
639                f.Printf("return;");
640
641             f.Printf("}");
642          }
643
644          break;
645       }
646       case asmStmt:
647       {
648          AsmField field;
649          f.Puts("__asm__ ");
650          if(stmt.asmStmt.spec)
651             OutputSpecifier(stmt.asmStmt.spec, f, false);
652          f.Puts("(");
653          f.Puts(stmt.asmStmt.statements);
654
655          if(stmt.asmStmt.inputFields || stmt.asmStmt.outputFields || stmt.asmStmt.clobberedFields)
656          {
657             f.Puts(":");
658             if(stmt.asmStmt.inputFields)
659             {
660                for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
661                {
662                   if(field.prev) f.Puts(",");
663                   OutputAsmField(field, f);
664                }
665             }
666          }
667          if(stmt.asmStmt.outputFields || stmt.asmStmt.clobberedFields)
668          {
669             f.Puts(":");
670             if(stmt.asmStmt.outputFields)
671             {
672                for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
673                {
674                   if(field.prev) f.Puts(",");
675                   OutputAsmField(field, f);
676                }
677             }
678          }
679          if(stmt.asmStmt.clobberedFields)
680          {
681             f.Puts(":");
682             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
683             {
684                if(field.prev) f.Puts(",");
685                OutputAsmField(field, f);
686             }
687          }
688          f.Puts(");\n");
689          outputLine++;
690          break;
691       }
692    }
693
694    if(inCompiler && outputLineNumbers && stmt.loc.start.line) 
695    {
696       f.Printf("\n#line %d \"%s\"\n", outputLine+2, origName);
697       outputLine += 2;
698    }
699 }
700
701 static void OutputPointer(Pointer ptr, File f)
702 {
703    f.Puts("*");
704    if(ptr.qualifiers)
705    {
706       Specifier spec;
707       f.Puts(" ");
708       for(spec = ptr.qualifiers->first; spec; spec = spec.next)
709       {
710          OutputSpecifier(spec, f, false);
711          if(spec.next) f.Puts(" ");
712       }
713    }
714    if(ptr.pointer)
715    {
716       OutputPointer(ptr.pointer, f);
717    }
718 }
719
720 static void OutputDeclarator(Declarator decl, File f)
721 {
722    switch(decl.type)
723    {
724       case structDeclarator:
725          if(decl.declarator)
726          {
727             OutputDeclarator(decl.declarator, f);
728          }
729          if(decl.structDecl.exp)
730          {
731             f.Puts(" : ");
732             OutputExpression(decl.structDecl.exp, f);
733          }
734          if(decl.structDecl.posExp)
735          {
736             f.Puts(" : ");
737             OutputExpression(decl.structDecl.posExp, f);
738          }
739          if(decl.structDecl.attrib)
740          {
741             f.Puts(" ");
742             OutputAttrib(decl.structDecl.attrib, f);
743          }
744          break;
745       case identifierDeclarator:
746          OutputIdentifier(decl.identifier, f);
747          break;
748       case bracketsDeclarator:
749          f.Puts("(");
750          OutputDeclarator(decl.declarator, f);
751          f.Puts(")");
752          break;
753       case extendedDeclarator:
754          if(decl.extended.extended) OutputExtDecl(decl.extended.extended, f);
755          f.Puts(" ");
756          OutputDeclarator(decl.declarator, f);
757          break;
758       case extendedDeclaratorEnd:
759          OutputDeclarator(decl.declarator, f);
760          f.Puts(" ");
761          if(decl.extended.extended)
762             OutputExtDecl(decl.extended.extended, f);
763          break;
764       case arrayDeclarator:
765          if(decl.declarator)
766          {
767             OutputDeclarator(decl.declarator, f);
768          }
769          f.Puts("[");
770          if(decl.array.exp)
771          {
772             // Hacked this here
773             ProcessExpressionType(decl.array.exp);
774             ComputeExpression(decl.array.exp);
775
776             OutputExpression(decl.array.exp, f);
777          }
778          else if(decl.array.enumClass)
779          {
780             Symbol _class = decl.array.enumClass.symbol; // FindClass(decl.array.enumClass.name);
781             if(_class && _class.registered)
782             {
783                f.Printf("%d", (int)eClass_GetProperty(_class.registered, "enumSize"));
784             }            
785          }
786          f.Puts("]");
787          break;
788       case functionDeclarator:
789       {
790          TypeName param;
791
792          if(decl.declarator)
793             OutputDeclarator(decl.declarator, f);
794          f.Puts("(");
795          if(decl.function.parameters && decl.function.parameters->first)
796          {
797             for(param = decl.function.parameters->first; param; param = param.next)
798             {
799                OutputTypeName(param, f, false);
800                if(param.next)
801                   f.Puts(", ");
802             }
803          }
804          f.Puts(")");
805          break;
806       }
807       case pointerDeclarator:
808          if(decl.pointer.pointer) OutputPointer(decl.pointer.pointer, f);
809          if(decl.declarator) 
810          {
811             f.Puts(" ");
812             OutputDeclarator(decl.declarator, f);
813          }
814          break;
815    }
816 }
817
818 static void OutputEnumerator(Enumerator enumerator, File f)
819 {
820    OutputIdentifier(enumerator.id, f);
821    if(enumerator.exp)
822    {
823       f.Puts(" = ");
824       OutputExpression(enumerator.exp, f);
825    }
826 }
827
828 static void OutputAttribute(Attribute attr, File f)
829 {
830    if(attr.attr)
831       f.Puts(attr.attr);
832    if(attr.exp)
833    {
834       f.Puts(" ");
835       OutputExpression(attr.exp, f);
836    }
837 }
838
839 static void OutputAttrib(Attrib attr, File f)
840 {
841    switch(attr.type)
842    {
843       case ATTRIB:      f.Puts("__attribute__(("); break;
844       case __ATTRIB:    f.Puts("__attribute((");  break;
845       case ATTRIB_DEP:  f.Puts("__attribute_deprecated__(("); break;
846    }
847    
848    if(attr.attribs)
849    {
850       Attribute attrib;
851       for(attrib = attr.attribs->first; attrib; attrib = attrib.next)
852       {
853          if(attrib.prev) f.Puts(" ");
854          OutputAttribute(attrib, f);
855       }
856    }
857    f.Puts("))"); 
858 }
859
860 static void OutputExtDecl(ExtDecl extDecl, File f)
861 {
862    if(extDecl.type == extDeclString && extDecl.s)
863       f.Puts(extDecl.s);
864    else if(extDecl.type == extDeclAttrib)
865       OutputAttrib(extDecl.attr, f);
866 }
867
868 static void OutputSpecifier(Specifier spec, File f, bool typeName)
869 {
870    switch(spec.type)
871    {
872       case baseSpecifier:
873          switch(spec.specifier)
874          {
875             // Storage Class
876             case TYPEDEF:
877                f.Puts("typedef");
878                break;
879             case EXTERN:
880                f.Puts("extern");
881                break;
882             case STATIC:
883                f.Puts("static");
884                break;
885             case AUTO:
886                f.Puts("auto");
887                break;
888             case REGISTER:
889                f.Puts("register");
890                break;
891
892             // Qualifier
893             case CONST:
894                f.Puts("const");
895                break;
896             case VOLATILE:
897                f.Puts("volatile");
898                break;
899
900             // Type Specifier
901             case VOID:
902                f.Puts("void");
903                break;
904             case CHAR:
905                f.Puts("char");
906                break;
907             case SHORT:
908                f.Puts("short");
909                break;
910             case INT:
911                f.Puts("int");
912                break;
913             case UINT:
914                f.Puts(typeName ? "uint" : "unsigned int");
915                break;
916             case INT64:
917                //f.Puts("__int64");
918                //f.Puts("int64");
919                f.Puts(typeName ? "int64" : "long long");
920                break;
921             case VALIST:
922                f.Puts("__builtin_va_list");
923                break;
924             case LONG:
925                f.Puts("long");
926                break;
927             case FLOAT:
928                f.Puts("float");
929                break;
930             case DOUBLE:
931                f.Puts("double");
932                break;
933             case SIGNED:
934                f.Puts("signed");
935                break;
936             case UNSIGNED:
937                f.Puts("unsigned");
938                break;
939             case TYPED_OBJECT:
940                f.Puts("typed_object");
941                break;
942             case ANY_OBJECT:
943                f.Puts("any_object");
944                break;
945             case CLASS:
946                f.Puts("class");
947                break;
948             case THISCLASS:
949                f.Puts("thisclass");
950                break;
951          }
952          break;
953       case extendedSpecifier:
954          if(spec.extDecl)
955             OutputExtDecl(spec.extDecl, f);
956          break;
957       case nameSpecifier:
958       //case classSpecifier:
959          if(spec.name && !strcmp(spec.name, "class"))
960          {
961             f.Puts("typed_object");
962          }
963          else
964          {
965             Symbol symbol = spec.symbol; // FindClass(spec.name);
966             // WILL HAVE TO VERIFY THESE ELSEWHERE...
967             if(!symbol && spec.name)
968                symbol = FindClass(spec.name);
969             if(symbol)
970             {
971                f.Puts(symbol.string ? symbol.string : "(null)");
972             }
973             else if(spec.name)
974                f.Puts(spec.name);
975          }
976          break;
977       case enumSpecifier:
978       {
979          f.Puts("enum");
980          if(spec.id)
981          {
982             f.Puts(" ");
983             OutputIdentifier(spec.id, f);
984          }
985          if(spec.list)
986          {
987             Enumerator enumerator;
988             f.Puts("\n{\n");
989             outputLine += 2;
990             for(enumerator = spec.list->first; enumerator; enumerator = enumerator.next)
991             {
992                OutputEnumerator(enumerator, f);
993                if(enumerator.next) f.Puts(", ");
994             }
995             f.Puts("\n}");
996             outputLine ++;
997          }
998          break;
999       }
1000       case structSpecifier:
1001       case unionSpecifier:
1002       {
1003          f.Puts((spec.type == structSpecifier) ? "struct" : "union");
1004          if(spec.extDeclStruct)
1005          {
1006             f.Puts(" ");
1007             OutputExtDecl(spec.extDeclStruct, f);
1008          }
1009          if(spec.id)
1010          {
1011             f.Puts(" ");
1012             OutputIdentifier(spec.id, f);
1013          }
1014          if(spec.definitions)
1015          {
1016             ClassDef def;
1017             f.Puts("\n{\n");
1018             outputLine += 2;
1019             for(def = spec.definitions->first; def; def = def.next)
1020             {
1021                //OutputDeclaration(decl, f);
1022                OutputClassDef(def, f);
1023             }
1024             f.Puts("} __attribute__ ((gcc_struct))");
1025          }
1026          break;
1027       }
1028       case typeOfSpecifier:
1029          f.Puts("__typeof(");
1030          OutputExpression(spec.expression, f);
1031          f.Puts(")");                  
1032          break;
1033       case subClassSpecifier:
1034          f.Puts("subclass(");
1035          OutputSpecifier(spec._class, f, false);
1036          f.Puts(")");                  
1037          break;
1038       case templateTypeSpecifier:
1039          OutputIdentifier(spec.templateParameter.identifier, f);
1040          break;
1041    }
1042 }
1043
1044 static void OutputInitializer(Initializer initializer, File f)
1045 {
1046    char name[MAX_FILENAME] = "";
1047    char origName[MAX_FILENAME] = "";
1048
1049    if(inCompiler)
1050    {
1051       GetSourceName(name, initializer.loc.start.included ? GetIncludeFileFromID(initializer.loc.start.included) : null);
1052
1053       PathCat(origName, outputFile);
1054       ChangeCh(origName, '\\', '/');
1055    }
1056
1057    switch(initializer.type)
1058    {
1059       case listInitializer:
1060       {
1061          Initializer init;
1062          f.Puts("\n{\n");
1063          outputLine += 2;
1064
1065          if(inCompiler && outputLineNumbers && initializer.loc.start.line) 
1066          {
1067             /*if(initializer.loc.start.line == 1)
1068                printf("bug");*/
1069
1070             f.Printf("\n#line %d \"%s\"\n", initializer.loc.start.line, name);
1071             outputLine += 2;
1072          }
1073
1074          for(init = initializer.list->first; init; init = init.next)
1075          {
1076             OutputInitializer(init, f);
1077             if(init.next) f.Puts(", ");
1078          }
1079          f.Puts("\n}");
1080
1081          if(inCompiler && outputLineNumbers && initializer.loc.start.line) 
1082          {
1083             /*if(initializer.loc.start.line == 1)
1084                printf("bug");*/
1085
1086             f.Printf("\n#line %d \"%s\"\n", initializer.loc.start.line, name);
1087             outputLine += 2;
1088          }
1089
1090          outputLine ++;
1091          break;
1092       }
1093       case expInitializer:
1094          if(initializer.exp)
1095             OutputExpression(initializer.exp, f);
1096          break;
1097    }
1098 }
1099
1100 static void OutputInitDeclarator(InitDeclarator decl, File f)
1101 {
1102    OutputDeclarator(decl.declarator, f);
1103    if(decl.initializer)
1104    {
1105       f.Puts(" = ");
1106       OutputInitializer(decl.initializer, f);
1107    }
1108 }
1109
1110 static void OutputDeclaration(Declaration decl, File f)
1111 {
1112    Specifier spec;
1113    char origName[MAX_FILENAME] = "";
1114
1115    switch(decl.type)
1116    {
1117       case initDeclaration:
1118       {
1119          InitDeclarator d;
1120
1121          //GetWorkingDir(origName, sizeof(origName));
1122          if(inCompiler)
1123          {
1124             PathCat(origName, outputFile);
1125             ChangeCh(origName, '\\', '/');
1126          }
1127
1128          if(decl.declarators && decl.declarators->first)
1129          {
1130             for(d = decl.declarators->first; d; d = d.next)
1131                if(d.initializer)
1132                {
1133                   char name[MAX_FILENAME] = "";
1134
1135                   GetSourceName(name, decl.loc.start.included ? GetIncludeFileFromID(decl.loc.start.included) : null);
1136
1137                   if(inCompiler && outputLineNumbers && decl.loc.start.line) 
1138                   {
1139                      /*if(decl.loc.start.line == 1)
1140                         printf("bug");*/
1141
1142                      f.Printf("\n#line %d \"%s\"\n", decl.loc.start.line, name);
1143                      outputLine += 2;
1144                   }
1145                   break;
1146                }
1147          }
1148
1149          if(decl.specifiers)
1150          {
1151             bool inTypeDef = false;
1152             for(spec = decl.specifiers->first; spec; spec = spec.next)
1153             {
1154                if(spec.type == baseSpecifier && spec.specifier == TYPEDEF)
1155                   inTypeDef = true;
1156                OutputSpecifier(spec, f, inTypeDef && !spec.next);
1157                if(spec.next) f.Puts(" ");
1158             }
1159          }
1160          if(decl.declarators && decl.declarators->first)
1161          {
1162             f.Puts(" ");
1163
1164             for(d = decl.declarators->first; d; d = d.next)
1165             {
1166                OutputInitDeclarator(d, f);
1167                if(d.next) f.Puts(", ");
1168             }   
1169          }
1170          break;
1171       }
1172       case structDeclaration:
1173       {
1174          if(decl.specifiers)
1175          {
1176             for(spec = decl.specifiers->first; spec; spec = spec.next)
1177             {
1178                OutputSpecifier(spec, f, false);
1179                if(spec.next) f.Puts(" ");
1180             }
1181          }
1182          if(decl.declarators)
1183          {
1184             Declarator d;
1185             f.Puts(" ");
1186
1187             for(d = decl.declarators->first; d; d = d.next)
1188             {
1189                OutputDeclarator(d, f);
1190                if(d.next) f.Puts(", ");
1191             }   
1192          }
1193          if(decl.extStorage)
1194          {
1195             f.Puts(" ");
1196             OutputSpecifier(decl.extStorage, f, false);
1197          }
1198          break;
1199       }
1200       case instDeclaration:
1201          if(decl.inst)
1202          {
1203             OutputInstance(decl.inst, f);
1204          }
1205          break;
1206       case defineDeclaration:
1207          return; // Skip semicolon
1208    }
1209    f.Puts(";\n");
1210    outputLine ++;
1211    if(inCompiler && outputLineNumbers && decl.loc.start.line && decl.type == initDeclaration) 
1212    {
1213       f.Printf("\n#line %d \"%s\"\n", outputLine+2, origName);
1214       outputLine += 2;
1215    }
1216 }
1217
1218 static FunctionDefinition curFunction;
1219
1220 static void OutputFunction(FunctionDefinition func, File f)
1221 {
1222    FunctionDefinition oldFunc = curFunction;
1223    curFunction = func;
1224    if(func.specifiers) 
1225    {
1226       Specifier spec;
1227       for(spec = func.specifiers->first; spec; spec = spec.next)
1228       {
1229          OutputSpecifier(spec, f, false);
1230          if(spec.next) f.Puts(" ");
1231       }
1232       f.Puts(" ");
1233    }
1234    if(func.declarator) OutputDeclarator(func.declarator, f);
1235    f.Puts("\n");
1236    outputLine ++;
1237    if(func.declarations)
1238    {
1239       Declaration decl;
1240       for(decl = func.declarations->first; decl; decl = decl.next)
1241       {
1242          OutputDeclaration(decl, f);
1243       }
1244       f.Puts("\n");
1245       outputLine ++;
1246    }
1247    if(func.body)
1248    {
1249       if(inCompiler && memoryGuard)
1250       {
1251          char name[1024] = "";
1252          Identifier id = GetDeclId(func.declarator);
1253
1254          GetSourceName(name, func.loc.start.included ? GetIncludeFileFromID(func.loc.start.included) : null);
1255
1256          f.Printf("{\n");
1257          f.Printf("   __ecereNameSpace__ecere__com__MemoryGuard_PushLoc(\"%s:%s\");\n", name, id.string);
1258          outputLine += 2;
1259       }
1260       OutputStatement(func.body, f);
1261       if(inCompiler && memoryGuard)
1262       {
1263          f.Printf("   __ecereNameSpace__ecere__com__MemoryGuard_PopLoc();\n");
1264          f.Printf("}\n");
1265          outputLine += 2;
1266       }
1267       f.Puts("\n");
1268       outputLine ++;
1269    }
1270    curFunction = oldFunc;
1271 }
1272
1273 static void OutputMemberInit(MemberInit init, File f)
1274 {
1275    if(init.identifiers)
1276    {
1277       if(init.identifiers->count > 1)
1278       {
1279          Identifier id;
1280          //f.Puts("[");
1281          for(id = init.identifiers->first; id; id = id.next)
1282          {
1283             OutputIdentifier(id, f);
1284             if(id.next)
1285                f.Puts(".");
1286          }
1287          //f.Puts("]");
1288       }
1289       else if(init.identifiers->first)
1290          OutputIdentifier(init.identifiers->first, f);
1291       f.Puts(" = ");
1292    }
1293    if(init.initializer)
1294       OutputInitializer(init.initializer, f);
1295 }
1296
1297 static void OutputMembersInit(MembersInit init, File f)
1298 {
1299    switch(init.type)
1300    {
1301       case dataMembersInit:
1302       {
1303          MemberInit member;
1304          if(init.dataMembers)
1305          {
1306             for(member = init.dataMembers->first; member; member = member.next)
1307             {
1308                OutputMemberInit(member, f);
1309                if(member.next) f.Puts(", ");
1310             }
1311          }
1312          break;
1313       }
1314       case methodMembersInit:
1315          OutputClassFunction(init.function, f);
1316          break;
1317    }
1318 }
1319
1320 static void OutputInstance(Instantiation inst, File f)
1321 {
1322    if(inst._class)
1323       OutputSpecifier(inst._class, f, false);
1324    if(inst.exp)
1325    {
1326       f.Puts(" ");
1327       OutputExpression(inst.exp, f);
1328    }
1329    if(inst.members && inst.members->count > 1)
1330    {
1331       f.Puts("\n{\n");
1332       outputLine += 2;
1333    }
1334    else if(inst.members)
1335       f.Puts(" { ");
1336    else
1337       f.Puts("{");
1338    if(inst.members)
1339    {
1340       MembersInit init;
1341       for(init = inst.members->first; init; init = init.next)
1342       {
1343          OutputMembersInit(init, f);
1344          if(init.type == dataMembersInit && init.next)
1345          {
1346             f.Puts(";\n");
1347             outputLine ++;
1348          }
1349       }
1350    }
1351    if(inst.members)
1352       f.Puts(" }");
1353    else
1354       f.Puts("}");
1355 }
1356
1357 static void OutputClassFunction(ClassFunction func, File f)
1358 {
1359    if(func.specifiers) 
1360    {
1361       Specifier spec;
1362       for(spec = func.specifiers->first; spec; spec = spec.next)
1363       {
1364          OutputSpecifier(spec, f, false);
1365          if(spec.next) f.Puts(" ");
1366       }
1367       f.Puts(" ");
1368    }
1369    /*if(func.class)
1370    {
1371       //if(func.class != (void *)-1)
1372       if(func.class)
1373          OutputSpecifier(func.class, f, false);
1374       f.Puts("::");
1375    }*/
1376    if(func.declarator) OutputDeclarator(func.declarator, f);
1377    f.Puts("\n");
1378    outputLine ++;
1379    if(func.declarations)
1380    {
1381       Declaration decl;
1382       for(decl = func.declarations->first; decl; decl = decl.next)
1383       {
1384          OutputDeclaration(decl, f);
1385       }
1386       f.Puts("\n");
1387       outputLine ++;
1388    }
1389    if(func.body)
1390    {
1391       OutputStatement(func.body, f);
1392       f.Puts("\n");
1393       outputLine ++;
1394    }
1395    else
1396       f.Puts(";");
1397 }
1398
1399 static void OutputClassDef(ClassDef def, File f)
1400 {
1401    switch(def.type)
1402    {
1403       case declarationClassDef:
1404          if(def.decl)
1405          {
1406             OutputDeclaration(def.decl, f);
1407             if(def.next && def.next.type != declarationClassDef)
1408             {
1409                f.Puts("\n");
1410                outputLine ++;
1411             }
1412          }
1413          break;
1414       case defaultPropertiesClassDef:
1415       {
1416          MemberInit init;
1417          for(init = def.defProperties->first; init; init = init.next)
1418          {
1419             OutputMemberInit(init, f);
1420             if(init.next) f.Puts(", ");
1421          }
1422          f.Puts(";\n\n");
1423          outputLine += 2;
1424          break;
1425       }
1426       case functionClassDef:
1427          OutputClassFunction(def.function, f);
1428          f.Puts("\n");
1429          outputLine ++;
1430          break;
1431    }
1432 }
1433
1434 static void OutputClass(ClassDefinition _class, File f)
1435 {
1436    f.Puts("class ");
1437    OutputSpecifier(_class._class, f, false);
1438    if(_class.baseSpecs)
1439    {
1440       Specifier spec;
1441
1442       f.Puts(" : ");
1443       for(spec = _class.baseSpecs->first; spec; spec = spec.next)
1444       {
1445          OutputSpecifier(spec, f, false);
1446       }
1447    }
1448    if(_class.definitions)
1449    {
1450       ClassDef def;
1451       f.Puts("\n{\n");
1452       outputLine += 2;
1453       for(def = _class.definitions->first; def; def = def.next)
1454       {
1455          OutputClassDef(def, f);
1456       }
1457       f.Puts("}\n");
1458       outputLine ++;
1459    }
1460    else
1461       f.Puts(";");
1462 }
1463
1464 public void OutputTree(OldList ast, File f)
1465 {
1466    External external;
1467
1468    outputLine = 30;
1469
1470    for(external = ast.first; external; external = external.next)
1471    {
1472       switch(external.type)
1473       {
1474          case functionExternal: 
1475             OutputFunction(external.function, f); 
1476             f.Puts("\n");
1477             outputLine ++;
1478             break;
1479          case declarationExternal: 
1480             OutputDeclaration(external.declaration, f);
1481             f.Puts("\n");   
1482             outputLine ++;
1483             break;
1484          case classExternal: 
1485             OutputClass(external._class, f);
1486             f.Puts("\n");   
1487             outputLine ++;
1488             break;
1489       }
1490    }
1491 }
1492
1493 public char * StringFromSpecDecl(OldList specs, Declarator decl)
1494 {
1495    char * string;
1496    TypeName typeName { };
1497    File f = TempFile { };
1498    FileSize size;
1499
1500    typeName.qualifiers = specs;
1501    typeName.declarator = decl;
1502
1503    OutputTypeName(typeName, f, true);
1504
1505    delete typeName;
1506
1507    size = f.GetSize();
1508    string = new char[size + 1];
1509    f.Seek(0, start);
1510    f.Read(string, 1, size);
1511    string[size] = '\0';
1512    TrimRSpaces(string, string);
1513
1514    delete f;
1515
1516    return string;
1517 }