#include "all.h" #include "str.h" #include #include #include #include #include #include int main(int argc, char *argv[]) { bool dump_c = false; bool dump_ast = false; for (int i = 1; i < argc; i++) { if (strcmp("-cdump", argv[i]) == 0) { dump_c = true; } if (strcmp("-ast_dump", argv[i]) == 0) { dump_ast = true; } } str input = {0}; str_append_fread(&input, stdin); // Run the lexer to get tokens (honestly useless considering the simplicity of // BF) lexer_t lexer = lex_init(&input); lex_run(&lexer); // Run the parser and turn tokens into an AST representation parser_t p = parser_init(&lexer); ast_node_t *ast = parse_program(&p); ast = optimize_ast(ast); if (dump_ast) ast_dump(ast, 0); str c_code = gen_code(ast); if (dump_c) fprintf(stderr, "%s\n", c_code.data); // Run gcc int fd[2]; pipe(fd); if (fork() == 0) { dup2(fd[0], STDIN_FILENO); close(fd[0]); close(fd[1]); char *argv[] = {"gcc", "-Os", "-flto", "-fuse-linker-plugin", "-DNDEBUG", "-fomit-frame-pointer", "-nostdlib", "-nostartfiles", "-ffreestanding", "-no-pie", "-fno-stack-protector", "-o", "/proc/self/fd/1", "-x", "c", "-", NULL}; execvp("gcc", argv); perror("execvp"); _exit(1); } // Cleanup close(fd[0]); write(fd[1], c_code.data, strlen(c_code.data)); close(fd[1]); int status; wait(&status); if (WIFEXITED(status)) { int code = WEXITSTATUS(status); if (code != 0) { fprintf(stderr, "GCC failed with exit code %d\n", code); fprintf(stderr, "Dumping C code:\n%s\n", c_code.data); } } else if (WIFSIGNALED(status)) { fprintf(stderr, "GCC killed by signal %d\n", WTERMSIG(status)); } else { fprintf(stderr, "GCC died in an unknown and mysterious way\n"); } ast_free(ast); free_str(&input); return 0; }