misc.c revision 1.18 1 1.18 lukem /* $NetBSD: misc.c,v 1.18 2007/10/05 07:36:45 lukem Exp $ */
2 1.12 tv /* $OpenBSD: misc.c,v 1.25 2001/10/10 11:17:37 espie Exp $ */
3 1.6 tls
4 1.5 glass /*
5 1.5 glass * Copyright (c) 1989, 1993
6 1.5 glass * The Regents of the University of California. All rights reserved.
7 1.5 glass *
8 1.5 glass * This code is derived from software contributed to Berkeley by
9 1.5 glass * Ozan Yigit at York University.
10 1.5 glass *
11 1.5 glass * Redistribution and use in source and binary forms, with or without
12 1.5 glass * modification, are permitted provided that the following conditions
13 1.5 glass * are met:
14 1.5 glass * 1. Redistributions of source code must retain the above copyright
15 1.5 glass * notice, this list of conditions and the following disclaimer.
16 1.5 glass * 2. Redistributions in binary form must reproduce the above copyright
17 1.5 glass * notice, this list of conditions and the following disclaimer in the
18 1.5 glass * documentation and/or other materials provided with the distribution.
19 1.16 agc * 3. Neither the name of the University nor the names of its contributors
20 1.5 glass * may be used to endorse or promote products derived from this software
21 1.5 glass * without specific prior written permission.
22 1.5 glass *
23 1.5 glass * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.5 glass * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.5 glass * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.5 glass * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.5 glass * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.5 glass * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.5 glass * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.5 glass * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.5 glass * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.5 glass * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.5 glass * SUCH DAMAGE.
34 1.5 glass */
35 1.5 glass
36 1.17 jmc #if HAVE_NBTOOL_CONFIG_H
37 1.17 jmc #include "nbtool_config.h"
38 1.17 jmc #endif
39 1.17 jmc
40 1.7 lukem #include <sys/cdefs.h>
41 1.15 tv #if defined(__RCSID) && !defined(lint)
42 1.6 tls #if 0
43 1.5 glass static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93";
44 1.6 tls #else
45 1.18 lukem __RCSID("$NetBSD: misc.c,v 1.18 2007/10/05 07:36:45 lukem Exp $");
46 1.6 tls #endif
47 1.5 glass #endif /* not lint */
48 1.5 glass
49 1.5 glass #include <sys/types.h>
50 1.5 glass #include <errno.h>
51 1.5 glass #include <stdio.h>
52 1.5 glass #include <stdlib.h>
53 1.12 tv #include <stddef.h>
54 1.5 glass #include <string.h>
55 1.18 lukem #include <util.h>
56 1.1 cgd #include "mdef.h"
57 1.5 glass #include "stdd.h"
58 1.5 glass #include "extern.h"
59 1.5 glass #include "pathnames.h"
60 1.12 tv
61 1.12 tv char *ep; /* first free char in strspace */
62 1.12 tv static char *strspace; /* string space for evaluation */
63 1.12 tv char *endest; /* end of string space */
64 1.12 tv static size_t strsize = STRSPMAX;
65 1.12 tv static size_t bufsize = BUFSIZE;
66 1.12 tv
67 1.12 tv char *buf; /* push-back buffer */
68 1.12 tv char *bufbase; /* the base for current ilevel */
69 1.12 tv char *bbase[MAXINP]; /* the base for each ilevel */
70 1.12 tv char *bp; /* first available character */
71 1.12 tv char *endpbb; /* end of push-back buffer */
72 1.12 tv
73 1.12 tv
74 1.5 glass /*
75 1.5 glass * find the index of second str in the first str.
76 1.5 glass */
77 1.12 tv ptrdiff_t
78 1.5 glass indx(s1, s2)
79 1.12 tv const char *s1;
80 1.12 tv const char *s2;
81 1.5 glass {
82 1.7 lukem char *t;
83 1.7 lukem
84 1.7 lukem t = strstr(s1, s2);
85 1.7 lukem if (t == NULL)
86 1.7 lukem return (-1);
87 1.7 lukem return (t - s1);
88 1.5 glass }
89 1.7 lukem
90 1.5 glass /*
91 1.5 glass * putback - push character back onto input
92 1.5 glass */
93 1.5 glass void
94 1.5 glass putback(c)
95 1.11 wiz int c;
96 1.5 glass {
97 1.12 tv if (c == EOF)
98 1.12 tv return;
99 1.12 tv if (bp >= endpbb)
100 1.12 tv enlarge_bufspace();
101 1.12 tv *bp++ = c;
102 1.9 cgd }
103 1.9 cgd
104 1.9 cgd /*
105 1.5 glass * pbstr - push string back onto input
106 1.5 glass * putback is replicated to improve
107 1.5 glass * performance.
108 1.5 glass */
109 1.5 glass void
110 1.5 glass pbstr(s)
111 1.12 tv const char *s;
112 1.5 glass {
113 1.12 tv size_t n;
114 1.2 glass
115 1.12 tv n = strlen(s);
116 1.12 tv while (endpbb - bp <= n)
117 1.12 tv enlarge_bufspace();
118 1.12 tv while (n > 0)
119 1.12 tv *bp++ = s[--n];
120 1.5 glass }
121 1.5 glass
122 1.5 glass /*
123 1.5 glass * pbnum - convert number to string, push back on input.
124 1.5 glass */
125 1.5 glass void
126 1.5 glass pbnum(n)
127 1.7 lukem int n;
128 1.5 glass {
129 1.7 lukem int num;
130 1.2 glass
131 1.5 glass num = (n < 0) ? -n : n;
132 1.2 glass do {
133 1.5 glass putback(num % 10 + '0');
134 1.2 glass }
135 1.5 glass while ((num /= 10) > 0);
136 1.2 glass
137 1.5 glass if (n < 0)
138 1.5 glass putback('-');
139 1.5 glass }
140 1.5 glass
141 1.5 glass /*
142 1.12 tv * pbunsigned - convert unsigned long to string, push back on input.
143 1.12 tv */
144 1.12 tv void
145 1.12 tv pbunsigned(n)
146 1.12 tv unsigned long n;
147 1.12 tv {
148 1.12 tv do {
149 1.12 tv putback(n % 10 + '0');
150 1.12 tv }
151 1.12 tv while ((n /= 10) > 0);
152 1.12 tv }
153 1.12 tv
154 1.12 tv void
155 1.12 tv initspaces()
156 1.12 tv {
157 1.12 tv int i;
158 1.12 tv
159 1.12 tv strspace = xalloc(strsize+1);
160 1.12 tv ep = strspace;
161 1.12 tv endest = strspace+strsize;
162 1.12 tv buf = (char *)xalloc(bufsize);
163 1.12 tv bufbase = buf;
164 1.12 tv bp = buf;
165 1.12 tv endpbb = buf + bufsize;
166 1.12 tv for (i = 0; i < MAXINP; i++)
167 1.12 tv bbase[i] = buf;
168 1.12 tv }
169 1.12 tv
170 1.12 tv void
171 1.12 tv enlarge_strspace()
172 1.12 tv {
173 1.12 tv char *newstrspace;
174 1.12 tv int i;
175 1.12 tv
176 1.12 tv strsize *= 2;
177 1.12 tv newstrspace = malloc(strsize + 1);
178 1.12 tv if (!newstrspace)
179 1.12 tv errx(1, "string space overflow");
180 1.12 tv memcpy(newstrspace, strspace, strsize/2);
181 1.12 tv for (i = 0; i <= sp; i++)
182 1.12 tv if (sstack[i])
183 1.12 tv mstack[i].sstr = (mstack[i].sstr - strspace)
184 1.12 tv + newstrspace;
185 1.12 tv ep = (ep-strspace) + newstrspace;
186 1.12 tv free(strspace);
187 1.12 tv strspace = newstrspace;
188 1.12 tv endest = strspace + strsize;
189 1.12 tv }
190 1.12 tv
191 1.12 tv void
192 1.12 tv enlarge_bufspace()
193 1.12 tv {
194 1.12 tv char *newbuf;
195 1.12 tv int i;
196 1.12 tv
197 1.12 tv bufsize *= 2;
198 1.12 tv newbuf = realloc(buf, bufsize);
199 1.12 tv if (!newbuf)
200 1.12 tv errx(1, "too many characters pushed back");
201 1.12 tv for (i = 0; i < MAXINP; i++)
202 1.12 tv bbase[i] = (bbase[i]-buf)+newbuf;
203 1.12 tv bp = (bp-buf)+newbuf;
204 1.12 tv bufbase = (bufbase-buf)+newbuf;
205 1.12 tv buf = newbuf;
206 1.12 tv endpbb = buf+bufsize;
207 1.12 tv }
208 1.12 tv
209 1.12 tv /*
210 1.5 glass * chrsave - put single char on string space
211 1.5 glass */
212 1.5 glass void
213 1.5 glass chrsave(c)
214 1.12 tv int c;
215 1.5 glass {
216 1.12 tv if (ep >= endest)
217 1.12 tv enlarge_strspace();
218 1.12 tv *ep++ = c;
219 1.5 glass }
220 1.5 glass
221 1.5 glass /*
222 1.5 glass * read in a diversion file, and dispose it.
223 1.5 glass */
224 1.5 glass void
225 1.5 glass getdiv(n)
226 1.7 lukem int n;
227 1.5 glass {
228 1.7 lukem int c;
229 1.2 glass
230 1.5 glass if (active == outfile[n])
231 1.7 lukem errx(1, "undivert: diversion still active");
232 1.12 tv rewind(outfile[n]);
233 1.12 tv while ((c = getc(outfile[n])) != EOF)
234 1.12 tv putc(c, active);
235 1.5 glass (void) fclose(outfile[n]);
236 1.5 glass outfile[n] = NULL;
237 1.5 glass }
238 1.2 glass
239 1.5 glass void
240 1.5 glass onintr(signo)
241 1.5 glass int signo;
242 1.5 glass {
243 1.12 tv #define intrmessage "m4: interrupted.\n"
244 1.12 tv write(STDERR_FILENO, intrmessage, sizeof(intrmessage));
245 1.18 lukem (void)raise_default_signal(signo);
246 1.12 tv _exit(1);
247 1.5 glass }
248 1.5 glass
249 1.5 glass /*
250 1.5 glass * killdiv - get rid of the diversion files
251 1.5 glass */
252 1.5 glass void
253 1.5 glass killdiv()
254 1.5 glass {
255 1.7 lukem int n;
256 1.2 glass
257 1.12 tv for (n = 0; n < maxout; n++)
258 1.5 glass if (outfile[n] != NULL) {
259 1.5 glass (void) fclose(outfile[n]);
260 1.5 glass }
261 1.5 glass }
262 1.2 glass
263 1.12 tv /*
264 1.12 tv * resizedivs: allocate more diversion files */
265 1.12 tv void
266 1.12 tv resizedivs(n)
267 1.12 tv int n;
268 1.12 tv {
269 1.12 tv int i;
270 1.12 tv
271 1.12 tv outfile = (FILE **)realloc(outfile, sizeof(FILE *) * n);
272 1.12 tv if (outfile == NULL)
273 1.12 tv errx(1, "too many diverts %d", n);
274 1.12 tv for (i = maxout; i < n; i++)
275 1.12 tv outfile[i] = NULL;
276 1.12 tv maxout = n;
277 1.12 tv }
278 1.12 tv
279 1.12 tv void *
280 1.5 glass xalloc(n)
281 1.12 tv size_t n;
282 1.5 glass {
283 1.7 lukem char *p = malloc(n);
284 1.2 glass
285 1.5 glass if (p == NULL)
286 1.7 lukem err(1, "malloc");
287 1.5 glass return p;
288 1.5 glass }
289 1.2 glass
290 1.5 glass char *
291 1.5 glass xstrdup(s)
292 1.7 lukem const char *s;
293 1.5 glass {
294 1.7 lukem char *p = strdup(s);
295 1.5 glass if (p == NULL)
296 1.7 lukem err(1, "strdup");
297 1.5 glass return p;
298 1.5 glass }
299 1.2 glass
300 1.12 tv void
301 1.13 tv usage(progname)
302 1.13 tv const char *progname;
303 1.12 tv {
304 1.13 tv fprintf(stderr, "usage: %s [-Pg] [-Dname[=val]] [-I dirname] [-Uname]\n", progname);
305 1.13 tv fprintf(stderr, "\t[-d flags] [-o trfile] [-t macro]\n");
306 1.12 tv exit(1);
307 1.12 tv }
308 1.12 tv
309 1.12 tv int
310 1.12 tv obtain_char(f)
311 1.12 tv struct input_file *f;
312 1.12 tv {
313 1.12 tv if (f->c == EOF)
314 1.12 tv return EOF;
315 1.12 tv else if (f->c == '\n')
316 1.12 tv f->lineno++;
317 1.12 tv
318 1.12 tv f->c = fgetc(f->file);
319 1.12 tv return f->c;
320 1.12 tv }
321 1.12 tv
322 1.12 tv void
323 1.12 tv set_input(f, real, name)
324 1.12 tv struct input_file *f;
325 1.12 tv FILE *real;
326 1.12 tv const char *name;
327 1.12 tv {
328 1.12 tv f->file = real;
329 1.12 tv f->lineno = 1;
330 1.12 tv f->c = 0;
331 1.12 tv f->name = xstrdup(name);
332 1.12 tv }
333 1.12 tv
334 1.12 tv void
335 1.12 tv release_input(f)
336 1.12 tv struct input_file *f;
337 1.12 tv {
338 1.12 tv if (f->file != stdin)
339 1.12 tv fclose(f->file);
340 1.12 tv f->c = EOF;
341 1.12 tv /*
342 1.12 tv * XXX can't free filename, as there might still be
343 1.12 tv * error information pointing to it.
344 1.12 tv */
345 1.12 tv }
346 1.12 tv
347 1.12 tv void
348 1.12 tv doprintlineno(f)
349 1.12 tv struct input_file *f;
350 1.5 glass {
351 1.12 tv pbunsigned(f->lineno);
352 1.12 tv }
353 1.2 glass
354 1.12 tv void
355 1.12 tv doprintfilename(f)
356 1.12 tv struct input_file *f;
357 1.12 tv {
358 1.12 tv pbstr(rquote);
359 1.12 tv pbstr(f->name);
360 1.12 tv pbstr(lquote);
361 1.12 tv }
362 1.2 glass
363 1.12 tv /*
364 1.12 tv * buffer_mark/dump_buffer: allows one to save a mark in a buffer,
365 1.12 tv * and later dump everything that was added since then to a file.
366 1.12 tv */
367 1.12 tv size_t
368 1.12 tv buffer_mark()
369 1.12 tv {
370 1.12 tv return bp - buf;
371 1.5 glass }
372 1.2 glass
373 1.12 tv
374 1.5 glass void
375 1.12 tv dump_buffer(f, m)
376 1.12 tv FILE *f;
377 1.12 tv size_t m;
378 1.5 glass {
379 1.12 tv char *s;
380 1.12 tv
381 1.12 tv for (s = bp; s-buf > m;)
382 1.12 tv fputc(*--s, f);
383 1.5 glass }
384