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