changeset 6:0601b6e8e53d

checkpoint - can find files
author David A. Holland
date Sun, 19 Dec 2010 18:55:51 -0500
parents 7c489c73d62b
children b8167949474a
files Makefile array.h files.c files.h main.c utils.h
diffstat 6 files changed, 458 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun Dec 19 17:53:49 2010 -0500
+++ b/Makefile	Sun Dec 19 18:55:51 2010 -0500
@@ -1,7 +1,7 @@
 #	$NetBSD$
 
 PROG=	tradcpp
-SRCS=	main.c array.c utils.c
+SRCS=	main.c files.c array.c utils.c
 WARNS=	5
 
 .include <bsd.prog.mk>
--- a/array.h	Sun Dec 19 17:53:49 2010 -0500
+++ b/array.h	Sun Dec 19 18:55:51 2010 -0500
@@ -30,6 +30,7 @@
 #ifndef ARRAY_H
 #define ARRAY_H
 
+#include "inlinedefs.h" // XXX
 #include "utils.h"
 
 #define ARRAYS_CHECKED
--- /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);
+}
--- a/files.h	Sun Dec 19 17:53:49 2010 -0500
+++ b/files.h	Sun Dec 19 18:55:51 2010 -0500
@@ -1,6 +1,17 @@
 struct place;
 
+struct place *place_gettemporary(void);
+void place_puttemporary(struct place *p);
+void place_setnowhere(struct place *p);
+void place_setbuiltin(struct place *p, unsigned num);
+void place_setcommandline(struct place *p, unsigned column);
+
+void files_init(void);
+void files_cleanup(void);
+
 void files_addquotepath(const char *dir, bool issystem);
 void files_addbracketpath(const char *dir, bool issystem);
 
-void files_read(struct place *, const char *name);
+void file_readquote(struct place *, const char *name);
+void file_readbracket(struct place *, const char *name);
+void file_readabsolute(struct place *, const char *name);
--- a/main.c	Sun Dec 19 17:53:49 2010 -0500
+++ b/main.c	Sun Dec 19 18:55:51 2010 -0500
@@ -5,7 +5,6 @@
 #include <errno.h>
 #include <err.h>
 
-#include "inlinedefs.h" // XXX
 #include "version.h"
 #include "config.h"
 #include "utils.h"
@@ -56,6 +55,7 @@
 // commandline macros
 
 struct commandline_macro {
+	unsigned column;
 	const char *macro;
 	const char *expansion;
 };
@@ -78,18 +78,20 @@
 
 static
 void
-commandline_macro_add(const char *macro, const char *expansion)
+commandline_macro_add(unsigned column,
+		      const char *macro, const char *expansion)
 {
 	struct commandline_macro *cm;
 
 	cm = domalloc(sizeof(*cm));
+	cm->column = column;
 	cm->macro = macro;
 	cm->expansion = expansion;
 }
 
 static
 void
-commandline_def(char *str)
+commandline_def(unsigned column, char *str)
 {
 	char *val;
 
@@ -98,14 +100,14 @@
 		*val = '\0';
 		val++;
 	}
-	commandline_macro_add(str, val ? val : "1");
+	commandline_macro_add(column, str, val ? val : "1");
 }
 
 static
 void
-commandline_undef(char *str)
+commandline_undef(unsigned column, char *str)
 {
-	commandline_macro_add(str, NULL);
+	commandline_macro_add(column, str, NULL);
 }
 
 static
@@ -113,19 +115,23 @@
 apply_commandline_macros(void)
 {
 	struct commandline_macro *cm;
+	struct place *p;
 	unsigned i, num;
 
+	p = place_gettemporary();
 	num = array_num(&commandline_macros);
 	for (i=0; i<num; i++) {
 		cm = array_get(&commandline_macros, i);
 		if (cm->expansion != NULL) {
-			macro_define(NULL, cm->macro, cm->expansion);
+			place_setcommandline(p, cm->column);
+			macro_define(p, cm->macro, cm->expansion);
 		} else {
 			macro_undef(cm->macro);
 		}
 		free(cm);
 	}
 	array_setsize(&commandline_macros, 0);
+	place_puttemporary(p);
 }
 
 static
@@ -174,6 +180,7 @@
 struct commandline_file {
 	char *name;
 	bool suppress_output;
+	unsigned column;
 };
 
 static struct array commandline_files;
@@ -194,28 +201,29 @@
 
 static
 void
-commandline_addfile(char *name, bool suppress_output)
+commandline_addfile(char *name, bool suppress_output, unsigned column)
 {
 	struct commandline_file *cf;
 
 	cf = domalloc(sizeof(*cf));
 	cf->name = name;
 	cf->suppress_output = suppress_output;
+	cf->column = column;
 	array_add(&commandline_files, cf, NULL);
 }
 
 static
 void
