diff options
Diffstat (limited to 'src/prc1/im.c')
| -rw-r--r-- | src/prc1/im.c | 144 |
1 files changed, 98 insertions, 46 deletions
diff --git a/src/prc1/im.c b/src/prc1/im.c index e9a208c..68ff9f3 100644 --- a/src/prc1/im.c +++ b/src/prc1/im.c @@ -1,77 +1,143 @@ #include "im.h" +#include "dbg.h" #include "errloc.h" #include "fn.h" #include "prv.h" #include "parse.h" +#include "sym.h" #include <errno.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -static int imlit(const struct lex *, struct prv *); - -static const struct seq seqs[] = -{ - {(struct step[]){{LIT, NULL, 1}, {0}}, .fn = imlit}, - {0} -}; - void im_free(struct im *im) { ast_free(&im->ast); lex_free(&im->l); } +static FILE *tryinc(const char *dir, const char *path, char **fullpath) +{ + FILE *ret = NULL; + size_t n = strlen(dir) + strlen(path) + 2; + char *fp = malloc(n); + + if (!fp) + { + perror("malloc(3)"); + goto end; + } + else if (snprintf(fp, n, "%s/%s", dir, path) < 0) + { + fprintf(stderr, "%s: snprintf(3) failed\n", __func__); + goto end; + } + else if ((ret = fopen(fp, "rb"))) + *fullpath = fp; + +end: + if (!ret) + free(fp); + + return ret; +} + +static char *fpath(const char *cur, const char *path) +{ + const char *sl = strrchr(cur, '/'); + char *ret; + /* '/' + '\0' */ + size_t n = 2; + int curlen; + + if (!sl) + { + cur = "."; + curlen = 1; + } + else + curlen = sl - cur; + + n += curlen + strlen(path); + + if ((ret = malloc(n))) + snprintf(ret, n, "%.*s/%s", curlen, cur, path); + else + perror("malloc(3)"); + + return ret; +} + static int doim(const struct lex *l, const struct tk *tk, struct prv *p) { int ret = -1; FILE *f = NULL; struct im *im; - struct fn *fn = fn_cur(p); + struct fn *fn = fn_cur(p), *fns = NULL; struct ast *ast; - size_t n = fn->nimps + 1; const char *path = tk->s; + size_t n = fn->nimps + 1; + char *fp = NULL, *incfp; + const struct loc *loc = &tk->loc; - if (!strcmp(l->loc.f, path)) - { - errloc(tk, "detected recursive import \"%s\"", path); + /* TODO: no protection against recursive imports */ + if (!(fp = fpath(l->loc.f, path))) goto end; + else if (!(f = fopen(fp, "rb"))) + { + const struct arg_input *incs = &l->args->incs; + + for (size_t i = 0; i < incs->n; i++) + if ((f = tryinc(incs->v[i], path, &incfp))) + { + free(fp); + fp = incfp; + break; + } } - /* TODO: honor -I flags */ - if (!(f = fopen(path, "rb"))) + + if (!f) { - errloc(tk, "failed to open import \"%s\": %s", path, strerror(errno)); + errloc(tk, "failed to open import \"%s\"", path); goto end; } - else if (!(im = realloc(fn->imps, n * sizeof *im))) + else if (!(fns = malloc(sizeof *fns))) { - perror("realloc(3)"); + perror("malloc(3)"); goto end; } - fn->imps = im; - im = &fn->imps[fn->nimps++]; - *im = (struct im){.l.loc.f = path}; - ast = &im->ast; + *fns = (struct fn){.tk = tk}; - if (!(ast->fns = malloc(sizeof *ast->fns))) + if (!(im = realloc(fn->imps, n * sizeof *im))) { - perror("malloc(3)"); + perror("realloc(3)"); goto end; } - *ast->fns = (struct fn){.tk = tk}; + fn->imps = im; + im = &fn->imps[fn->nimps++]; + *im = (struct im){.l = {.loc.f = fp, .args = l->args}}; + ast = &im->ast; + ast->fns = fns; /* hack: treat imports as a function */ ast->nfns = 1; + fp = NULL; + dbg("start import %s (from %s:%d:%d)\n", im->l.loc.f, loc->f, loc->line, + loc->col); if (lex(&im->l, f) || parse_im(&im->l, ast)) goto end; + dbg("end import %s\n", im->l.loc.f); ret = 0; end: + if (ret) + free(fp); + if (f && fclose(f)) { fprintf(stderr, "fclose(3) %s: %s\n", path, strerror(errno)); @@ -81,30 +147,19 @@ end: return ret; } -static int imlit(const struct lex *l, struct prv *p) +static int onsym(const struct lex *l, struct prv *p, const struct sym *s) { - const struct tk *tk = p->stk; - - while (!lex_eof(l, tk) && !kw(tk->s)) - if (doim(l, tk++, p)) - return -1; - - if (pop(l, p)) + if (s->type != SYM_LIT) + { + errloc(s->tk, "expected literal"); return -1; + } - p->stk = p->tk; - return 1; + return doim(l, s->tk, p); } int im(const struct lex *l, struct prv *p) { - struct pos init = - { - .seq = seqs, - .stseq = seqs, - .step = seqs->steps - }; - struct fn *fn = fn_cur(p); if (fn->im) @@ -116,10 +171,7 @@ int im(const struct lex *l, struct prv *p) return -1; } - if (push(&init, p)) - return -1; - fn->im = p->stk; p->stk = p->tk; - return 1; + return sym(p, onsym); } |
