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