diff --git a/frontend/cmd/assemble.c b/frontend/cmd/assemble.c index 9eab1e4..db30705 100644 --- a/frontend/cmd/assemble.c +++ b/frontend/cmd/assemble.c @@ -1,15 +1,95 @@ +#include "../debug.h" #include "cmd.h" #include +#include +#include +#include +#include +#include + +enum { + ARG_SOURCE_FILE, +}; + +static int assemble_file(const char *path) +{ + FILE *fp = fopen(path, "r"); + if (!fp) { + b_err("cannot open source file '%s'", path); + b_i("reason: %s", strerror(errno)); + return -1; + } + + struct ivy_file *src = ivy_file_from_fp(fp); + struct ivy_asm_lexer *lex; + if (ivy_asm_lexer_create(&lex) != IVY_OK) { + b_err("failed to initialise Ivy assembly lexer"); + ivy_file_close(src); + return -1; + } + + ivy_asm_lexer_set_source(lex, &src->f_base); + enum ivy_status status = IVY_OK; + + while (true) { + struct ivy_asm_token *tok = ivy_asm_lexer_read(lex); + status = ivy_asm_lexer_get_status(lex); + if (status == IVY_ERR_EOF) { + break; + } + + if (status != IVY_OK) { + b_err("failed to parse '%s'", path); + b_i("reason: lex error (%s)", + ivy_status_to_string(ivy_asm_lexer_get_status(lex))); + break; + } + + print_asm_lex_token(tok); + } + + int r = (status == IVY_OK || status == IVY_ERR_EOF) ? 0 : -1; + ivy_file_close(src); + ivy_asm_lexer_destroy(lex); + return r; +} + +static int assemble(const b_command *cmd, const b_arglist *args, const b_array *_) +{ + b_arglist_iterator it; + b_arglist_foreach_filtered(&it, args, B_COMMAND_INVALID_ID, ARG_SOURCE_FILE) + { + b_arglist_value *path = it.value; + if (path->val_type != B_COMMAND_ARG_STRING) { + continue; + } + + printf("%s\n", path->val_str); + int r = assemble_file(path->val_str); + if (r != 0) { + return r; + } + } + + return 0; +} B_COMMAND(CMD_ASSEMBLE, CMD_ROOT) { B_COMMAND_NAME("assemble"); B_COMMAND_SHORT_NAME('A'); B_COMMAND_DESC( - "assemble one or more Ivy assembly source files into Ivy " - "object files."); + "assemble one or more Ivy assembly source files into Ivy object files."); B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); + B_COMMAND_FUNCTION(assemble); + + B_COMMAND_ARG(ARG_SOURCE_FILE) + { + B_ARG_NAME("source file"); + B_ARG_DESC("the .iasm assembly files to compile."); + B_ARG_NR_VALUES(B_ARG_1_OR_MORE_VALUES); + } B_COMMAND_HELP_OPTION(); }