summaryrefslogtreecommitdiffstats
path: root/contrib/dtc/srcpos.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/dtc/srcpos.c')
-rw-r--r--contrib/dtc/srcpos.c332
1 files changed, 211 insertions, 121 deletions
diff --git a/contrib/dtc/srcpos.c b/contrib/dtc/srcpos.c
index 8bb0c02..3ee523d 100644
--- a/contrib/dtc/srcpos.c
+++ b/contrib/dtc/srcpos.c
@@ -24,126 +24,224 @@
#include "dtc.h"
#include "srcpos.h"
+/* A node in our list of directories to search for source/include files */
+struct search_path {
+ struct search_path *next; /* next node in list, NULL for end */
+ const char *dirname; /* name of directory to search */
+};
-/*
- * Like yylineno, this is the current open file pos.
- */
-struct dtc_file *srcpos_file;
+/* This is the list of directories that we search for source files */
+static struct search_path *search_path_head, **search_path_tail;
-/*
- * The empty source position.
- */
-struct dtc_file dtc_empty_file = {
- .dir = NULL,
- .name = "<no file>",
- .file = NULL
-};
+static char *dirname(const char *path)
+{
+ const char *slash = strrchr(path, '/');
-srcpos srcpos_empty = {
- .first_line = 0,
- .first_column = 0,
- .last_line = 0,
- .last_column = 0,
- .file = &dtc_empty_file
-};
+ if (slash) {
+ int len = slash - path;
+ char *dir = xmalloc(len + 1);
+
+ memcpy(dir, path, len);
+ dir[len] = '\0';
+ return dir;
+ }
+ return NULL;
+}
+
+FILE *depfile; /* = NULL */
+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)
+
+/**
+ * Try to open a file in a given directory.
+ *
+ * If the filename is an absolute path, then dirname is ignored. If it is a
+ * relative path, then we look in that directory for the file.
+ *
+ * @param dirname Directory to look in, or NULL for none
+ * @param fname Filename to look for
+ * @param fp Set to NULL if file did not open
+ * @return allocated filename on success (caller must free), NULL on failure
+ */
+static char *try_open(const char *dirname, const char *fname, FILE **fp)
{
char *fullname;
- if (search) {
- fullname = xmalloc(strlen(search) + strlen(fname) + 2);
-
- strcpy(fullname, search);
- strcat(fullname, "/");
- strcat(fullname, fname);
- } else {
+ if (!dirname || fname[0] == '/')
fullname = xstrdup(fname);
- }
+ else
+ fullname = join_path(dirname, fname);
- file->file = fopen(fullname, "r");
- if (!file->file) {
+ *fp = fopen(fullname, "r");
+ if (!*fp) {
free(fullname);
- return 0;
+ fullname = NULL;
}
- file->name = fullname;
- return 1;
+ return fullname;
}
-
-struct dtc_file *
-dtc_open_file(const char *fname, const struct search_path *search)
+/**
+ * Open a file for read access
+ *
+ * If it is a relative filename, we search the full search path for it.
+ *
+ * @param fname Filename to open
+ * @param fp Returns pointer to opened FILE, or NULL on failure
+ * @return pointer to allocated filename, which caller must free
+ */
+static char *fopen_any_on_path(const char *fname, FILE **fp)
{
- static const struct search_path default_search = { NULL, NULL, NULL };
+ const char *cur_dir = NULL;
+ struct search_path *node;
+ char *fullname;
- struct dtc_file *file;
- const char *slash;
+ /* Try current directory first */
+ assert(fp);
+ if (current_srcfile)
+ cur_dir = current_srcfile->dir;
+ fullname = try_open(cur_dir, fname, fp);
- file = xmalloc(sizeof(struct dtc_file));
+ /* Failing that, try each search path in turn */
+ for (node = search_path_head; !*fp && node; node = node->next)
+ fullname = try_open(node->dirname, fname, fp);
- slash = strrchr(fname, '/');
- if (slash) {
- char *dir = xmalloc(slash - fname + 1);
+ return fullname;
+}
- memcpy(dir, fname, slash - fname);
- dir[slash - fname] = 0;
- file->dir = dir;
- } else {
- file->dir = NULL;
- }
+FILE *srcfile_relative_open(const char *fname, char **fullnamep)
+{
+ FILE *f;
+ char *fullname;
if (streq(fname, "-")) {
- file->name = "stdin";
- file->file = stdin;
- return file;
+ f = stdin;
+ fullname = xstrdup("<stdin>");
+ } else {
+ fullname = fopen_any_on_path(fname, &f);
+ if (!f)
+ die("Couldn't open \"%s\": %s\n", fname,
+ strerror(errno));
}
- if (fname[0] == '/') {
- file->file = fopen(fname, "r");
- if (!file->file)
- goto fail;
+ if (depfile)
+ fprintf(depfile, " %s", fullname);
- file->name = xstrdup(fname);
- return file;
- }
+ if (fullnamep)
+ *fullnamep = fullname;
+ else
+ free(fullname);
- if (!search)
- search = &default_search;
+ return f;
+}
- while (search) {
- if (dtc_open_one(file, search->dir, fname))
- return file;
+void srcfile_push(const char *fname)
+{
+ struct srcfile_state *srcfile;
- if (errno != ENOENT)
- goto fail;
+ if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
+ die("Includes nested too deeply");
- search = search->next;
- }
+ srcfile = xmalloc(sizeof(*srcfile));
+
+ srcfile->f = srcfile_relative_open(fname, &srcfile->name);
+ srcfile->dir = dirname(srcfile->name);
+ srcfile->prev = current_srcfile;
-fail:
- die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
+ srcfile->lineno = 1;
+ srcfile->colno = 1;
+
+ current_srcfile = srcfile;
}
+int srcfile_pop(void)
+{
+ struct srcfile_state *srcfile = current_srcfile;
+
+ assert(srcfile);
-void
-dtc_close_file(struct dtc_file *file)
+ current_srcfile = srcfile->prev;
+
+ if (fclose(srcfile->f))
+ die("Error closing \"%s\": %s\n", srcfile->name,
+ strerror(errno));
+
+ /* 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. */
+
+ return current_srcfile ? 1 : 0;
+}
+
+void srcfile_add_search_path(const char *dirname)
{
- if (fclose(file->file))
- die("Error closing \"%s\": %s\n", file->name, strerror(errno));
+ struct search_path *node;
+
+ /* Create the node */
+ node = xmalloc(sizeof(*node));
+ node->next = NULL;
+ node->dirname = xstrdup(dirname);
+
+ /* Add to the end of our list */
+ if (search_path_tail)
+ *search_path_tail = node;
+ else
+ search_path_head = node;
+ search_path_tail = &node->next;
}
+/*
+ * The empty source position.
+ */
-srcpos *
-srcpos_copy(srcpos *pos)
+struct srcpos srcpos_empty = {
+ .first_line = 0,
+ .first_column = 0,
+ .last_line = 0,
+ .last_column = 0,
+ .file = NULL,
+};
+
+#define TAB_SIZE 8
+
+void srcpos_update(struct srcpos *pos, const char *text, int len)
{
- srcpos *pos_new;
+ int i;
+
+ pos->file = current_srcfile;
- pos_new = xmalloc(sizeof(srcpos));
- memcpy(pos_new, pos, sizeof(srcpos));
+ pos->first_line = current_srcfile->lineno;
+ pos->first_column = current_srcfile->colno;
+
+ for (i = 0; i < len; i++)
+ if (text[i] == '\n') {
+ current_srcfile->lineno++;
+ current_srcfile->colno = 1;
+ } else if (text[i] == '\t') {
+ current_srcfile->colno =
+ ALIGN(current_srcfile->colno, TAB_SIZE);
+ } else {
+ current_srcfile->colno++;
+ }
+
+ pos->last_line = current_srcfile->lineno;
+ pos->last_column = current_srcfile->colno;
+}
+
+struct srcpos *
+srcpos_copy(struct srcpos *pos)
+{
+ struct srcpos *pos_new;
+
+ pos_new = xmalloc(sizeof(struct srcpos));
+ memcpy(pos_new, pos, sizeof(struct srcpos));
return pos_new;
}
@@ -151,7 +249,7 @@ srcpos_copy(srcpos *pos)
void
-srcpos_dump(srcpos *pos)
+srcpos_dump(struct srcpos *pos)
{
printf("file : \"%s\"\n",
pos->file ? (char *) pos->file : "<no file>");
@@ -164,67 +262,59 @@ srcpos_dump(srcpos *pos)
char *
-srcpos_string(srcpos *pos)
+srcpos_string(struct srcpos *pos)
{
- const char *fname;
- char col_buf[100];
+ const char *fname = "<no-file>";
char *pos_str;
+ int rc;
- if (!pos) {
- fname = "<no-file>";
- } else if (pos->file->name) {
+ if (pos)
fname = pos->file->name;
- if (strcmp(fname, "-") == 0)
- fname = "stdin";
- } else {
- fname = "<no-file>";
- }
- if (pos->first_line == pos->last_line) {
- if (pos->first_column == pos->last_column) {
- snprintf(col_buf, sizeof(col_buf),
- "%d:%d",
- pos->first_line, pos->first_column);
- } else {
- snprintf(col_buf, sizeof(col_buf),
- "%d:%d-%d",
- pos->first_line,
- pos->first_column, pos->last_column);
- }
- } else {
- snprintf(col_buf, sizeof(col_buf),
- "%d:%d - %d:%d",
- pos->first_line, pos->first_column,
- pos->last_line, pos->last_column);
- }
+ if (pos->first_line != pos->last_line)
+ rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
+ else if (pos->first_column != pos->last_column)
+ rc = asprintf(&pos_str, "%s:%d.%d-%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_column);
+ else
+ rc = asprintf(&pos_str, "%s:%d.%d", fname,
+ pos->first_line, pos->first_column);
- if (asprintf(&pos_str, "%s %s", fname, col_buf) == -1)
- return "<unknown source position?";
+ if (rc == -1)
+ die("Couldn't allocate in srcpos string");
return pos_str;
}
-
void
-srcpos_error(srcpos *pos, char const *fmt, ...)
+srcpos_verror(struct srcpos *pos, char const *fmt, va_list va)
{
- const char *srcstr;
- va_list va;
- va_start(va, fmt);
+ const char *srcstr;
- srcstr = srcpos_string(pos);
+ srcstr = srcpos_string(pos);
- fprintf(stderr, "Error: %s ", srcstr);
- vfprintf(stderr, fmt, va);
- fprintf(stderr, "\n");
+ fprintf(stdout, "Error: %s ", srcstr);
+ vfprintf(stdout, fmt, va);
+ fprintf(stdout, "\n");
+}
+void
+srcpos_error(struct srcpos *pos, char const *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ srcpos_verror(pos, fmt, va);
va_end(va);
}
void
-srcpos_warn(srcpos *pos, char const *fmt, ...)
+srcpos_warn(struct srcpos *pos, char const *fmt, ...)
{
const char *srcstr;
va_list va;
OpenPOWER on IntegriCloud