1 /* $NetBSD: util.c,v 1.1 2005/06/05 18:19:53 thorpej 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 263 static void 264 vxwarn(const char *file, int line, const char *fmt, va_list ap) 265 { 266 vxmsg(file, line, "warning: ", fmt, ap); 267 } 268 269 /* 270 * External (config file) error. Complain, using current file 271 * and line number. 272 */ 273 void 274 error(const char *fmt, ...) 275 { 276 va_list ap; 277 extern const char *yyfile; 278 279 va_start(ap, fmt); 280 vxerror(yyfile, currentline(), fmt, ap); 281 va_end(ap); 282 } 283 284 /* 285 * Delayed config file error (i.e., something was wrong but we could not 286 * find out about it until later). 287 */ 288 void 289 xerror(const char *file, int line, const char *fmt, ...) 290 { 291 va_list ap; 292 293 va_start(ap, fmt); 294 vxerror(file, line, fmt, ap); 295 va_end(ap); 296 } 297 298 /* 299 * Internal form of error() and xerror(). 300 */ 301 static void 302 vxerror(const char *file, int line, const char *fmt, va_list ap) 303 { 304 vxmsg(file, line, "", fmt, ap); 305 errors++; 306 } 307 308 309 /* 310 * Internal error, abort. 311 */ 312 __dead void 313 panic(const char *fmt, ...) 314 { 315 va_list ap; 316 317 va_start(ap, fmt); 318 (void)fprintf(stderr, "config: panic: "); 319 (void)vfprintf(stderr, fmt, ap); 320 (void)putc('\n', stderr); 321 va_end(ap); 322 exit(2); 323 } 324 325 /* 326 * Internal form of error() and xerror(). 327 */ 328 static void 329 vxmsg(const char *file, int line, const char *msgclass, const char *fmt, 330 va_list ap) 331 { 332 333 (void)fprintf(stderr, "%s:%d: %s", file, line, msgclass); 334 (void)vfprintf(stderr, fmt, ap); 335 (void)putc('\n', stderr); 336 } 337