-commandline_addfile_output(char *name)
+commandline_addfile_output(unsigned column, char *name)
 {
-	commandline_addfile(name, false);
+	commandline_addfile(name, false, column);
 }
 
 static
 void
-commandline_addfile_nooutput(char *name)
+commandline_addfile_nooutput(unsigned column, char *name)
 {
-	commandline_addfile(name, true);
+	commandline_addfile(name, true, column);
 }
 
 static
@@ -225,20 +233,24 @@
 	struct commandline_file *cf;
 	unsigned i, num;
 	bool save = false;
+	struct place *p;
 
+	p = place_gettemporary();
 	num = array_num(&commandline_files);
 	for (i=0; i<num; i++) {
 		cf = array_get(&commandline_files, i);
+		place_setcommandline(p, cf->column);
 		if (cf->suppress_output) {
 			save = mode.do_output;
 			mode.do_output = false;
-			files_read(NULL, cf->name);
+			file_readquote(p, cf->name);
 			mode.do_output = save;
 		} else {
-			files_read(NULL, cf->name);
+			file_readquote(p, cf->name);
 		}
 		free(cf);
 	}
+	place_puttemporary(p);
 	array_setsize(&commandline_files, 0);
 }
 
@@ -273,8 +285,9 @@
 
 static
 void
-commandline_isysroot(char *dir)
+commandline_isysroot(unsigned column, char *dir)
 {
+	(void)column;
 	sysroot = dir;
 }
 
@@ -287,29 +300,33 @@
 
 static
 void
-commandline_addincpath_quote(char *dir)
+commandline_addincpath_quote(unsigned column, char *dir)
 {
+	(void)column;
 	commandline_addincpath(&incpath_quote, dir);
 }
 
 static
 void
-commandline_addincpath_user(char *dir)
+commandline_addincpath_user(unsigned column, char *dir)
 {
+	(void)column;
 	commandline_addincpath(&incpath_user, dir);
 }
 
 static
 void
-commandline_addincpath_system(char *dir)
+commandline_addincpath_system(unsigned column, char *dir)
 {
+	(void)column;
 	commandline_addincpath(&incpath_system, dir);
 }
 
 static
 void
-commandline_addincpath_late(char *dir)
+commandline_addincpath_late(unsigned column, char *dir)
 {
+	(void)column;
 	commandline_addincpath(&incpath_late, dir);
 }
 
@@ -379,14 +396,15 @@
 
 static
 void
-commandline_setprefix(char *prefix)
+commandline_setprefix(unsigned column, char *prefix)
 {
+	(void)column;
 	commandline_prefix = prefix;
 }
 
 static
 void
-commandline_addincpath_user_withprefix(char *dir)
+commandline_addincpath_user_withprefix(unsigned column, char *dir)
 {
 	char *s;
 
@@ -396,12 +414,12 @@
 	}
 	s = dostrdup3(commandline_prefix, "/", dir);
 	freestringlater(s);
-	commandline_addincpath_user(s);
+	commandline_addincpath_user(column, s);
 }
 
 static
 void
-commandline_addincpath_late_withprefix(char *dir)
+commandline_addincpath_late_withprefix(unsigned column, char *dir)
 {
 	char *s;
 
@@ -411,13 +429,15 @@
 	}
 	s = dostrdup3(commandline_prefix, "/", dir);
 	freestringlater(s);
-	commandline_addincpath_late(s);
+	commandline_addincpath_late(column, s);
 }
 
 static
 void
