Merge from vendor branch PKGSRC:
[netbsd-mini2440.git] / usr.bin / config / util.c
blob22e6938838a96125e8f33e37c1ca1a793386b028
1 /* $NetBSD: util.c,v 1.7 2007/12/12 00:03:34 lukem Exp $ */
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
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.
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.
40 * from: @(#)util.c 8.1 (Berkeley) 6/6/93
43 #if HAVE_NBTOOL_CONFIG_H
44 #include "nbtool_config.h"
45 #endif
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"
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)));
65 * Push a prefix onto the prefix stack.
67 void
68 prefix_push(const char *path)
70 struct prefix *pf;
71 char *cp;
73 pf = ecalloc(1, sizeof(struct prefix));
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);
85 SLIST_INSERT_HEAD(&prefixes, pf, pf_next);
89 * Pop a prefix off the prefix stack.
91 void
92 prefix_pop(void)
94 struct prefix *pf;
96 if ((pf = SLIST_FIRST(&prefixes)) == NULL) {
97 cfgerror("no prefixes on the stack to pop");
98 return;
101 SLIST_REMOVE_HEAD(&prefixes, pf_next);
102 /* Remember this prefix for emitting -I... directives later. */
103 SLIST_INSERT_HEAD(&allprefixes, pf, pf_next);
107 * Prepend the source path to a file name.
109 char *
110 sourcepath(const char *file)
112 size_t len;
113 char *cp;
114 struct prefix *pf;
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;
125 cp = emalloc(len);
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);
138 struct nvlist *
139 newnv(const char *name, const char *str, void *ptr, long long i, struct nvlist *next)
141 struct nvlist *nv;
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;
153 * Free an nvlist structure (just one).
155 void
156 nvfree(struct nvlist *nv)
159 free(nv);
163 * Free an nvlist (the whole list).
165 void
166 nvfreel(struct nvlist *nv)
168 struct nvlist *next;
170 for (; nv != NULL; nv = next) {
171 next = nv->nv_next;
172 free(nv);
176 struct nvlist *
177 nvcat(struct nvlist *nv1, struct nvlist *nv2)
179 struct nvlist *nv;
181 if (nv1 == NULL)
182 return nv2;
184 for (nv = nv1; nv->nv_next != NULL; nv = nv->nv_next);
186 nv->nv_next = nv2;
187 return nv1;
190 void
191 cfgwarn(const char *fmt, ...)
193 va_list ap;
194 extern const char *yyfile;
196 va_start(ap, fmt);
197 cfgvxwarn(yyfile, currentline(), fmt, ap);
198 va_end(ap);
201 void
202 cfgxwarn(const char *file, int line, const char *fmt, ...)
204 va_list ap;
206 va_start(ap, fmt);
207 cfgvxwarn(file, line, fmt, ap);
208 va_end(ap);
211 static void
212 cfgvxwarn(const char *file, int line, const char *fmt, va_list ap)
214 cfgvxmsg(file, line, "warning: ", fmt, ap);
218 * External (config file) error. Complain, using current file
219 * and line number.
221 void
222 cfgerror(const char *fmt, ...)
224 va_list ap;
225 extern const char *yyfile;
227 va_start(ap, fmt);
228 cfgvxerror(yyfile, currentline(), fmt, ap);
229 va_end(ap);
233 * Delayed config file error (i.e., something was wrong but we could not
234 * find out about it until later).
236 void
237 cfgxerror(const char *file, int line, const char *fmt, ...)
239 va_list ap;
241 va_start(ap, fmt);
242 cfgvxerror(file, line, fmt, ap);
243 va_end(ap);
247 * Internal form of error() and xerror().
249 static void
250 cfgvxerror(const char *file, int line, const char *fmt, va_list ap)
252 cfgvxmsg(file, line, "", fmt, ap);
253 errors++;
258 * Internal error, abort.
260 __dead void
261 panic(const char *fmt, ...)
263 va_list ap;
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);
274 * Internal form of error() and xerror().
276 static void
277 cfgvxmsg(const char *file, int line, const char *msgclass, const char *fmt,
278 va_list ap)
281 (void)fprintf(stderr, "%s:%d: %s", file, line, msgclass);
282 (void)vfprintf(stderr, fmt, ap);
283 (void)putc('\n', stderr);
286 void
287 autogen_comment(FILE *fp, const char *targetfile)
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);