util.c revision 1.1 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