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