1 /* $NetBSD: util.c,v 1.4 2006/09/03 07:45:40 dsl 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 <sys/types.h> 48 #include <ctype.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <stdarg.h> 53 #include <util.h> 54 #include "defs.h" 55 56 static void nomem(void); 57 static void vxerror(const char *, int, const char *, va_list) 58 __attribute__((__format__(__printf__, 3, 0))); 59 static void vxwarn(const char *, int, const char *, va_list) 60 __attribute__((__format__(__printf__, 3, 0))); 61 static void vxmsg(const char *fname, int line, const char *class, 62 const char *fmt, va_list) 63 __attribute__((__format__(__printf__, 4, 0))); 64 65 /* 66 * Calloc, with abort on error. 67 */ 68 void * 69 ecalloc(size_t nelem, size_t size) 70 { 71 void *p; 72 73 if ((p = calloc(nelem, size)) == NULL) 74 nomem(); 75 return (p); 76 } 77 78 /* 79 * Malloc, with abort on error. 80 */ 81 void * 82 emalloc(size_t size) 83 { 84 void *p; 85 86 if ((p = malloc(size)) == NULL) 87 nomem(); 88 return (p); 89 } 90 91 /* 92 * Realloc, with abort on error. 93 */ 94 void * 95 erealloc(void *p, size_t size) 96 { 97 void *q; 98 99 if ((q = realloc(p, size)) == NULL) 100 nomem(); 101 p = q; 102 return (p); 103 } 104 105 /* 106 * Strdup, with abort on error. 107 */ 108 char * 109 estrdup(const char *p) 110 { 111 char *cp; 112 113 if ((cp = strdup(p)) == NULL) 114 nomem(); 115 return (cp); 116 } 117 118 static void 119 nomem(void) 120 { 121 122 (void)fprintf(stderr, "config: out of memory\n"); 123 exit(1); 124 } 125 126 /* 127 * Push a prefix onto the prefix stack. 128 */ 129 void 130 prefix_push(const char *path) 131 { 132 struct prefix *pf; 133 char *cp; 134 135 pf = ecalloc(1, sizeof(struct prefix)); 136 137 if (! SLIST_EMPTY(&prefixes) && *path != '/') { 138 cp = emalloc(strlen(SLIST_FIRST(&prefixes)->pf_prefix) + 1 + 139 strlen(path) + 1); 140 (void) sprintf(cp, "%s/%s", 141 SLIST_FIRST(&prefixes)->pf_prefix, path); 142 pf->pf_prefix = intern(cp); 143 free(cp); 144 } else 145 pf->pf_prefix = intern(path); 146 147 SLIST_INSERT_HEAD(&prefixes, pf, pf_next); 148 } 149 150 /* 151 * Pop a prefix off the prefix stack. 152 */ 153 void 154 prefix_pop(void) 155 { 156 struct prefix *pf; 157 158 if ((pf = SLIST_FIRST(&prefixes)) == NULL) { 159 error("no prefixes on the stack to pop"); 160 return; 161 } 162 163 SLIST_REMOVE_HEAD(&prefixes, pf_next); 164 /* Remember this prefix for emitting -I... directives later. */ 165 SLIST_INSERT_HEAD(&allprefixes, pf, pf_next); 166 } 167 168 /* 169 * Prepend the source path to a file name. 170 */ 171 char * 172 sourcepath(const char *file) 173 { 174 size_t len; 175 char *cp; 176 struct prefix *pf; 177 178 pf = SLIST_EMPTY(&prefixes) ? NULL : SLIST_FIRST(&prefixes); 179 if (pf != NULL && *pf->pf_prefix == '/') 180 len = strlen(pf->pf_prefix) + 1 + strlen(file) + 1; 181 else { 182 len = strlen(srcdir) + 1 + strlen(file) + 1; 183 if (pf != NULL) 184 len += strlen(pf->pf_prefix) + 1; 185 } 186 187 cp = emalloc(len); 188 189 if (pf != NULL) { 190 if (*pf->pf_prefix == '/') 191 (void) sprintf(cp, "%s/%s", pf->pf_prefix, file); 192 else 193 (void) sprintf(cp, "%s/%s/%s", srcdir, 194 pf->pf_prefix, file); 195 } else 196 (void) sprintf(cp, "%s/%s", srcdir, file); 197 return (cp); 198 } 199 200 struct nvlist * 201 newnv(const char *name, const char *str, void *ptr, int i, struct nvlist *next) 202 { 203 struct nvlist *nv; 204 205 nv = ecalloc(1, sizeof(*nv)); 206 nv->nv_next = next; 207 nv->nv_name = name; 208 nv->nv_str = str; 209 nv->nv_ptr = ptr; 210 nv->nv_int = i; 211 return nv; 212 } 213 214 /* 215 * Free an nvlist structure (just one). 216 */ 217 void 218 nvfree(struct nvlist *nv) 219 { 220 221 free(nv); 222 } 223 224 /* 225 * Free an nvlist (the whole list). 226 */ 227 void 228 nvfreel(struct nvlist *nv) 229 { 230 struct nvlist *next; 231 232 for (; nv != NULL; nv = next) { 233 next = nv->nv_next; 234 free(nv); 235 } 236 } 237 238 void 239 warn(const char *fmt, ...) 240 { 241 va_list ap; 242 extern const char *yyfile; 243 244 va_start(ap, fmt); 245 vxwarn(yyfile, currentline(), fmt, ap); 246 va_end(ap); 247 } 248 249 void 250 xwarn(const char *file, int line, const char *fmt, ...) 251 { 252 va_list ap; 253 254 va_start(ap, fmt); 255 vxwarn(file, line, fmt, ap); 256 va_end(ap); 257 } 258 259 static void 260 vxwarn(const char *file, int line, const char *fmt, va_list ap) 261 { 262 vxmsg(file, line, "warning: ", fmt, ap); 263 } 264 265 /* 266 * External (config file) error. Complain, using current file 267 * and line number. 268 */ 269 void 270 error(const char *fmt, ...) 271 { 272 va_list ap; 273 extern const char *yyfile; 274 275 va_start(ap, fmt); 276 vxerror(yyfile, currentline(), fmt, ap); 277 va_end(ap); 278 } 279 280 /* 281 * Delayed config file error (i.e., something was wrong but we could not 282 * find out about it until later). 283 */ 284 void 285 xerror(const char *file, int line, const char *fmt, ...) 286 { 287 va_list ap; 288 289 va_start(ap, fmt); 290 vxerror(file, line, fmt, ap); 291 va_end(ap); 292 } 293 294 /* 295 * Internal form of error() and xerror(). 296 */ 297 static void 298 vxerror(const char *file, int line, const char *fmt, va_list ap) 299 { 300 vxmsg(file, line, "", fmt, ap); 301 errors++; 302 } 303 304 305 /* 306 * Internal error, abort. 307 */ 308 __dead void 309 panic(const char *fmt, ...) 310 { 311 va_list ap; 312 313 va_start(ap, fmt); 314 (void)fprintf(stderr, "config: panic: "); 315 (void)vfprintf(stderr, fmt, ap); 316 (void)putc('\n', stderr); 317 va_end(ap); 318 exit(2); 319 } 320 321 /* 322 * Internal form of error() and xerror(). 323 */ 324 static void 325 vxmsg(const char *file, int line, const char *msgclass, const char *fmt, 326 va_list ap) 327 { 328 329 (void)fprintf(stderr, "%s:%d: %s", file, line, msgclass); 330 (void)vfprintf(stderr, fmt, ap); 331 (void)putc('\n', stderr); 332 } 333