diff files.c @ 6:0601b6e8e53d

checkpoint - can find files
author David A. Holland
date Sun, 19 Dec 2010 18:55:51 -0500
parents
children b8167949474a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/files.c	Sun Dec 19 18:55:51 2010 -0500
@@ -0,0 +1,345 @@
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+
+#include "array.h"
+#include "files.h"
+
+struct place {
+	struct seenfile *file;
+	unsigned line;
+	unsigned column;
+};
+
+struct incdir {
+	const char *name;
+	bool issystem;
+};
+
+struct seenfile {
+	struct place includedfrom;
+	char *name;
+	bool fromsystemdir;
+};
+
+DECLARRAY(incdir);
+DECLARRAY(seenfile);
+DEFARRAY(incdir, );
+DEFARRAY(seenfile, );
+
+static struct incdirarray quotepath, bracketpath;
+static struct seenfilearray seenfiles;
+static bool overall_failure;
+
+////////////////////////////////////////////////////////////
+// management
+
+#define DESTROYALL(T) \
+	static						\
+	void						\
+	T##array_destroyall(struct T##array *arr)	\
+	{						\
+		unsigned i, num;			\
+		struct T *t;				\
+							\
+		num = T##array_num(arr);		\
+		for (i=0; i<num; i++) {			\
+			t = T##array_get(arr, i);	\
+			T##_destroy(t);			\
+		}					\
+		T##array_setsize(arr, 0);		\
+	}
+
+static
+struct incdir *
+incdir_create(const char *name, bool issystem)
+{
+	struct incdir *id;
+
+	id = domalloc(sizeof(*id));
+	id->name = name;
+	id->issystem = issystem;
+	return id;
+}
+
+static
+void
+incdir_destroy(struct incdir *id)
+{
+	free(id);
+}
+
+static
+struct seenfile *
+seenfile_create(const struct place *from, char *name, bool fromsystemdir)
+{
+	struct seenfile *sf;
+
+	sf = domalloc(sizeof(*sf));
+	sf->includedfrom = *from;
+	sf->name = name;
+	sf->fromsystemdir = fromsystemdir;
+	return sf;
+}
+
+static
+void
+seenfile_destroy(struct seenfile *sf)
+{
+	free(sf->name);
+	free(sf);
+}
+
+void
+files_init(void)
+{
+	incdirarray_init(&quotepath);
+	incdirarray_init(&bracketpath);
+}
+
+DESTROYALL(incdir);
+DESTROYALL(seenfile);
+
+void
+files_cleanup(void)
+{
+	seenfilearray_destroyall(&seenfiles);
+	seenfilearray_cleanup(&seenfiles);
+
+	incdirarray_destroyall(&quotepath);
+	incdirarray_cleanup(&quotepath);
+	incdirarray_destroyall(&bracketpath);
+	incdirarray_cleanup(&bracketpath);
+}
+
+////////////////////////////////////////////////////////////
+// path setup
+
+void
+files_addquotepath(const char *dir, bool issystem)
+{
+	struct incdir *id;
+
+	id = incdir_create(dir, issystem);
+	incdirarray_add(&quotepath, id, NULL);
+}
+
+void
+files_addbracketpath(const char *dir, bool issystem)
+{
+	struct incdir *id;
+
+	id = incdir_create(dir, issystem);
+	incdirarray_add(&bracketpath, id, NULL);
+}
+
+////////////////////////////////////////////////////////////
+// places and complaints
+
+#define NOWHERE_LINE      0
+#define BUILTIN_LINE      1
+#define COMMANDLINE_LINE  2
+
+static struct place scratchplace;
+static bool scratchplace_inuse;
+
+static
+bool
+place_isnowhere(const struct place *p)
+{
+	return p->file == NULL && p->line == NOWHERE_LINE;
+}
+
+static
+bool
+place_isbuiltin(const struct place *p)
+{
+	return p->file == NULL && p->line == BUILTIN_LINE;
+}
+
+static
+bool
+place_iscommandline(const struct place *p)
+{
+	return p->file == NULL && p->line == COMMANDLINE_LINE;
+}
+
+struct place *
+place_gettemporary(void)
+{
+	assert(!scratchplace_inuse);
+	scratchplace_inuse = true;
+	return &scratchplace;
+}
+
+void
+place_puttemporary(struct place *p)
+{
+	assert(scratchplace_inuse);
+	assert(p == &scratchplace);
+	scratchplace_inuse = false;
+}
+
+void
+place_setnowhere(struct place *p)
+{
+	p->file = NULL;
+	p->line = NOWHERE_LINE;
+	p->column = 0;
+}
+
+void
+place_setbuiltin(struct place *p, unsigned num)
+{
+	p->file = NULL;
+	p->line = BUILTIN_LINE;
+	p->column = num;
+}
+
+void
+place_setcommandline(struct place *p, unsigned column)
+{
+	p->file = NULL;
+	p->line = COMMANDLINE_LINE;
+	p->column = column;
+}
+
+static
+void
+place_print(const struct place *p)
+{
+	if (place_iscommandline(p)) {
+		fprintf(stderr, "<command-line>:1:%u", p->column);
+	} else if (place_isbuiltin(p)) {
+		fprintf(stderr, "<built-in>:%u:1", p->column);
+	} else {
+		fprintf(stderr, "%s:%u:%u", p->file->name, p->line, p->column);
+	}
+}
+
+static
+void
+place_printfrom(const struct place *p)
+{
+	if (!place_isnowhere(&p->file->includedfrom)) {
+		place_printfrom(&p->file->includedfrom);
+	}
+	fprintf(stderr, "In file included from ");
+	fprintf(stderr, ":\n");
+}
+
+void
+complain(const struct place *p, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (!place_isnowhere(&p->file->includedfrom)) {
+		place_printfrom(&p->file->includedfrom);
+	}
+	place_print(p);
+	fprintf(stderr, ": ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+}
+
+void
+complain_fail(void)
+{
+	overall_failure = true;
+}
+
+bool
+complain_failed(void)
+{
+	return overall_failure;
+}
+
+////////////////////////////////////////////////////////////
+// parsing
+
+void
+file_read(struct seenfile *sf, int fd);
+
+////////////////////////////////////////////////////////////
+// path search
+
+static
+int
+file_tryopen(const char *file)
+{
+	int fd;
+
+	fd = open(file, O_RDONLY);
+	if (fd < 0) {
+		return -1;
+	}
+	/* XXX: do we need to do anything here or is this function pointless?*/
+	return fd;
+}
+
+static
+void
+file_search(struct place *place, struct incdirarray *path, const char *name)
+{
+	unsigned i, num;
+	struct incdir *id;
+	struct seenfile *sf;
+	char *file;
+	int fd;
+
+	assert(place != NULL);
+
+	num = incdirarray_num(path);
+	for (i=0; i<num; i++) {
+		id = incdirarray_get(path, i);
+		file = dostrdup3(id->name, "/", name);
+		fd = file_tryopen(file);
+		if (fd >= 0) {
+			sf = seenfile_create(place, file, id->issystem);
+			seenfilearray_add(&seenfiles, sf, NULL);
+			file_read(sf, fd);
+			close(fd);
+			return;
+		}
+		free(file);
+	}
+	complain(place, "Include file %s not found", name);
+	complain_fail();
+}
+
+void
+file_readquote(struct place *place, const char *name)
+{
+	file_search(place, &quotepath, name);
+}
+
+void
+file_readbracket(struct place *place, const char *name)
+{
+	file_search(place, &bracketpath, name);
+}
+
+void
+file_readabsolute(struct place *place, const char *name)
+{
+	struct seenfile *sf;
+	int fd;
+
+	assert(place != NULL);
+
+	fd = file_tryopen(name);
+	if (fd < 0) {
+		warn("%s", name);
+		die();
+	}
+	sf = seenfile_create(place, dostrdup(name), false);
+	seenfilearray_add(&seenfiles, sf, NULL);
+	file_read(sf, fd);
+	close(fd);
+}