From 5ad57d142bcf05886c750018b067865fc97e13fe Mon Sep 17 00:00:00 2001 From: pacien Date: Sat, 26 May 2018 18:45:50 +0200 Subject: Handle output to file option --- src/generator.c | 171 ++++++++++++++++++++++++++--------------------------- src/generator.h | 3 + src/symbol_table.c | 15 ++--- src/tpc.y | 21 ++++++- 4 files changed, 116 insertions(+), 94 deletions(-) diff --git a/src/generator.c b/src/generator.c index 88f32d7..8329aee 100644 --- a/src/generator.c +++ b/src/generator.c @@ -4,41 +4,40 @@ */ #include "generator.h" -#include #include "symbol_table.h" // ----- GLOBAL FUNCTIONS ----- void gen_prologue() { - printf("extern printf\n"); - printf("section .data\n"); - printf("format_int db \"%%d\",10,0\n\n"); - printf("section .bss\n"); + fprintf(output, "extern printf\n"); + fprintf(output, "section .data\n"); + fprintf(output, "format_int db \"%%d\",10,0\n\n"); + fprintf(output, "section .bss\n"); } void gen_prologue_continue(){ - printf("globals: resq %d\n", nb_globals); - printf("section .text\n\nglobal _start\n"); - printf("print: ;print needs an argument in rax\n"); - printf("push rbp\n"); - printf("mov rbp, rsp\n"); - printf("push rsi\n"); - printf("mov rsi, rax\n"); - printf("mov rdi, format_int\n"); - printf("mov rax, 0\n"); - printf("call printf WRT ..plt\n"); - printf("pop rsi\n"); - printf("pop rbp\n"); - printf("ret\n"); - printf("\n_start:\n"); - printf("push rbp\nmov rbp, rsp\n\n"); + fprintf(output, "globals: resq %d\n", nb_globals); + fprintf(output, "section .text\n\nglobal _start\n"); + fprintf(output, "print: ;print needs an argument in rax\n"); + fprintf(output, "push rbp\n"); + fprintf(output, "mov rbp, rsp\n"); + fprintf(output, "push rsi\n"); + fprintf(output, "mov rsi, rax\n"); + fprintf(output, "mov rdi, format_int\n"); + fprintf(output, "mov rax, 0\n"); + fprintf(output, "call printf WRT ..plt\n"); + fprintf(output, "pop rsi\n"); + fprintf(output, "pop rbp\n"); + fprintf(output, "ret\n"); + fprintf(output, "\n_start:\n"); + fprintf(output, "push rbp\nmov rbp, rsp\n\n"); } void gen_const_declaration() { - printf("mov rax,60 \n"); - printf("mov rdi,0 \n"); - printf("syscall \n"); - printf(";global table\n"); + fprintf(output, "mov rax,60 \n"); + fprintf(output, "mov rdi,0 \n"); + fprintf(output, "syscall \n"); + fprintf(output, ";global table\n"); glo_display_table(); - printf(";local table\n"); + fprintf(output, ";local table\n"); loc_display_table(); } @@ -50,7 +49,7 @@ void gen_declaration(const char name[], int type, Scope scope) { break; case LOCAL: loc_addVar(name, type); - printf("push 0\n"); + fprintf(output, "push 0\n"); break; } @@ -70,32 +69,32 @@ void gen_read(const char name[], Scope scope) { } void gen_print() { - printf("pop rax\n"); - printf("call print\n"); + fprintf(output, "pop rax\n"); + fprintf(output, "call print\n"); } // ----- CONDITIONAL BRANCHING ------ void gen_if_label(int idx) { - printf(".end_if%d:\n", idx); - printf(";ENDIF\n\n"); + fprintf(output, ".end_if%d:\n", idx); + fprintf(output, ";ENDIF\n\n"); } void gen_if_start(int idx) { - printf("\n;BEGINIF\n"); - printf("pop rax\n"); - printf("cmp rax,0\n"); - printf("jz .end_if%d\n", idx); + fprintf(output, "\n;BEGINIF\n"); + fprintf(output, "pop rax\n"); + fprintf(output, "cmp rax,0\n"); + fprintf(output, "jz .end_if%d\n", idx); } void gen_if_end(int idx) { - printf("jmp .end_ifelse%d\n", idx); - printf(".end_if%d:\n", idx); + fprintf(output, "jmp .end_ifelse%d\n", idx); + fprintf(output, ".end_if%d:\n", idx); } void gen_ifelse_end(int idx) { - printf(".end_ifelse%d:\n", idx); - printf("ENDIF\n\n"); + fprintf(output, ".end_ifelse%d:\n", idx); + fprintf(output, "ENDIF\n\n"); } // ----- OPERATORS ----- @@ -105,10 +104,10 @@ int gen_assign(const char ident[], Scope scope) { switch (scope) { case GLOBAL: - printf(instr_fmt, glo_get_addr(ident), ident); + fprintf(output, instr_fmt, glo_get_addr(ident), ident); return glo_lookup(ident); case LOCAL: - printf(instr_fmt, loc_get_addr(ident), ident); + fprintf(output, instr_fmt, loc_get_addr(ident), ident); return loc_lookup(ident); default: exit(1); @@ -119,72 +118,72 @@ void gen_or(int left, int right, int idx) { check_expected_type(left, INT); check_expected_type(right, INT); - printf(";a OR c\n"); - printf("pop rax\n"); - printf("cmp rax,1\n"); - printf("je .true%d\n", idx); - printf("pop rcx\n"); - printf("cmp rcx,1\n"); - printf("jz .true%d\n", idx); - printf("push 0\n"); - printf("jmp .false%d\n", idx); - printf(".true%d:\n", idx); - printf("push 1\n"); - printf(".false%d:", idx); + fprintf(output, ";a OR c\n"); + fprintf(output, "pop rax\n"); + fprintf(output, "cmp rax,1\n"); + fprintf(output, "je .true%d\n", idx); + fprintf(output, "pop rcx\n"); + fprintf(output, "cmp rcx,1\n"); + fprintf(output, "jz .true%d\n", idx); + fprintf(output, "push 0\n"); + fprintf(output, "jmp .false%d\n", idx); + fprintf(output, ".true%d:\n", idx); + fprintf(output, "push 1\n"); + fprintf(output, ".false%d:", idx); } void gen_and(int left, int right, int idx) { check_expected_type(left, INT); check_expected_type(right, INT); - printf(";a AND c\n"); - printf("pop rax\n"); - printf("cmp rax,0\n"); - printf("jz .false%d\n", idx); - printf("pop rcx\n"); - printf("cmp rcx,0\n"); - printf("jz .false%d\n", idx); - printf("push 1\n"); - printf("jmp .true%d\n", idx); - printf(".false%d:\n", idx); - printf("push 0\n"); - printf(".true%d:", idx); + fprintf(output, ";a AND c\n"); + fprintf(output, "pop rax\n"); + fprintf(output, "cmp rax,0\n"); + fprintf(output, "jz .false%d\n", idx); + fprintf(output, "pop rcx\n"); + fprintf(output, "cmp rcx,0\n"); + fprintf(output, "jz .false%d\n", idx); + fprintf(output, "push 1\n"); + fprintf(output, "jmp .true%d\n", idx); + fprintf(output, ".false%d:\n", idx); + fprintf(output, "push 0\n"); + fprintf(output, ".true%d:", idx); } void gen_eq(const char op[], int left, int right, int idx) { check_expected_type(left, INT); check_expected_type(right, INT); - printf(";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); + fprintf(output, ";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); if (!strcmp(op, "==")) - printf("je .true%d\n", idx); + fprintf(output, "je .true%d\n", idx); else if (!strcmp(op, "!=")) - printf("jne .true%d\n", idx); + fprintf(output, "jne .true%d\n", idx); else exit(1); // TODO: error on unexpected op - printf("push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:", idx, idx, idx); + fprintf(output, "push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:", idx, idx, idx); } void gen_order(const char op[], int left, int right, int idx) { check_expected_type(left, INT); check_expected_type(right, INT); - printf(";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); + fprintf(output, ";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); if (!strcmp(op, "<")) - printf("jl .true%d\n", idx); + fprintf(output, "jl .true%d\n", idx); else if (!strcmp(op, "<=")) - printf("jle .true%d\n", idx); + fprintf(output, "jle .true%d\n", idx); else if(!strcmp(op, ">")) - printf("jg .true%d\n", idx); + fprintf(output, "jg .true%d\n", idx); else if(!strcmp(op, "<=")) - printf("jge .true%d\n", idx); + fprintf(output, "jge .true%d\n", idx); else exit(1); // TODO: error on unexpected op - printf("push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:", idx, idx, idx); + fprintf(output, "push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:", idx, idx, idx); } void gen_addsub(char op, int left, int right) { @@ -193,10 +192,10 @@ void gen_addsub(char op, int left, int right) { switch (op) { case '+': - printf(";E + T\npop rcx\npop rax\nadd rax,rcx\npush rax\n"); + fprintf(output, ";E + T\npop rcx\npop rax\nadd rax,rcx\npush rax\n"); break; case '-': - printf(";E - T\npop rcx\npop rax\nsub rax,rcx\npush rax\n"); + fprintf(output, ";E - T\npop rcx\npop rax\nsub rax,rcx\npush rax\n"); break; default: exit(1); @@ -209,12 +208,12 @@ void gen_divstar(char op, int left, int right) { switch (op) { case '*': - printf(";E * T\npop rax\npop rcx\nimul rax,rcx\npush rax\n"); + fprintf(output, ";E * T\npop rax\npop rcx\nimul rax,rcx\npush rax\n"); break; case '/': case '%': - printf(";E / T\npop rax\npop rcx\nxor rdx,rdx\nidiv rcx\n"); - printf("push %s\n", op == '/' ? "rax" : "rdx"); + fprintf(output, ";E / T\npop rax\npop rcx\nxor rdx,rdx\nidiv rcx\n"); + fprintf(output, "push %s\n", op == '/' ? "rax" : "rdx"); break; default: exit(1); @@ -224,10 +223,10 @@ void gen_divstar(char op, int left, int right) { int gen_signed_expr(char op, int type) { switch (op) { case '+': - printf(";+F\n"); + fprintf(output, ";+F\n"); break; case '-': - printf(";-F\npop rdx\nxor rax,rax\nsub rax,rdx\npush rax\n"); + fprintf(output, ";-F\npop rdx\nxor rax,rax\nsub rax,rdx\npush rax\n"); break; default: exit(1); @@ -237,17 +236,17 @@ int gen_signed_expr(char op, int type) { } int gen_negate_expr(int type) { - printf(";!F\npop rax\nxor rax,1\npush rax\n"); + fprintf(output, ";!F\npop rax\nxor rax,1\npush rax\n"); return type; } int gen_value(const char ident[], Scope scope) { switch (scope) { case GLOBAL: - printf("push QWORD [rbp - %d] ;%s\n", glo_get_addr(ident), ident); + fprintf(output, "push QWORD [rbp - %d] ;%s\n", glo_get_addr(ident), ident); return glo_lookup(ident); case LOCAL: - printf("push QWORD [rbp - %d] ;%s\n", loc_get_addr(ident), ident); + fprintf(output, "push QWORD [rbp - %d] ;%s\n", loc_get_addr(ident), ident); return loc_lookup(ident); default: exit(1); @@ -255,14 +254,14 @@ int gen_value(const char ident[], Scope scope) { } int gen_num(int value, Scope scope) { - if (scope == LOCAL) printf("push %d\n", value); // TODO: remove if? + if (scope == LOCAL) fprintf(output, "push %d\n", value); // TODO: remove if? // stored for the semantic analysis. return INT; } int gen_char(int value, Scope scope) { - if(scope == LOCAL) printf("push %d\n", value); // TODO: remove if? + if(scope == LOCAL) fprintf(output, "push %d\n", value); // TODO: remove if? return CHAR; } diff --git a/src/generator.h b/src/generator.h index daa7339..825ec8c 100644 --- a/src/generator.h +++ b/src/generator.h @@ -6,12 +6,15 @@ #ifndef __GENERATOR_H__ #define __GENERATOR_H__ +#include + typedef enum scope { GLOBAL, LOCAL } Scope; extern int nb_globals; +FILE *output; void gen_prologue(); void gen_prologue_continue(); diff --git a/src/symbol_table.c b/src/symbol_table.c index 6f84ce4..8e6db97 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -4,6 +4,7 @@ */ #include "symbol_table.h" +#include "generator.h" extern int lineno; /* from lexical analyser */ @@ -61,15 +62,15 @@ void glo_display_table() { int count; for (count = 0; count < glo_symbol_table.size; count++) { if (glo_symbol_table.entries[count].type == INT) - printf(";entier: %s, pos: %d \n", + fprintf(output, ";entier: %s, pos: %d \n", glo_symbol_table.entries[count].name, glo_symbol_table.entries[count].addr); else - printf(";caractere: %s, pos: %d \n", + fprintf(output, ";caractere: %s, pos: %d \n", glo_symbol_table.entries[count].name, glo_symbol_table.entries[count].addr); } - printf("\n"); + fprintf(output, "\n"); } void loc_addVar(const char name[], int type) { @@ -127,21 +128,21 @@ void loc_display_table() { int count; for (count = 0; count < loc_symbol_table.size; count++) { if (loc_symbol_table.entries[count].type == INT) - printf(";entier: %s, pos: %d \n", + fprintf(output, ";entier: %s, pos: %d \n", loc_symbol_table.entries[count].name, loc_symbol_table.entries[count].addr); else - printf(";caractere: %s, pos: %d \n", + fprintf(output, ";caractere: %s, pos: %d \n", loc_symbol_table.entries[count].name, loc_symbol_table.entries[count].addr); } - printf("\n"); + fprintf(output, "\n"); } void loc_clean_table() { int i; for (i = 0; i < loc_symbol_table.size; i++) { - printf("pop eax\n"); + fprintf(output, "pop eax\n"); } loc_symbol_table.size = 0; } diff --git a/src/tpc.y b/src/tpc.y index 6da63ef..b5ab84c 100644 --- a/src/tpc.y +++ b/src/tpc.y @@ -11,9 +11,10 @@ * */ -#include int nb_globals = 0; #include "symbol_table.h" +#include +#include #include "generator.h" extern int lineno; @@ -182,5 +183,23 @@ void yyerror(char *msg){ } int main(int argc, char **argv) { + char opt; + + output = stdout; + while ((opt = getopt(argc, argv, "o:")) != -1) + switch (opt) { + case 'o': + output = fopen(optarg, "w+"); + if (output == NULL) { + perror("Error opening output file: "); + return -1; + } + break; + + default: + fputs("Exiting due to invalid option.\n", stderr); + return -1; + } + return yyparse(); } -- cgit v1.2.3