-commandline_setstd(char *std)
+commandline_setstd(unsigned column, char *std)
 {
+	(void)column;
+
 	if (!strcmp(std, "krc")) {
 		return;
 	}
@@ -427,8 +447,10 @@
 
 static
 void
-commandline_setlang(char *lang)
+commandline_setlang(unsigned column, char *lang)
 {
+	(void)column;
+
 	if (!strcmp(lang, "c") || !strcmp(lang, "assembler-with-cpp")) {
 		return;
 	}
@@ -441,20 +463,24 @@
 
 static
 void
-commandline_iremap(char *str)
+commandline_iremap(unsigned column, char *str)
 {
+	(void)column;
 	/* XXX */
+	(void)str;
 	warnx("-iremap not supported");
 	die();
 }
 
 static
 void
-commandline_tabstop(char *s)
+commandline_tabstop(unsigned column, char *s)
 {
 	char *t;
 	unsigned long val;
 
+	(void)column;
+
 	t = strchr(s, '=');
 	if (t == NULL) {
 		/* should not happen */
@@ -535,24 +561,27 @@
 
 static
 void
-commandline_setdependtarget(char *str)
+commandline_setdependtarget(unsigned column, char *str)
 {
+	(void)column;
 	mode.depend_target = str;
 	mode.depend_quote_target = false;
 }
 
 static
 void
-commandline_setdependtarget_quoted(char *str)
+commandline_setdependtarget_quoted(unsigned column, char *str)
 {
+	(void)column;
 	mode.depend_target = str;
 	mode.depend_quote_target = true;
 }
 
 static
 void
-commandline_setdependoutput(char *str)
+commandline_setdependoutput(unsigned column, char *str)
 {
+	(void)column;
 	mode.depend_file = str;
 }
 
@@ -634,12 +663,12 @@
 
 struct prefix_option {
 	const char *string;
-	void (*func)(char *);
+	void (*func)(unsigned column, char *);
 };
 
 struct arg_option {
 	const char *string;
-	void (*func)(char *);
+	void (*func)(unsigned column, char *);
 };
 
 static const struct flag_option flag_options[] = {
@@ -750,7 +779,7 @@
 
 static
 bool
-check_prefix_option(char *opt)
+check_prefix_option(unsigned column, char *opt)
 {
 	unsigned i;
 	int r;
@@ -759,7 +788,7 @@
 		r = strncmp(opt, prefix_options[i].string,
 			    strlen(prefix_options[i].string));
 		if (r == 0) {
-			prefix_options[i].func(opt);
+			prefix_options[i].func(column, opt);
 			return true;
 		}
 		if (r < 0) {
@@ -771,7 +800,7 @@
 
 static
 bool
-check_arg_option(const char *opt, char *arg)
+check_arg_option(const char *opt, unsigned argcolumn, char *arg)
 {
 	unsigned i;
 	int r;
@@ -783,7 +812,7 @@
 				warnx("Option -%s requires an argument", opt);
 				die();
 			}
-			arg_options[i].func(arg);
+			arg_options[i].func(argcolumn, arg);
 			return true;
 		}
 		if (r < 0) {
@@ -826,9 +855,12 @@
 init(void)
 {
 	stringarray_init(&freestrings);
+
 	incpath_init();
 	commandline_macros_init();
 	commandline_files_init();
+
+	files_init();
 }
 
 static
@@ -837,6 +869,8 @@
 {
 	unsigned i, num;
 
+	files_cleanup();
+
 	commandline_files_cleanup();
 	commandline_macros_cleanup();
 	incpath_cleanup();
@@ -870,25 +904,31 @@
 {
 	const char *inputfile = NULL;
 	const char *outputfile = NULL;
+	unsigned column, nextcolumn;
+	struct place *p;
 	int i;
 
 	init();
 
-	for (i=1; i<argc; i++) {
+	column = 1;
+	for (i=1; i<argc; i++, column = nextcolumn) {
 		if (argv[i][0] != '-') {
 			break;
 		}
+		nextcolumn = column + strlen(argv[i]) + 1;
 		if (check_flag_option(argv[i]+1)) {
 			continue;
 		}
 		if (check_act_option(argv[i]+1)) {
 			continue;
 		}
-		if (check_prefix_option(argv[i]+1)) {
+		if (check_prefix_option(column, argv[i]+1)) {
 			continue;
 		}
-		if (check_arg_option(argv[i]+1, argv[i+1])) {
+		if (check_arg_option(argv[i]+1, nextcolumn, argv[i+1])) {
+			column = nextcolumn;
 			i++;
+			nextcolumn = strlen(argv[i]) + 1;
 			continue;
 		}
 		usage();
@@ -909,8 +949,14 @@
 	apply_builtin_macros();
 	apply_commandline_macros();
 	read_commandline_files();
-	files_read(NULL, inputfile);
+	p = place_gettemporary();
+	place_setnowhere(p);
+	file_readabsolute(p, inputfile);
+	place_puttemporary(p);
 
 	cleanup();
+	if (complain_failed()) {
+		return EXIT_FAILURE;
+	}
 	return EXIT_SUCCESS;
 }
--- a/utils.h	Sun Dec 19 17:53:49 2010 -0500
+++ b/utils.h	Sun Dec 19 18:55:51 2010 -0500
@@ -1,3 +1,9 @@
+#include <stdbool.h>
+#include <stddef.h>
+
+struct place;
+
+
 #define HOWMANY(arr) (sizeof(arr)/sizeof((arr)[0]))
 
 void *domalloc(size_t len);
@@ -7,5 +13,11 @@
 char *dostrdup2(const char *s, const char *t);
 char *dostrdup3(const char *s, const char *t, const char *u);
 
+/* in files.c */
+void complain(const struct place *, const char *fmt, ...);
+void complain_fail(void);
+bool complain_failed(void);
+
+/* in main.c */
 void freestringlater(char *s);
 void die(void);