Mercurial > ~dholland > hg > tradcpp > index.cgi
view files.c @ 7:b8167949474a
make places work better
author | David A. Holland |
---|---|
date | Sun, 19 Dec 2010 19:08:24 -0500 |
parents | 0601b6e8e53d |
children | 97243badae69 |
line wrap: on
line source
#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("epath); incdirarray_init(&bracketpath); } DESTROYALL(incdir); DESTROYALL(seenfile); void files_cleanup(void) { seenfilearray_destroyall(&seenfiles); seenfilearray_cleanup(&seenfiles); incdirarray_destroyall("epath); incdirarray_cleanup("epath); 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("epath, 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; } struct place * place_create(void) { struct place *p; p = domalloc(sizeof(*p)); place_setnowhere(p); return p; } struct place * place_clone(const struct place *op) { struct place *p; p = domalloc(sizeof(*p)); *p = *op; return p; } void place_destroy(struct place *p) { free(p); } 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, "epath, 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); }