Annotation of src/usr.bin/m4/misc.c, Revision 1.31
1.31 ! espie 1: /* $OpenBSD: misc.c,v 1.30 2003/11/17 17:12:10 espie Exp $ */
1.1 deraadt 2: /* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls 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.
1.29 millert 19: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 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: #ifndef lint
37: #if 0
38: static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93";
39: #else
1.31 ! espie 40: static char rcsid[] = "$OpenBSD: misc.c,v 1.30 2003/11/17 17:12:10 espie Exp $";
1.1 deraadt 41: #endif
42: #endif /* not lint */
43:
44: #include <sys/types.h>
45: #include <errno.h>
46: #include <unistd.h>
1.30 espie 47: #include <stdarg.h>
1.1 deraadt 48: #include <stdio.h>
49: #include <stdlib.h>
1.7 espie 50: #include <stddef.h>
1.1 deraadt 51: #include <string.h>
1.7 espie 52: #include <err.h>
1.1 deraadt 53: #include "mdef.h"
54: #include "stdd.h"
55: #include "extern.h"
56: #include "pathnames.h"
57:
1.9 espie 58:
59: char *ep; /* first free char in strspace */
60: static char *strspace; /* string space for evaluation */
1.24 espie 61: char *endest; /* end of string space */
1.9 espie 62: static size_t strsize = STRSPMAX;
63: static size_t bufsize = BUFSIZE;
64:
1.17 espie 65: char *buf; /* push-back buffer */
66: char *bufbase; /* the base for current ilevel */
67: char *bbase[MAXINP]; /* the base for each ilevel */
68: char *bp; /* first available character */
1.24 espie 69: char *endpbb; /* end of push-back buffer */
1.9 espie 70:
71:
1.1 deraadt 72: /*
73: * find the index of second str in the first str.
74: */
1.7 espie 75: ptrdiff_t
1.27 espie 76: indx(const char *s1, const char *s2)
1.1 deraadt 77: {
1.12 espie 78: char *t;
1.7 espie 79:
1.12 espie 80: t = strstr(s1, s2);
81: if (t == NULL)
82: return (-1);
1.7 espie 83: else
1.12 espie 84: return (t - s1);
1.1 deraadt 85: }
86: /*
87: * putback - push character back onto input
88: */
89: void
1.27 espie 90: putback(int c)
1.1 deraadt 91: {
1.17 espie 92: if (c == EOF)
93: return;
1.9 espie 94: if (bp >= endpbb)
95: enlarge_bufspace();
96: *bp++ = c;
1.1 deraadt 97: }
98:
99: /*
100: * pbstr - push string back onto input
101: * putback is replicated to improve
102: * performance.
103: */
104: void
1.27 espie 105: pbstr(const char *s)
1.1 deraadt 106: {
1.9 espie 107: size_t n;
1.1 deraadt 108:
1.9 espie 109: n = strlen(s);
1.12 espie 110: while (endpbb - bp <= n)
1.9 espie 111: enlarge_bufspace();
112: while (n > 0)
113: *bp++ = s[--n];
1.1 deraadt 114: }
115:
116: /*
117: * pbnum - convert number to string, push back on input.
118: */
119: void
1.27 espie 120: pbnum(int n)
1.1 deraadt 121: {
1.31 ! espie 122: pbnumbase(n, 10, 0);
! 123: }
! 124:
! 125: void
! 126: pbnumbase(int n, int base, int d)
! 127: {
! 128: static char digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
1.12 espie 129: int num;
1.31 ! espie 130: int printed = 0;
! 131:
! 132: if (base > 36)
! 133: errx(1, "base %d > 36: not supported", base);
! 134:
! 135: if (base < 2)
! 136: errx(1, "bad base %d for conversion", base);
1.1 deraadt 137:
138: num = (n < 0) ? -n : n;
139: do {
1.31 ! espie 140: putback(digits[num % base]);
! 141: printed++;
1.1 deraadt 142: }
1.31 ! espie 143: while ((num /= base) > 0);
! 144:
! 145: if (n < 0)
! 146: printed++;
! 147: while (printed++ < d)
! 148: putback('0');
1.1 deraadt 149:
150: if (n < 0)
151: putback('-');
152: }
153:
1.18 espie 154: /*
155: * pbunsigned - convert unsigned long to string, push back on input.
156: */
157: void
1.27 espie 158: pbunsigned(unsigned long n)
1.18 espie 159: {
160: do {
161: putback(n % 10 + '0');
162: }
163: while ((n /= 10) > 0);
164: }
1.9 espie 165:
166: void
167: initspaces()
168: {
169: int i;
170:
1.30 espie 171: strspace = xalloc(strsize+1, NULL);
1.9 espie 172: ep = strspace;
173: endest = strspace+strsize;
1.30 espie 174: buf = (char *)xalloc(bufsize, NULL);
1.9 espie 175: bufbase = buf;
176: bp = buf;
177: endpbb = buf + bufsize;
178: for (i = 0; i < MAXINP; i++)
179: bbase[i] = buf;
180: }
181:
1.24 espie 182: void
1.17 espie 183: enlarge_strspace()
1.9 espie 184: {
185: char *newstrspace;
1.19 espie 186: int i;
1.9 espie 187:
188: strsize *= 2;
189: newstrspace = malloc(strsize + 1);
190: if (!newstrspace)
191: errx(1, "string space overflow");
192: memcpy(newstrspace, strspace, strsize/2);
1.19 espie 193: for (i = 0; i <= sp; i++)
194: if (sstack[i])
195: mstack[i].sstr = (mstack[i].sstr - strspace)
196: + newstrspace;
1.9 espie 197: ep = (ep-strspace) + newstrspace;
1.19 espie 198: free(strspace);
1.9 espie 199: strspace = newstrspace;
200: endest = strspace + strsize;
201: }
202:
1.24 espie 203: void
1.17 espie 204: enlarge_bufspace()
1.9 espie 205: {
1.17 espie 206: char *newbuf;
1.9 espie 207: int i;
208:
1.30 espie 209: bufsize += bufsize/2;
210: newbuf = xrealloc(buf, bufsize, "too many characters pushed back");
1.9 espie 211: for (i = 0; i < MAXINP; i++)
212: bbase[i] = (bbase[i]-buf)+newbuf;
213: bp = (bp-buf)+newbuf;
214: bufbase = (bufbase-buf)+newbuf;
215: buf = newbuf;
1.10 espie 216: endpbb = buf+bufsize;
1.9 espie 217: }
218:
1.1 deraadt 219: /*
220: * chrsave - put single char on string space
221: */
222: void
1.27 espie 223: chrsave(int c)
1.1 deraadt 224: {
1.9 espie 225: if (ep >= endest)
226: enlarge_strspace();
227: *ep++ = c;
1.1 deraadt 228: }
229:
230: /*
231: * read in a diversion file, and dispose it.
232: */
233: void
1.27 espie 234: getdiv(int n)
1.1 deraadt 235: {
1.12 espie 236: int c;
1.1 deraadt 237:
238: if (active == outfile[n])
1.7 espie 239: errx(1, "undivert: diversion still active");
1.8 espie 240: rewind(outfile[n]);
241: while ((c = getc(outfile[n])) != EOF)
242: putc(c, active);
1.1 deraadt 243: (void) fclose(outfile[n]);
1.13 espie 244: outfile[n] = NULL;
1.1 deraadt 245: }
246:
247: void
1.27 espie 248: onintr(int signo)
1.1 deraadt 249: {
1.21 espie 250: #define intrmessage "m4: interrupted.\n"
1.26 deraadt 251: write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1);
1.21 espie 252: _exit(1);
1.1 deraadt 253: }
254:
255: /*
256: * killdiv - get rid of the diversion files
257: */
258: void
259: killdiv()
260: {
1.12 espie 261: int n;
1.1 deraadt 262:
1.20 espie 263: for (n = 0; n < maxout; n++)
1.1 deraadt 264: if (outfile[n] != NULL) {
265: (void) fclose(outfile[n]);
266: }
1.20 espie 267: }
268:
269: /*
270: * resizedivs: allocate more diversion files */
271: void
1.27 espie 272: resizedivs(int n)
1.20 espie 273: {
274: int i;
275:
1.30 espie 276: outfile = (FILE **)xrealloc(outfile, sizeof(FILE *) * n,
277: "too many diverts %d", n);
1.20 espie 278: for (i = maxout; i < n; i++)
279: outfile[i] = NULL;
280: maxout = n;
1.1 deraadt 281: }
282:
1.18 espie 283: void *
1.30 espie 284: xalloc(size_t n, const char *fmt, ...)
1.1 deraadt 285: {
1.30 espie 286: void *p = malloc(n);
1.1 deraadt 287:
1.30 espie 288: if (p == NULL) {
289: if (fmt == NULL)
290: err(1, "malloc");
291: else {
292: va_list va;
293:
294: va_start(va, fmt);
295: verr(1, fmt, va);
296: va_end(va);
297: }
298: }
299: return p;
300: }
301:
302: void *
303: xrealloc(void *old, size_t n, const char *fmt, ...)
304: {
305: char *p = realloc(old, n);
306:
307: if (p == NULL) {
308: free(old);
309: if (fmt == NULL)
310: err(1, "realloc");
311: else {
312: va_list va;
313:
314: va_start(va, fmt);
315: verr(1, fmt, va);
316: va_end(va);
317: }
318: }
1.1 deraadt 319: return p;
320: }
321:
322: char *
1.27 espie 323: xstrdup(const char *s)
1.1 deraadt 324: {
1.12 espie 325: char *p = strdup(s);
1.1 deraadt 326: if (p == NULL)
1.7 espie 327: err(1, "strdup");
1.1 deraadt 328: return p;
329: }
330:
331: void
332: usage()
333: {
1.28 espie 334: fprintf(stderr, "usage: m4 [-gs] [-d flags] [-t macro] [-o file] [-Dname[=val]] [-Uname] [-I dirname...]\n");
1.1 deraadt 335: exit(1);
336: }
337:
1.15 espie 338: int
1.27 espie 339: obtain_char(struct input_file *f)
1.15 espie 340: {
1.17 espie 341: if (f->c == EOF)
342: return EOF;
343: else if (f->c == '\n')
1.15 espie 344: f->lineno++;
345:
346: f->c = fgetc(f->file);
347: return f->c;
348: }
349:
350: void
1.27 espie 351: set_input(struct input_file *f, FILE *real, const char *name)
1.15 espie 352: {
353: f->file = real;
354: f->lineno = 1;
355: f->c = 0;
356: f->name = xstrdup(name);
1.28 espie 357: emit_synchline();
358: }
359:
360: void
361: do_emit_synchline()
362: {
363: fprintf(active, "#line %lu \"%s\"\n",
364: infile[ilevel].lineno, infile[ilevel].name);
365: infile[ilevel].synch_lineno = infile[ilevel].lineno;
1.15 espie 366: }
367:
368: void
1.27 espie 369: release_input(struct input_file *f)
1.15 espie 370: {
371: if (f->file != stdin)
372: fclose(f->file);
1.17 espie 373: f->c = EOF;
1.16 espie 374: /*
375: * XXX can't free filename, as there might still be
376: * error information pointing to it.
377: */
1.18 espie 378: }
379:
380: void
1.27 espie 381: doprintlineno(struct input_file *f)
1.18 espie 382: {
383: pbunsigned(f->lineno);
384: }
385:
386: void
1.27 espie 387: doprintfilename(struct input_file *f)
1.18 espie 388: {
1.25 espie 389: pbstr(rquote);
1.18 espie 390: pbstr(f->name);
1.25 espie 391: pbstr(lquote);
1.22 espie 392: }
393:
394: /*
395: * buffer_mark/dump_buffer: allows one to save a mark in a buffer,
396: * and later dump everything that was added since then to a file.
397: */
398: size_t
399: buffer_mark()
400: {
401: return bp - buf;
402: }
403:
404:
405: void
1.27 espie 406: dump_buffer(FILE *f, size_t m)
1.22 espie 407: {
408: char *s;
409:
1.23 espie 410: for (s = bp; s-buf > m;)
1.22 espie 411: fputc(*--s, f);
1.15 espie 412: }