aboutsummaryrefslogtreecommitdiff
path: root/src/prc1/im.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/prc1/im.c')
-rw-r--r--src/prc1/im.c144
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);
}