harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 770c3280c3f8fc7a1f6e8956831457679fada79a
parent bef5892c5acbecb8a532552753ef8013751eb651
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 30 Dec 2020 09:53:13 -0500

Implement option parsing and multi-subunit builds

Diffstat:
Msrc/check.c | 6++++--
Msrc/main.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 83 insertions(+), 11 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -695,7 +695,7 @@ check_function(struct context *ctx, return decl; } -static void +static struct declarations ** check_declarations(struct context *ctx, const struct ast_decls *adecls, struct declarations **next) @@ -727,6 +727,7 @@ check_declarations(struct context *ctx, adecls = adecls->next; } trleave(TR_CHECK, NULL); + return next; } static void @@ -805,11 +806,12 @@ check(const struct ast_unit *aunit, struct unit *unit) // Second pass populates the expression graph struct scopes *scope = subunit_scopes; + struct declarations **next_decl = &unit->declarations; for (const struct ast_subunit *su = &aunit->subunits; su; su = su->next) { ctx.scope = scope->scope; trenter(TR_CHECK, "scope %p", ctx.scope); - check_declarations(&ctx, &su->decls, &unit->declarations); + next_decl = check_declarations(&ctx, &su->decls, next_decl); trleave(TR_CHECK, NULL); scope = scope->next; } diff --git a/src/main.c b/src/main.c @@ -1,6 +1,9 @@ +#include <assert.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "ast.h" #include "check.h" #include "emit.h" @@ -8,6 +11,15 @@ #include "lex.h" #include "parse.h" #include "qbe.h" +#include "util.h" + +static void +usage(const char *argv_0) +{ + fprintf(stderr, + "Usage: %s [-o output] [-T tags...] [-T typdefs] [-N namespace]\n", + argv_0); +} enum stage { STAGE_LEX, @@ -42,19 +54,66 @@ int main(int argc, char *argv[]) { enum stage stage = parse_stage(getenv("HA_STAGE")); + char *output = NULL; + int c; + while ((c = getopt(argc, argv, "o:T:t:N:")) != -1) { + switch (c) { + case 'o': + output = optarg; + break; + case 'T': + assert(0); // TODO: Build tags + case 't': + assert(0); // TODO: Typedefs + case 'N': + assert(0); // TODO: Namespace + default: + usage(argv[0]); + return 1; + } + } + + size_t ninputs = argc - optind; + if (ninputs == 0) { + usage(argv[0]); + return 1; + } + + struct ast_unit aunit = {0}; + struct ast_subunit *subunit = &aunit.subunits; + struct ast_subunit **next = &aunit.subunits.next; struct lexer lexer; - lex_init(&lexer, stdin); - if (stage == STAGE_LEX) { - struct token tok; - while (lex(&lexer, &tok) != T_EOF); + for (size_t i = 0; i < ninputs; ++i) { + FILE *in; + const char *path = argv[optind + i]; + if (strcmp(path, "-") == 0) { + in = stdin; + } else { + in = fopen(path, "r"); + } + + if (!in) { + fprintf(stderr, "Unable to open %s for reading: %s\n", + path, strerror(errno)); + return 1; + } + + lex_init(&lexer, in); + if (stage == STAGE_LEX) { + struct token tok; + while (lex(&lexer, &tok) != T_EOF); + } else { + parse(&lexer, subunit); + if (i + 1 < ninputs) { + *next = xcalloc(1, sizeof(struct ast_subunit)); + subunit = *next; + next = &subunit->next; + } + } lex_finish(&lexer); - return 0; } - struct ast_unit aunit = {0}; - parse(&lexer, &aunit.subunits); - lex_finish(&lexer); if (stage == STAGE_PARSE) { return 0; } @@ -71,6 +130,17 @@ main(int argc, char *argv[]) return 0; } - emit(&prog, stdout); + FILE *out; + if (!output) { + out = stdout; + } else { + out = fopen(output, "w"); + if (!out) { + fprintf(stderr, "Unable to open %s for writing: %s\n", + output, strerror(errno)); + return 1; + } + } + emit(&prog, out); return 0; }