1 /* $NetBSD: util.c,v 1.2 2005/10/04 12:35:00 cube Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratories. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: @(#)util.c 8.1 (Berkeley) 6/6/93 41 */ 42 43 #if HAVE_NBTOOL_CONFIG_H 44 #include "nbtool_config.h" 45 #endif 46 47 #include <ctype.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <stdarg.h> 52 #include <sys/types.h> 53 #include "defs.h" 54 55 static void nomem(void); 56 static void vxerror(const char *, int, const char *, va_list) 57 __attribute__((__format__(__printf__, 3, 0))); 58 static void vxwarn(const char *, int, const char *, va_list) 59 __attribute__((__format__(__printf__, 3, 0))); 60 static void vxmsg(const char *fname, int line, const char *class, 61 const char *fmt, va_list) 62 __attribute__((__format__(__printf__, 4, 0))); 63 64 /* 65 * Calloc, with abort on error. 66 */ 67 void * 68 ecalloc(size_t nelem, size_t size) 69 { 70 void *p; 71 72 if ((p = calloc(nelem, size)) == NULL) 73 nomem(); 74 return (p); 75 } 76 77 /* 78 * Malloc, with abort on error. 79 */ 80 void * 81 emalloc(size_t size) 82 { 83 void *p; 84 85 if ((p = malloc(size)) == NULL) 86 nomem(); 87 return (p); 88 } 89 90 /* 91 * Realloc, with abort on error. 92 */ 93 void * 94 erealloc(void *p, size_t size) 95 { 96 void *q; 97 98 if ((q = realloc(p, size)) == NULL) 99 nomem(); 100 p = q; 101 return (p); 102 } 103 104 /* 105 * Strdup, with abort on error. 106 */ 107 char * 108 estrdup(const char *p) 109 { 110 char *cp; 111 112 if ((cp = strdup(p)) == NULL) 113 nomem(); 114 return (cp); 115 } 116 117 static void 118 nomem(void) 119 { 120 121 (void)fprintf(stderr, "config: out of memory\n"); 122 exit(1); 123 } 124 125 /* 126 * Push a prefix onto the prefix stack. 127 */ 128 void 129 prefix_push(const char *path) 130 { 131 struct prefix *pf; 132 char *cp; 133 134 pf = ecalloc(1, sizeof(struct prefix)); 135 136 if (! SLIST_EMPTY(&prefixes) && *path != '/') { 137 cp = emalloc(strlen(SLIST_FIRST(&prefixes)->pf_prefix) + 1 + 138 strlen(path) + 1); 139 (void) sprintf(cp, "%s/%s", 140 SLIST_FIRST(&prefixes)->pf_prefix, path); 141 pf->pf_prefix = intern(cp); 142 free(cp); 143 } else 144 pf->pf_prefix = intern(path); 145 146 SLIST_INSERT_HEAD(&prefixes, pf, pf_next); 147 } 148 149 /* 150 * Pop a prefix off the prefix stack. 151 */ 152 void 153 prefix_pop(void) 154 { 155 struct prefix *pf; 156 157 if ((pf = SLIST_FIRST(&prefixes)) == NULL) { 158 error("no prefixes on the stack to pop"); 159 return; 160 } 161 162 SLIST_REMOVE_HEAD(&prefixes, pf_next); 163 /* Remember this prefix for emitting -I... directives later. */ 164 SLIST_INSERT_HEAD(&allprefixes, pf, pf_next); 165 } 166 167 /* 168 * Prepend the source path to a file name. 169 */ 170 char * 171 sourcepath(const char *file) 172 { 173 size_t len; 174 char *cp; 175 struct prefix *pf; 176 177 pf = SLIST_EMPTY(&prefixes) ? NULL : SLIST_FIRST(&prefixes); 178 if (pf != NULL && *pf->pf_prefix == '/') 179 len = strlen(pf->pf_prefix) + 1 + strlen(file) + 1; 180 else { 181 len = strlen(srcdir) + 1 + strlen(file) + 1; 182 if (pf != NULL) 183 len += strlen(pf->pf_prefix) + 1; 184 } 185 186 cp = emalloc(len); 187 188 if (pf != NULL) { 189 if (*pf->pf_prefix == '/') 190 (void) sprintf(cp, "%s/%s", pf->pf_prefix, file); 191 else 192 (void) sprintf(cp, "%s/%s/%s", srcdir, 193 pf->pf_prefix, file); 194 } else 195 (void) sprintf(cp, "%s/%s", srcdir, file); 196 return (cp); 197 } 198 199 static struct nvlist *nvfreelist; 200 201 struct nvlist * 202 newnv(const char *name, const char *str, void *ptr, int i, struct nvlist *next) 203 { 204 struct nvlist *nv; 205 206 if ((nv = nvfreelist) == NULL) 207 nv = ecalloc(1, sizeof(*nv)); 208 else 209 nvfreelist = nv->nv_next; 210 nv->nv_next = next; 211 nv->nv_name = name; 212 if (ptr == NULL) 213 nv->nv_str = str; 214 else { 215 if (str != NULL) 216 panic("newnv"); 217 nv->nv_ptr = ptr; 218 } 219 nv->nv_int = i; 220 return (nv); 221 } 222 223 /* 224 * Free an nvlist structure (just one). 225 */ 226 void 227 nvfree(struct nvlist *nv) 228 { 229 230 memset(nv, 0, sizeof(*nv)); 231 nv->nv_next = nvfreelist; 232 nvfreelist = nv; 233 } 234 235 /* 236 * Free an nvlist (the whole list). 237 */ 238 void 239 nvfreel(struct nvlist *nv) 240 { 241 struct nvlist *next; 242 243 for (; nv != NULL; nv = next) { 244 next = nv->nv_next; 245 memset(nv, 0, sizeof(*nv)); 246 nv->nv_next = nvfreelist; 247 nvfreelist = nv; 248 } 249 } 250 251 void 252 warn(const char *fmt, ...) 253 { 254 va_list ap; 255 extern const char *yyfile; 256 257 va_start(ap, fmt); 258 vxwarn(yyfile, currentline(), fmt, ap); 259 va_end(ap); 260 } 261 262 void 263 xwarn(const char *file, int line, const char *fmt, ...) 264 { 265 va_list ap; 266 267 va_start(ap, fmt); 268 vxwarn(file, line, fmt, ap); 269 va_end(ap); 270 } 271 272 static void 273 vxwarn(const char *file, int line, const char *fmt, va_list ap) 274 { 275 vxmsg(file, line, "warning: ", fmt, ap); 276 } 277 278 /* 279 * External (config file) error. Complain, using current file 280 * and line number. 281 */ 282 void 283 error(const char *fmt, ...) 284 { 285 va_list ap; 286 extern const char *yyfile; 287 288 va_start(ap, fmt); 289 vxerror(yyfile, currentline(), fmt, ap); 290 va_end(ap); 291 } 292 293 /* 294 * Delayed config file error (i.e., something was wrong but we could not 295 * find out about it until later). 296 */ 297 void 298 xerror(const char *file, int line, const char *fmt, ...) 299 { 300 va_list ap; 301 302 va_start(ap, fmt); 303 vxerror(file, line, fmt, ap); 304 va_end(ap); 305 } 306 307 /* 308 * Internal form of error() and xerror(). 309 */ 310 static void 311 vxerror(const char *file, int line, const char *fmt, va_list ap) 312 { 313 vxmsg(file, line, "", fmt, ap); 314 errors++; 315 } 316 317 318 /* 319 * Internal error, abort. 320 */ 321 __dead void 322 panic(const char *fmt, ...) 323 { 324 va_list ap; 325 326 va_start(ap, fmt); 327 (void)fprintf(stderr, "config: panic: "); 328 (void)vfprintf(stderr, fmt, ap); 329 (void)putc('\n', stderr); 330 va_end(ap); 331 exit(2); 332 } 333 334 /* 335 * Internal form of error() and xerror(). 336 */ 337 static void 338 vxmsg(const char *file, int line, const char *msgclass, const char *fmt, 339 va_list ap) 340 { 341 342 (void)fprintf(stderr, "%s:%d: %s", file, line, msgclass); 343 (void)vfprintf(stderr, fmt, ap); 344 (void)putc('\n', stderr); 345 } 346