1 /*- 2 * Copyright (c) 2010 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by David A. Holland. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <assert.h> 31 #include <stdarg.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 36 #include "utils.h" 37 #include "array.h" 38 #include "place.h" 39 40 struct placefile { 41 struct place includedfrom; 42 char *dir; 43 char *name; 44 int depth; 45 bool fromsystemdir; 46 }; 47 DECLARRAY(placefile, static UNUSED); 48 DEFARRAY(placefile, static); 49 50 static struct placefilearray placefiles; 51 static bool overall_failure; 52 53 static const char *myprogname; 54 55 //////////////////////////////////////////////////////////// 56 // seenfiles 57 58 static 59 struct placefile * 60 placefile_create(const struct place *from, const char *name, 61 bool fromsystemdir) 62 { 63 struct placefile *pf; 64 const char *s; 65 size_t len; 66 67 pf = domalloc(sizeof(*pf)); 68 pf->includedfrom = *from; 69 70 s = strrchr(name, '/'); 71 len = (s == NULL) ? 0 : s - name; 72 pf->dir = dostrndup(name, len); 73 74 pf->name = dostrdup(name); 75 pf->fromsystemdir = fromsystemdir; 76 77 if (from->file != NULL) { 78 pf->depth = from->file->depth + 1; 79 } else { 80 pf->depth = 1; 81 } 82 return pf; 83 } 84 85 static 86 void 87 placefile_destroy(struct placefile *pf) 88 { 89 dostrfree(pf->name); 90 dofree(pf, sizeof(*pf)); 91 } 92 93 DESTROYALL_ARRAY(placefile, ); 94 95 const char * 96 place_getparsedir(const struct place *place) 97 { 98 if (place->file == NULL) { 99 return "."; 100 } 101 return place->file->dir; 102 } 103 104 const struct placefile * 105 place_addfile(const struct place *place, const char *file, bool issystem) 106 { 107 struct placefile *pf; 108 109 pf = placefile_create(place, file, issystem); 110 placefilearray_add(&placefiles, pf, NULL); 111 if (pf->depth > 120) { 112 complain(place, "Maximum include nesting depth exceeded"); 113 die(); 114 } 115 return pf; 116 } 117 118 //////////////////////////////////////////////////////////// 119 // places 120 121 void 122 place_setnowhere(struct place *p) 123 { 124 p->type = P_NOWHERE; 125 p->file = NULL; 126 p->line = 0; 127 p->column = 0; 128 } 129 130 void 131 place_setbuiltin(struct place *p, unsigned num) 132 { 133 p->type = P_BUILTIN; 134 p->file = NULL; 135 p->line = num; 136 p->column = 1; 137 } 138 139 void 140 place_setcommandline(struct place *p, unsigned line, unsigned column) 141 { 142 p->type = P_COMMANDLINE; 143 p->file = NULL; 144 p->line = line; 145 p->column = column; 146 } 147 148 void 149 place_setfilestart(struct place *p, const struct placefile *pf) 150 { 151 p->type = P_FILE; 152 p->file = pf; 153 p->line = 1; 154 p->column = 1; 155 } 156 157 static 158 const char * 159 place_getname(const struct place *p) 160 { 161 switch (p->type) { 162 case P_NOWHERE: return "<nowhere>"; 163 case P_BUILTIN: return "<built-in>"; 164 case P_COMMANDLINE: return "<command-line>"; 165 case P_FILE: return p->file->name; 166 } 167 assert(0); 168 return NULL; 169 } 170 171 static 172 void 173 place_printfrom(const struct place *p) 174 { 175 const struct place *from; 176 177 if (p->file == NULL) { 178 return; 179 } 180 from = &p->file->includedfrom; 181 if (from->type != P_NOWHERE) { 182 place_printfrom(from); 183 fprintf(stderr, "In file included from %s:%u:%u:\n", 184 place_getname(from), from->line, from->column); 185 } 186 } 187 188 //////////////////////////////////////////////////////////// 189 // complaints 190 191 void 192 complain_init(const char *pn) 193 { 194 myprogname = pn; 195 } 196 197 void 198 complain(const struct place *p, const char *fmt, ...) 199 { 200 va_list ap; 201 202 if (p != NULL) { 203 place_printfrom(p); 204 fprintf(stderr, "%s:%u:%u: ", place_getname(p), 205 p->line, p->column); 206 } else { 207 fprintf(stderr, "%s: ", myprogname); 208 } 209 va_start(ap, fmt); 210 vfprintf(stderr, fmt, ap); 211 va_end(ap); 212 fprintf(stderr, "\n"); 213 } 214 215 void 216 complain_fail(void) 217 { 218 overall_failure = true; 219 } 220 221 bool 222 complain_failed(void) 223 { 224 return overall_failure; 225 } 226 227 //////////////////////////////////////////////////////////// 228 // module init and cleanup 229 230 void 231 place_init(void) 232 { 233 placefilearray_init(&placefiles); 234 } 235 236 void 237 place_cleanup(void) 238 { 239 placefilearray_destroyall(&placefiles); 240 placefilearray_cleanup(&placefiles); 241 } 242