From b41275f6f4cbbf2ec79226931aa4f2130d1ead1f Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Sun, 21 Jun 2020 16:27:37 -0700 Subject: [PATCH] jaf: support multiple input files --- include/system4/ain.h | 1 + src/ain.c | 7 ++ src/tools/ainedit/ainedit.c | 11 ++-- src/tools/ainedit/jaf.h | 12 +++- src/tools/ainedit/jaf_ast.c | 8 +++ src/tools/ainedit/jaf_compile.c | 87 +++++++++---------------- src/tools/ainedit/jaf_parser.y | 73 ++++++++++++++++++++- src/tools/ainedit/jaf_static_analysis.c | 5 +- 8 files changed, 139 insertions(+), 65 deletions(-) diff --git a/include/system4/ain.h b/include/system4/ain.h index 91e9a07..d0d6561 100644 --- a/include/system4/ain.h +++ b/include/system4/ain.h @@ -334,6 +334,7 @@ int ain_get_global_no(struct ain *ain, char *name); void ain_add_initval(struct ain *ain, struct ain_initval *init); int ain_add_function(struct ain *ain, struct ain_function *fun); int ain_add_string(struct ain *ain, const char *str); +int ain_add_file(struct ain *ain, const char *filename); void ain_free(struct ain *ain); void ain_free_functions(struct ain *ain); diff --git a/src/ain.c b/src/ain.c index 962de3c..f14e275 100644 --- a/src/ain.c +++ b/src/ain.c @@ -293,6 +293,13 @@ int ain_add_string(struct ain *ain, const char *str) return i; } +int ain_add_file(struct ain *ain, const char *filename) +{ + ain->filenames = xrealloc_array(ain->filenames, ain->nr_filenames, ain->nr_filenames+1, sizeof(char*)); + ain->filenames[ain->nr_filenames++] = strdup(filename); + return ain->nr_filenames - 1; +} + static const char *errtab[AIN_MAX_ERROR] = { [AIN_SUCCESS] = "Success", [AIN_FILE_ERROR] = "Error opening AIN file", diff --git a/src/tools/ainedit/ainedit.c b/src/tools/ainedit/ainedit.c index 5cf9005..ed9f18e 100644 --- a/src/tools/ainedit/ainedit.c +++ b/src/tools/ainedit/ainedit.c @@ -91,7 +91,8 @@ int main(int argc, char *argv[]) struct ain *ain; int err = AIN_SUCCESS; const char *code_file = NULL; - const char *jaf_file = NULL; + unsigned nr_jaf_files = 0; + const char **jaf_files = NULL; const char *decl_file = NULL; const char *text_file = NULL; const char *output_file = NULL; @@ -133,7 +134,8 @@ int main(int argc, char *argv[]) code_file = optarg; break; case LOPT_JAF: - jaf_file = optarg; + jaf_files = xrealloc_array(jaf_files, nr_jaf_files, nr_jaf_files+1, sizeof(char*)); + jaf_files[nr_jaf_files++] = optarg; break; case 'j': case LOPT_JSON: @@ -214,8 +216,8 @@ int main(int argc, char *argv[]) read_declarations(decl_file, ain); } - if (jaf_file) { - jaf_compile(ain, jaf_file); + if (jaf_files) { + jaf_build(ain, jaf_files, nr_jaf_files); } if (code_file) { @@ -230,6 +232,7 @@ write_ain_file: NOTICE("Writing AIN file..."); ain_write(output_file, ain); + free(jaf_files); ain_free(ain); return 0; } diff --git a/src/tools/ainedit/jaf.h b/src/tools/ainedit/jaf.h index 0c5cd4e..e94d467 100644 --- a/src/tools/ainedit/jaf.h +++ b/src/tools/ainedit/jaf.h @@ -194,7 +194,8 @@ enum block_item_kind { JAF_STMT_BREAK, JAF_STMT_RETURN, JAF_STMT_CASE, - JAF_STMT_DEFAULT + JAF_STMT_DEFAULT, + JAF_EOF }; struct jaf_declaration { @@ -251,6 +252,7 @@ struct jaf_block_item { struct jaf_block_item *body; } for_loop; struct string *target; // goto + unsigned file_no; // eof }; }; @@ -301,6 +303,7 @@ struct jaf_block *jaf_type_declaration(struct jaf_type_specifier *type); struct jaf_block *jaf_merge_blocks(struct jaf_block *head, struct jaf_block *tail); struct jaf_block *jaf_block(struct jaf_block_item *item); +struct jaf_block *jaf_block_append(struct jaf_block *head, struct jaf_block_item *tail); struct jaf_block_item *jaf_compound_statement(struct jaf_block *block); struct jaf_block_item *jaf_label_statement(struct string *label, struct jaf_block_item *stmt); struct jaf_block_item *jaf_case_statement(struct jaf_expression *expr, struct jaf_block_item *stmt); @@ -318,10 +321,13 @@ struct jaf_block_item *jaf_return(struct jaf_expression *expr); void jaf_free_expr(struct jaf_expression *expr); void jaf_free_block(struct jaf_block *block); -// jaf_compile.c +// jaf_parser.y struct ain *jaf_ain_out; struct jaf_block *jaf_toplevel; -void jaf_compile(struct ain *out, const char *path); +struct jaf_block *jaf_parse(struct ain *ain, const char **files, unsigned nr_files); + +// jaf_compile.c +void jaf_build(struct ain *out, const char **files, unsigned nr_files); void jaf_define_struct(struct ain *ain, struct jaf_type_specifier *type); // jaf_eval.c diff --git a/src/tools/ainedit/jaf_ast.c b/src/tools/ainedit/jaf_ast.c index e3399d0..77ffeac 100644 --- a/src/tools/ainedit/jaf_ast.c +++ b/src/tools/ainedit/jaf_ast.c @@ -281,6 +281,13 @@ struct jaf_block *jaf_merge_blocks(struct jaf_block *head, struct jaf_block *tai return head; } +struct jaf_block *jaf_block_append(struct jaf_block *head, struct jaf_block_item *tail) +{ + head->items = xrealloc_array(head->items, head->nr_items, head->nr_items+1, sizeof(struct jaf_block_item*)); + head->items[head->nr_items++] = tail; + return head; +} + struct jaf_block *jaf_block(struct jaf_block_item *item) { struct jaf_block *block = xcalloc(1, sizeof(struct jaf_block)); @@ -504,6 +511,7 @@ void jaf_free_block_item(struct jaf_block_item *item) free_string(item->target); case JAF_STMT_CONTINUE: case JAF_STMT_BREAK: + case JAF_EOF: break; case JAF_STMT_RETURN: jaf_free_expr(item->expr); diff --git a/src/tools/ainedit/jaf_compile.c b/src/tools/ainedit/jaf_compile.c index 77a679b..f8b1c1b 100644 --- a/src/tools/ainedit/jaf_compile.c +++ b/src/tools/ainedit/jaf_compile.c @@ -29,12 +29,6 @@ #include "jaf.h" #include "jaf_parser.tab.h" -FILE *yyin; -int yyparse(void); - -struct ain *jaf_ain_out; -struct jaf_block *jaf_toplevel; - /* * NOTE: We need to pass some state between calls to handle * break/continue. @@ -53,18 +47,6 @@ struct compiler_state { struct loop_state *loops; }; -int sym_type(char *name) -{ - char *u = encode_text_to_input_format(name); - struct ain_struct *s = ain_get_struct(jaf_ain_out, u); - free(u); - - if (s) { - return TYPEDEF_NAME; - } - return IDENTIFIER; -} - static void start_loop(struct compiler_state *state) { state->loops = xrealloc_array(state->loops, state->nr_loops, state->nr_loops+1, sizeof(struct loop_state)); @@ -805,6 +787,9 @@ static void compile_statement(struct compiler_state *state, struct jaf_block_ite case JAF_STMT_DEFAULT: ERROR("switch not supported"); break; + case JAF_EOF: + write_instruction1(state, _EOF, item->file_no); + break; } } @@ -819,8 +804,8 @@ static void compile_function(struct compiler_state *state, struct jaf_declaratio { assert(decl->func_no >= 0 && decl->func_no < state->ain->nr_functions); state->func_no = decl->func_no; - state->ain->functions[decl->func_no].address = state->out.index + 6; write_instruction1(state, FUNC, decl->func_no); + state->ain->functions[decl->func_no].address = state->out.index; compile_block(state, decl->body); compile_nullexpr(state, state->ain->functions[state->func_no].return_type.data); write_instruction0(state, RETURN); @@ -833,6 +818,9 @@ static void compile_declaration(struct compiler_state *state, struct jaf_block_i compile_function(state, &decl->decl); return; } + if (decl->kind == JAF_EOF) { + compile_statement(state, decl); + } // TODO: global constructors/array allocations } @@ -858,58 +846,45 @@ static void compile_global_init_function(struct compiler_state *state) write_instruction1(state, ENDFUNC, func_no); } -void jaf_compile(struct ain *out, const char *path) +static void jaf_compile(struct ain *ain, struct jaf_block *toplevel) { - out->keycode = 0x2d1f2904; - if (path) { - if (!strcmp(path, "-")) - yyin = stdin; - else - yyin = fopen(path, "rb"); - if (!yyin) - ERROR("Opening input file '%s': %s", path, strerror(errno)); - } - jaf_ain_out = out; - yyparse(); - - if (!jaf_toplevel) - ERROR("Failed to parse .jaf file"); - - jaf_toplevel = jaf_static_analyze(out, jaf_toplevel); - + assert(toplevel->nr_items > 0); struct compiler_state state = { - .ain = out, + .ain = ain, .out = { - .buf = out->code, - .size = out->code_size, - .index = out->code_size + .buf = ain->code, + .size = ain->code_size, + .index = ain->code_size } }; - for (size_t i = 0; i < jaf_toplevel->nr_items; i++) { - compile_declaration(&state, jaf_toplevel->items[i]); + for (size_t i = 0; i < toplevel->nr_items - 1; i++) { + compile_declaration(&state, toplevel->items[i]); } compile_global_init_function(&state); - state.ain->functions[0].address = state.out.index + 6; + // add NULL function write_instruction1(&state, FUNC, 0); - write_instruction1(&state, _EOF, out->nr_filenames); + state.ain->functions[0].address = state.out.index; - // add filename to ain file - char *filename = strdup(path); - out->filenames = xrealloc_array(out->filenames, out->nr_filenames, out->nr_filenames+1, sizeof(char*)); - out->filenames[out->nr_filenames++] = strdup(basename(filename)); - free(filename); + // add final EOF + compile_declaration(&state, toplevel->items[toplevel->nr_items-1]); free(state.loops); - out->code = state.out.buf; - out->code_size = state.out.index; + ain->code = state.out.buf; + ain->code_size = state.out.index; // XXX: ain_add_initval adds initval to GSET section of the ain file. // If the original ain file did not have a GSET section, init // code needs to be added to the "0" function instead. - if (out->nr_initvals && !out->GSET.present) { - WARNING("%d global initvals ignored", out->nr_initvals); - } + if (ain->nr_initvals && !ain->GSET.present) + WARNING("%d global initvals ignored", ain->nr_initvals); +} - jaf_free_block(jaf_toplevel); +void jaf_build(struct ain *out, const char **files, unsigned nr_files) +{ + struct jaf_block *toplevel; + toplevel = jaf_parse(out, files, nr_files); + toplevel = jaf_static_analyze(out, toplevel); + jaf_compile(out, toplevel); + jaf_free_block(toplevel); } diff --git a/src/tools/ainedit/jaf_parser.y b/src/tools/ainedit/jaf_parser.y index 921a380..89e262f 100644 --- a/src/tools/ainedit/jaf_parser.y +++ b/src/tools/ainedit/jaf_parser.y @@ -17,11 +17,82 @@ */ %{ +#include +#include +#include +#include +#include +#include #include "system4.h" #include "system4/ain.h" +#include "ainedit.h" #include "jaf.h" +#include "jaf_parser.tab.h" extern int yylex(); void yyerror(const char *s); +int yyparse(void); +FILE *yyin; + +struct ain *jaf_ain_out; +struct jaf_block *jaf_toplevel; + +static FILE *open_jaf_file(const char *file) +{ + if (!strcmp(file, "-")) + return stdin; + FILE *f = fopen(file, "rb"); + if (!f) + ERROR("Opening input file '%s': %s", file, strerror(errno)); + return f; +} + +static struct jaf_block *insert_eof(struct ain *ain, struct jaf_block *block, const char *_filename) +{ + assert(block); + char *filename = xstrdup(_filename); + int file_no = ain_add_file(ain, basename(filename)); + free(filename); + + struct jaf_block_item *eof = xmalloc(sizeof(struct jaf_block_item)); + eof->kind = JAF_EOF; + eof->file_no = file_no; + return jaf_block_append(block, eof); +} + +struct jaf_block *jaf_parse(struct ain *ain, const char **files, unsigned nr_files) +{ + jaf_ain_out = ain; + jaf_toplevel = NULL; + + for (unsigned i = 0; i < nr_files; i++) { + // open file + yyin = open_jaf_file(files[i]); + if (yyparse()) + ERROR("Failed to parse .jaf file"); + if (yyin != stdin) + fclose(yyin); + + jaf_toplevel = insert_eof(ain, jaf_toplevel, files[i]); + } + + struct jaf_block *r = jaf_toplevel; + jaf_toplevel = NULL; + jaf_ain_out = NULL; + return r; +} + +int sym_type(char *name) +{ + char *u = encode_text_to_input_format(name); + struct ain_struct *s = ain_get_struct(jaf_ain_out, u); + free(u); + + if (s) { + return TYPEDEF_NAME; + } + return IDENTIFIER; +} + %} %union { @@ -421,7 +492,7 @@ jump_statement ; toplevel - : translation_unit { jaf_toplevel = $1; } + : translation_unit { jaf_toplevel = jaf_merge_blocks(jaf_toplevel, $1); } ; translation_unit diff --git a/src/tools/ainedit/jaf_static_analysis.c b/src/tools/ainedit/jaf_static_analysis.c index 9fb40c6..c852ab4 100644 --- a/src/tools/ainedit/jaf_static_analysis.c +++ b/src/tools/ainedit/jaf_static_analysis.c @@ -261,6 +261,7 @@ static void analyze_statement(struct jaf_env *env, struct jaf_block_item *item) case JAF_STMT_GOTO: case JAF_STMT_CONTINUE: case JAF_STMT_BREAK: + case JAF_EOF: break; } } @@ -347,6 +348,7 @@ static void resolve_statement_types(struct ain *ain, struct jaf_block_item *item case JAF_STMT_CONTINUE: case JAF_STMT_BREAK: case JAF_STMT_RETURN: + case JAF_EOF: break; } } @@ -429,6 +431,7 @@ static struct ain_variable *block_item_get_vars(struct ain *ain, struct jaf_bloc case JAF_STMT_CONTINUE: case JAF_STMT_BREAK: case JAF_STMT_RETURN: + case JAF_EOF: break; case JAF_FUNDECL: @@ -492,7 +495,7 @@ static void jaf_process_declarations(struct ain *ain, struct jaf_block *block) if (block->items[i]->decl.name) { if (block->items[i]->kind == JAF_FUNDECL) add_function(ain, &block->items[i]->decl); - else + else if (block->items[i]->kind == JAF_DECLARATION) add_global(ain, &block->items[i]->decl); } }