xref: /netbsd-src/usr.bin/config/util.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: util.c,v 1.8 2008/12/28 01:23:46 christos 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, 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  */
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