1/* $NetBSD: util.c,v 1.7 2007/12/12 00:03:34 lukem 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 <err.h> 55#include "defs.h" 56 57static void cfgvxerror(const char *, int, const char *, va_list) 58 __attribute__((__format__(__printf__, 3, 0))); 59static void cfgvxwarn(const char *, int, const char *, va_list) 60 __attribute__((__format__(__printf__, 3, 0))); 61static void cfgvxmsg(const char *, int, const char *, const char *, va_list) 62 __attribute__((__format__(__printf__, 4, 0))); 63 64/* 65 * Push a prefix onto the prefix stack. 66 */ 67void 68prefix_push(const char *path) 69{ 70 struct prefix *pf; 71 char *cp; 72 73 pf = ecalloc(1, sizeof(struct prefix)); 74 75 if (! SLIST_EMPTY(&prefixes) && *path != '/') { 76 cp = emalloc(strlen(SLIST_FIRST(&prefixes)->pf_prefix) + 1 + 77 strlen(path) + 1); 78 (void) sprintf(cp, "%s/%s", 79 SLIST_FIRST(&prefixes)->pf_prefix, path); 80 pf->pf_prefix = intern(cp); 81 free(cp); 82 } else 83 pf->pf_prefix = intern(path); 84 85 SLIST_INSERT_HEAD(&prefixes, pf, pf_next); 86} 87 88/* 89 * Pop a prefix off the prefix stack. 90 */ 91void 92prefix_pop(void) 93{ 94 struct prefix *pf; 95 96 if ((pf = SLIST_FIRST(&prefixes)) == NULL) { 97 cfgerror("no prefixes on the stack to pop"); 98 return; 99 } 100 101 SLIST_REMOVE_HEAD(&prefixes, pf_next); 102 /* Remember this prefix for emitting -I... directives later. */ 103 SLIST_INSERT_HEAD(&allprefixes, pf, pf_next); 104} 105 106/* 107 * Prepend the source path to a file name. 108 */ 109char * 110sourcepath(const char *file) 111{ 112 size_t len; 113 char *cp; 114 struct prefix *pf; 115 116 pf = SLIST_EMPTY(&prefixes) ? NULL : SLIST_FIRST(&prefixes); 117 if (pf != NULL && *pf->pf_prefix == '/') 118 len = strlen(pf->pf_prefix) + 1 + strlen(file) + 1; 119 else { 120 len = strlen(srcdir) + 1 + strlen(file) + 1; 121 if (pf != NULL) 122 len += strlen(pf->pf_prefix) + 1; 123 } 124 125 cp = emalloc(len); 126 127 if (pf != NULL) { 128 if (*pf->pf_prefix == '/') 129 (void) sprintf(cp, "%s/%s", pf->pf_prefix, file); 130 else 131 (void) sprintf(cp, "%s/%s/%s", srcdir, 132 pf->pf_prefix, file); 133 } else 134 (void) sprintf(cp, "%s/%s", srcdir, file); 135 return (cp); 136} 137 138struct nvlist * 139newnv(const char *name, const char *str, void *ptr, long long i, struct nvlist *next) 140{ 141 struct nvlist *nv; 142 143 nv = ecalloc(1, sizeof(*nv)); 144 nv->nv_next = next; 145 nv->nv_name = name; 146 nv->nv_str = str; 147 nv->nv_ptr = ptr; 148 nv->nv_num = i; 149 return nv; 150} 151 152/* 153 * Free an nvlist structure (just one). 154 */ 155void 156nvfree(struct nvlist *nv) 157{ 158 159 free(nv); 160} 161 162/* 163 * Free an nvlist (the whole list). 164 */ 165void 166nvfreel(struct nvlist *nv) 167{ 168 struct nvlist *next; 169 170 for (; nv != NULL; nv = next) { 171 next = nv->nv_next; 172 free(nv); 173 } 174} 175 176struct nvlist * 177nvcat(struct nvlist *nv1, struct nvlist *nv2) 178{ 179 struct nvlist *nv; 180 181 if (nv1 == NULL) 182 return nv2; 183 184 for (nv = nv1; nv->nv_next != NULL; nv = nv->nv_next); 185 186 nv->nv_next = nv2; 187 return nv1; 188} 189 190void 191cfgwarn(const char *fmt, ...) 192{ 193 va_list ap; 194 extern const char *yyfile; 195 196 va_start(ap, fmt); 197 cfgvxwarn(yyfile, currentline(), fmt, ap); 198 va_end(ap); 199} 200 201void 202cfgxwarn(const char *file, int line, const char *fmt, ...) 203{ 204 va_list ap; 205 206 va_start(ap, fmt); 207 cfgvxwarn(file, line, fmt, ap); 208 va_end(ap); 209} 210 211static void 212cfgvxwarn(const char *file, int line, const char *fmt, va_list ap) 213{ 214 cfgvxmsg(file, line, "warning: ", fmt, ap); 215} 216 217/* 218 * External (config file) error. Complain, using current file 219 * and line number. 220 */ 221void 222cfgerror(const char *fmt, ...) 223{ 224 va_list ap; 225 extern const char *yyfile; 226 227 va_start(ap, fmt); 228 cfgvxerror(yyfile, currentline(), fmt, ap); 229 va_end(ap); 230} 231 232/* 233 * Delayed config file error (i.e., something was wrong but we could not 234 * find out about it until later). 235 */ 236void 237cfgxerror(const char *file, int line, const char *fmt, ...) 238{ 239 va_list ap; 240 241 va_start(ap, fmt); 242 cfgvxerror(file, line, fmt, ap); 243 va_end(ap); 244} 245 246/* 247 * Internal form of error() and xerror(). 248 */ 249static void 250cfgvxerror(const char *file, int line, const char *fmt, va_list ap) 251{ 252 cfgvxmsg(file, line, "", fmt, ap); 253 errors++; 254} 255 256 257/* 258 * Internal error, abort. 259 */ 260__dead void 261panic(const char *fmt, ...) 262{ 263 va_list ap; 264 265 va_start(ap, fmt); 266 (void)fprintf(stderr, "%s: panic: ", getprogname()); 267 (void)vfprintf(stderr, fmt, ap); 268 (void)putc('\n', stderr); 269 va_end(ap); 270 exit(2); 271} 272 273/* 274 * Internal form of error() and xerror(). 275 */ 276static void 277cfgvxmsg(const char *file, int line, const char *msgclass, const char *fmt, 278 va_list ap) 279{ 280 281 (void)fprintf(stderr, "%s:%d: %s", file, line, msgclass); 282 (void)vfprintf(stderr, fmt, ap); 283 (void)putc('\n', stderr); 284} 285 286void 287autogen_comment(FILE *fp, const char *targetfile) 288{ 289 290 (void)fprintf(fp, 291 "/*\n" 292 " * MACHINE GENERATED: DO NOT EDIT\n" 293 " *\n" 294 " * %s, from \"%s\"\n" 295 " */\n\n", 296 targetfile, conffile); 297} 298