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