Annotation of src/usr.bin/m4/misc.c, Revision 1.30
1.30 ! espie 1: /* $OpenBSD: misc.c,v 1.29 2003/06/03 02:56:10 millert 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.30 ! espie 40: static char rcsid[] = "$OpenBSD: misc.c,v 1.29 2003/06/03 02:56:10 millert 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.12 espie 122: int num;
1.1 deraadt 123:
124: num = (n < 0) ? -n : n;
125: do {
126: putback(num % 10 + '0');
127: }
128: while ((num /= 10) > 0);
129:
130: if (n < 0)
131: putback('-');
132: }
133:
1.18 espie 134: /*
135: * pbunsigned - convert unsigned long to string, push back on input.
136: */
137: void
1.27 espie 138: pbunsigned(unsigned long n)
1.18 espie 139: {
140: do {
141: putback(n % 10 + '0');
142: }
143: while ((n /= 10) > 0);
144: }
1.9 espie 145:
146: void
147: initspaces()
148: {
149: int i;
150:
1.30 ! espie 151: strspace = xalloc(strsize+1, NULL);
1.9 espie 152: ep = strspace;
153: endest = strspace+strsize;
1.30 ! espie 154: buf = (char *)xalloc(bufsize, NULL);
1.9 espie 155: bufbase = buf;
156: bp = buf;
157: endpbb = buf + bufsize;
158: for (i = 0; i < MAXINP; i++)
159: bbase[i] = buf;
160: }
161:
1.24 espie 162: void
1.17 espie 163: enlarge_strspace()
1.9 espie 164: {
165: char *newstrspace;
1.19 espie 166: int i;
1.9 espie 167:
168: strsize *= 2;
169: newstrspace = malloc(strsize + 1);
170: if (!newstrspace)
171: errx(1, "string space overflow");
172: memcpy(newstrspace, strspace, strsize/2);
1.19 espie 173: for (i = 0; i <= sp; i++)
174: if (sstack[i])
175: mstack[i].sstr = (mstack[i].sstr - strspace)
176: + newstrspace;
1.9 espie 177: ep = (ep-strspace) + newstrspace;
1.19 espie 178: free(strspace);
1.9 espie 179: strspace = newstrspace;
180: endest = strspace + strsize;
181: }
182:
1.24 espie 183: void
1.17 espie 184: enlarge_bufspace()
1.9 espie 185: {
1.17 espie 186: char *newbuf;
1.9 espie 187: int i;
188:
1.30 ! espie 189: bufsize += bufsize/2;
! 190: newbuf = xrealloc(buf, bufsize, "too many characters pushed back");
1.9 espie 191: for (i = 0; i < MAXINP; i++)
192: bbase[i] = (bbase[i]-buf)+newbuf;
193: bp = (bp-buf)+newbuf;
194: bufbase = (bufbase-buf)+newbuf;
195: buf = newbuf;
1.10 espie 196: endpbb = buf+bufsize;
1.9 espie 197: }
198:
1.1 deraadt 199: /*
200: * chrsave - put single char on string space
201: */
202: void
1.27 espie 203: chrsave(int c)
1.1 deraadt 204: {
1.9 espie 205: if (ep >= endest)
206: enlarge_strspace();
207: *ep++ = c;
1.1 deraadt 208: }
209:
210: /*
211: * read in a diversion file, and dispose it.
212: */
213: void
1.27 espie 214: getdiv(int n)
1.1 deraadt 215: {
1.12 espie 216: int c;
1.1 deraadt 217:
218: if (active == outfile[n])
1.7 espie 219: errx(1, "undivert: diversion still active");
1.8 espie 220: rewind(outfile[n]);
221: while ((c = getc(outfile[n])) != EOF)
222: putc(c, active);
1.1 deraadt 223: (void) fclose(outfile[n]);
1.13 espie 224: outfile[n] = NULL;
1.1 deraadt 225: }
226:
227: void
1.27 espie 228: onintr(int signo)
1.1 deraadt 229: {
1.21 espie 230: #define intrmessage "m4: interrupted.\n"
1.26 deraadt 231: write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1);
1.21 espie 232: _exit(1);
1.1 deraadt 233: }
234:
235: /*
236: * killdiv - get rid of the diversion files
237: */
238: void
239: killdiv()
240: {
1.12 espie 241: int n;
1.1 deraadt 242:
1.20 espie 243: for (n = 0; n < maxout; n++)
1.1 deraadt 244: if (outfile[n] != NULL) {
245: (void) fclose(outfile[n]);
246: }
1.20 espie 247: }
248:
249: /*
250: * resizedivs: allocate more diversion files */
251: void
1.27 espie 252: resizedivs(int n)
1.20 espie 253: {
254: int i;
255:
1.30 ! espie 256: outfile = (FILE **)xrealloc(outfile, sizeof(FILE *) * n,
! 257: "too many diverts %d", n);
1.20 espie 258: for (i = maxout; i < n; i++)
259: outfile[i] = NULL;
260: maxout = n;
1.1 deraadt 261: }
262:
1.18 espie 263: void *
1.30 ! espie 264: xalloc(size_t n, const char *fmt, ...)
1.1 deraadt 265: {
1.30 ! espie 266: void *p = malloc(n);
1.1 deraadt 267:
1.30 ! espie 268: if (p == NULL) {
! 269: if (fmt == NULL)
! 270: err(1, "malloc");
! 271: else {
! 272: va_list va;
! 273:
! 274: va_start(va, fmt);
! 275: verr(1, fmt, va);
! 276: va_end(va);
! 277: }
! 278: }
! 279: return p;
! 280: }
! 281:
! 282: void *
! 283: xrealloc(void *old, size_t n, const char *fmt, ...)
! 284: {
! 285: char *p = realloc(old, n);
! 286:
! 287: if (p == NULL) {
! 288: free(old);
! 289: if (fmt == NULL)
! 290: err(1, "realloc");
! 291: else {
! 292: va_list va;
! 293:
! 294: va_start(va, fmt);
! 295: verr(1, fmt, va);
! 296: va_end(va);
! 297: }
! 298: }
1.1 deraadt 299: return p;
300: }
301:
302: char *
1.27 espie 303: xstrdup(const char *s)
1.1 deraadt 304: {
1.12 espie 305: char *p = strdup(s);
1.1 deraadt 306: if (p == NULL)
1.7 espie 307: err(1, "strdup");
1.1 deraadt 308: return p;
309: }
310:
311: void
312: usage()
313: {
1.28 espie 314: fprintf(stderr, "usage: m4 [-gs] [-d flags] [-t macro] [-o file] [-Dname[=val]] [-Uname] [-I dirname...]\n");
1.1 deraadt 315: exit(1);
316: }
317:
1.15 espie 318: int
1.27 espie 319: obtain_char(struct input_file *f)
1.15 espie 320: {
1.17 espie 321: if (f->c == EOF)
322: return EOF;
323: else if (f->c == '\n')
1.15 espie 324: f->lineno++;
325:
326: f->c = fgetc(f->file);
327: return f->c;
328: }
329:
330: void
1.27 espie 331: set_input(struct input_file *f, FILE *real, const char *name)
1.15 espie 332: {
333: f->file = real;
334: f->lineno = 1;
335: f->c = 0;
336: f->name = xstrdup(name);
1.28 espie 337: emit_synchline();
338: }
339:
340: void
341: do_emit_synchline()
342: {
343: fprintf(active, "#line %lu \"%s\"\n",
344: infile[ilevel].lineno, infile[ilevel].name);
345: infile[ilevel].synch_lineno = infile[ilevel].lineno;
1.15 espie 346: }
347:
348: void
1.27 espie 349: release_input(struct input_file *f)
1.15 espie 350: {
351: if (f->file != stdin)
352: fclose(f->file);
1.17 espie 353: f->c = EOF;
1.16 espie 354: /*
355: * XXX can't free filename, as there might still be
356: * error information pointing to it.
357: */
1.18 espie 358: }
359:
360: void
1.27 espie 361: doprintlineno(struct input_file *f)
1.18 espie 362: {
363: pbunsigned(f->lineno);
364: }
365:
366: void
1.27 espie 367: doprintfilename(struct input_file *f)
1.18 espie 368: {
1.25 espie 369: pbstr(rquote);
1.18 espie 370: pbstr(f->name);
1.25 espie 371: pbstr(lquote);
1.22 espie 372: }
373:
374: /*
375: * buffer_mark/dump_buffer: allows one to save a mark in a buffer,
376: * and later dump everything that was added since then to a file.
377: */
378: size_t
379: buffer_mark()
380: {
381: return bp - buf;
382: }
383:
384:
385: void
1.27 espie 386: dump_buffer(FILE *f, size_t m)
1.22 espie 387: {
388: char *s;
389:
1.23 espie 390: for (s = bp; s-buf > m;)
1.22 espie 391: fputc(*--s, f);
1.15 espie 392: }