summaryrefslogtreecommitdiff
path: root/srcpos.c
diff options
context:
space:
mode:
Diffstat (limited to 'srcpos.c')
-rw-r--r--srcpos.c151
1 files changed, 68 insertions, 83 deletions
diff --git a/srcpos.c b/srcpos.c
index 8bb0c02..f08c1c3 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -25,117 +25,102 @@
#include "srcpos.h"
-/*
- * Like yylineno, this is the current open file pos.
- */
-struct dtc_file *srcpos_file;
+static char *dirname(const char *path)
+{
+ const char *slash = strrchr(path, '/');
-/*
- * The empty source position.
- */
+ if (slash) {
+ int len = slash - path;
+ char *dir = xmalloc(len + 1);
-struct dtc_file dtc_empty_file = {
- .dir = NULL,
- .name = "<no file>",
- .file = NULL
-};
+ memcpy(dir, path, len);
+ dir[len] = '\0';
+ return dir;
+ }
+ return NULL;
+}
-srcpos srcpos_empty = {
- .first_line = 0,
- .first_column = 0,
- .last_line = 0,
- .last_column = 0,
- .file = &dtc_empty_file
-};
+struct srcfile_state *current_srcfile; /* = NULL */
+/* Detect infinite include recursion. */
+#define MAX_SRCFILE_DEPTH (100)
+static int srcfile_depth; /* = 0 */
-static int
-dtc_open_one(struct dtc_file *file, const char *search, const char *fname)
+FILE *srcfile_relative_open(const char *fname, char **fullnamep)
{
+ FILE *f;
char *fullname;
- if (search) {
- fullname = xmalloc(strlen(search) + strlen(fname) + 2);
-
- strcpy(fullname, search);
- strcat(fullname, "/");
- strcat(fullname, fname);
+ if (streq(fname, "-")) {
+ f = stdin;
+ fullname = xstrdup("<stdin>");
} else {
- fullname = xstrdup(fname);
+ if (!current_srcfile || !current_srcfile->dir
+ || (fname[0] == '/'))
+ fullname = xstrdup(fname);
+ else
+ fullname = join_path(current_srcfile->dir, fname);
+
+ f = fopen(fullname, "r");
+ if (!f)
+ die("Couldn't open \"%s\": %s\n", fname,
+ strerror(errno));
}
- file->file = fopen(fullname, "r");
- if (!file->file) {
+ if (fullnamep)
+ *fullnamep = fullname;
+ else
free(fullname);
- return 0;
- }
- file->name = fullname;
- return 1;
+ return f;
}
-
-struct dtc_file *
-dtc_open_file(const char *fname, const struct search_path *search)
+void srcfile_push(const char *fname)
{
- static const struct search_path default_search = { NULL, NULL, NULL };
+ struct srcfile_state *srcfile;
- struct dtc_file *file;
- const char *slash;
+ if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
+ die("Includes nested too deeply");
- file = xmalloc(sizeof(struct dtc_file));
+ srcfile = xmalloc(sizeof(*srcfile));
- slash = strrchr(fname, '/');
- if (slash) {
- char *dir = xmalloc(slash - fname + 1);
-
- memcpy(dir, fname, slash - fname);
- dir[slash - fname] = 0;
- file->dir = dir;
- } else {
- file->dir = NULL;
- }
-
- if (streq(fname, "-")) {
- file->name = "stdin";
- file->file = stdin;
- return file;
- }
-
- if (fname[0] == '/') {
- file->file = fopen(fname, "r");
- if (!file->file)
- goto fail;
+ srcfile->f = srcfile_relative_open(fname, &srcfile->name);
+ srcfile->dir = dirname(srcfile->name);
+ srcfile->prev = current_srcfile;
+ current_srcfile = srcfile;
+}
- file->name = xstrdup(fname);
- return file;
- }
+int srcfile_pop(void)
+{
+ struct srcfile_state *srcfile = current_srcfile;
- if (!search)
- search = &default_search;
+ assert(srcfile);
- while (search) {
- if (dtc_open_one(file, search->dir, fname))
- return file;
+ current_srcfile = srcfile->prev;
- if (errno != ENOENT)
- goto fail;
+ if (fclose(srcfile->f))
+ die("Error closing \"%s\": %s\n", srcfile->name, strerror(errno));
- search = search->next;
- }
+ /* FIXME: We allow the srcfile_state structure to leak,
+ * because it could still be referenced from a location
+ * variable being carried through the parser somewhere. To
+ * fix this we could either allocate all the files from a
+ * table, or use a pool allocator. */
-fail:
- die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
+ return current_srcfile ? 1 : 0;
}
+/*
+ * The empty source position.
+ */
-void
-dtc_close_file(struct dtc_file *file)
-{
- if (fclose(file->file))
- die("Error closing \"%s\": %s\n", file->name, strerror(errno));
-}
-
+srcpos srcpos_empty = {
+ .first_line = 0,
+ .first_column = 0,
+ .last_line = 0,
+ .last_column = 0,
+ .file = NULL,
+};
srcpos *
srcpos_copy(srcpos *pos)