Home | History | Annotate | Line # | Download | only in config
util.c revision 1.7
      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 
     57 static void cfgvxerror(const char *, int, const char *, va_list)
     58 	     __attribute__((__format__(__printf__, 3, 0)));
     59 static void cfgvxwarn(const char *, int, const char *, va_list)
     60 	     __attribute__((__format__(__printf__, 3, 0)));
     61 static 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  */
     67 void
     68 prefix_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  */
     91 void
     92 prefix_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  */
    109 char *
    110 sourcepath(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 
    138 struct nvlist *
    139 newnv(const char *name, const char *str, void *ptr, int 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_int = i;
    149 	return nv;
    150 }
    151 
    152 /*
    153  * Free an nvlist structure (just one).
    154  */
    155 void
    156 nvfree(struct nvlist *nv)
    157 {
    158 
    159 	free(nv);
    160 }
    161 
    162 /*
    163  * Free an nvlist (the whole list).
    164  */
    165 void
    166 nvfreel(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 
    176 struct nvlist *
    177 nvcat(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 
    190 void
    191 cfgwarn(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 
    201 void
    202 cfgxwarn(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 
    211 static void
    212 cfgvxwarn(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  */
    221 void
    222 cfgerror(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  */
    236 void
    237 cfgxerror(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  */
    249 static void
    250 cfgvxerror(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
    261 panic(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  */
    276 static void
    277 cfgvxmsg(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 
    286 void
    287 autogen_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