/*- * Copyright (c) 2010 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by David A. Holland. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "utils.h" #include "array.h" #include "place.h" struct placefile { struct place includedfrom; char *dir; char *name; int depth; bool fromsystemdir; }; DECLARRAY(placefile, static UNUSED); DEFARRAY(placefile, static); static struct placefilearray placefiles; static bool overall_failure; static const char *myprogname; static FILE *debuglogfile; //////////////////////////////////////////////////////////// // placefiles static struct placefile * placefile_create(const struct place *from, const char *name, bool fromsystemdir) { struct placefile *pf; const char *s; size_t len; pf = domalloc(sizeof(*pf)); pf->includedfrom = *from; s = strrchr(name, '/'); len = (s == NULL) ? 0 : s - name; pf->dir = dostrndup(name, len); pf->name = dostrdup(name); pf->fromsystemdir = fromsystemdir; if (from->file != NULL) { pf->depth = from->file->depth + 1; } else { pf->depth = 1; } return pf; } static void placefile_destroy(struct placefile *pf) { dostrfree(pf->name); dofree(pf, sizeof(*pf)); } DESTROYALL_ARRAY(placefile, ); const char * place_getparsedir(const struct place *place) { if (place->file == NULL) { return "."; } return place->file->dir; } static struct placefile * placefile_find(const struct place *incfrom, const char *name) { unsigned i, num; struct placefile *pf; num = placefilearray_num(&placefiles); for (i=0; iincludedfrom) && !strcmp(name, pf->name)) { return pf; } } return NULL; } void place_changefile(struct place *p, const char *name) { struct placefile *pf; assert(p->type == P_FILE); if (!strcmp(name, p->file->name)) { return; } pf = placefile_find(&p->file->includedfrom, name); if (pf == NULL) { pf = placefile_create(&p->file->includedfrom, name, p->file->fromsystemdir); placefilearray_add(&placefiles, pf, NULL); } p->file = pf; } const struct placefile * place_addfile(const struct place *place, const char *file, bool issystem) { struct placefile *pf; pf = placefile_create(place, file, issystem); placefilearray_add(&placefiles, pf, NULL); if (pf->depth > 120) { complain(place, "Maximum include nesting depth exceeded"); die(); } return pf; } //////////////////////////////////////////////////////////// // places void place_setnowhere(struct place *p) { p->type = P_NOWHERE; p->file = NULL; p->line = 0; p->column = 0; } void place_setbuiltin(struct place *p, unsigned num) { p->type = P_BUILTIN; p->file = NULL; p->line = num; p->column = 1; } void place_setcommandline(struct place *p, unsigned line, unsigned column) { p->type = P_COMMANDLINE; p->file = NULL; p->line = line; p->column = column; } void place_setfilestart(struct place *p, const struct placefile *pf) { p->type = P_FILE; p->file = pf; p->line = 1; p->column = 1; } void place_addcolumns(struct place *p, unsigned cols) { unsigned newcol; newcol = p->column + cols; if (newcol < p->column) { /* overflow (use the old place to complain) */ complain(p, "Column numbering overflow"); die(); } p->column = newcol; } void place_addlines(struct place *p, unsigned lines) { unsigned nextline; nextline = p->line + lines; if (nextline < p->line) { /* overflow (use the old place to complain) */ complain(p, "Line numbering overflow"); die(); } p->line = nextline; } const char * place_getname(const struct place *p) { switch (p->type) { case P_NOWHERE: return ""; case P_BUILTIN: return ""; case P_COMMANDLINE: return ""; case P_FILE: return p->file->name; } assert(0); return NULL; } bool place_samefile(const struct place *a, const struct place *b) { if (a->type != b->type) { return false; } if (a->file != b->file) { return false; } return true; } bool place_eq(const struct place *a, const struct place *b) { if (!place_samefile(a, b)) { return false; } if (a->line != b->line || a->column != b->column) { return false; } return true; } static void place_printfrom(const struct place *p) { const struct place *from; if (p->file == NULL) { return; } from = &p->file->includedfrom; if (from->type != P_NOWHERE) { place_printfrom(from); fprintf(stderr, "In file included from %s:%u:%u:\n", place_getname(from), from->line, from->column); } } //////////////////////////////////////////////////////////// // complaints void complain_init(const char *pn) { myprogname = pn; } void complain(const struct place *p, const char *fmt, ...) { va_list ap; if (p != NULL) { place_printfrom(p); fprintf(stderr, "%s:%u:%u: ", place_getname(p), p->line, p->column); } else { fprintf(stderr, "%s: ", myprogname); } 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; } //////////////////////////////////////////////////////////// // debug logging void debuglog_open(const struct place *p, /*const*/ char *file) { assert(debuglogfile == NULL); debuglogfile = fopen(file, "w"); if (debuglogfile == NULL) { complain(p, "%s: %s", file, strerror(errno)); die(); } } void debuglog_close(void) { if (debuglogfile != NULL) { fclose(debuglogfile); debuglogfile = NULL; } } PF(2, 3) void debuglog(const struct place *p, const char *fmt, ...) { va_list ap; if (debuglogfile == NULL) { return; } fprintf(debuglogfile, "%s:%u: ", place_getname(p), p->line); va_start(ap, fmt); vfprintf(debuglogfile, fmt, ap); va_end(ap); fprintf(debuglogfile, "\n"); fflush(debuglogfile); } PF(3, 4) void debuglog2(const struct place *p, const struct place *p2, const char *fmt, ...) { va_list ap; if (debuglogfile == NULL) { return; } fprintf(debuglogfile, "%s:%u: ", place_getname(p), p->line); if (place_samefile(p, p2)) { fprintf(debuglogfile, "(block began at line %u) ", p2->line); } else { fprintf(debuglogfile, "(block began at %s:%u)", place_getname(p2), p2->line); } va_start(ap, fmt); vfprintf(debuglogfile, fmt, ap); va_end(ap); fprintf(debuglogfile, "\n"); fflush(debuglogfile); } //////////////////////////////////////////////////////////// // module init and cleanup void place_init(void) { placefilearray_init(&placefiles); } void place_cleanup(void) { placefilearray_destroyall(&placefiles); placefilearray_cleanup(&placefiles); }