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