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