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