1bd2bfb58SJuli Mallett /* $OpenBSD: misc.c,v 1.27 2002/04/26 16:15:16 espie Exp $ */ 2acc9d408SJuli Mallett /* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $ */ 3acc9d408SJuli Mallett 49b50d902SRodney W. Grimes /* 59b50d902SRodney W. Grimes * Copyright (c) 1989, 1993 69b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 79b50d902SRodney W. Grimes * 89b50d902SRodney W. Grimes * This code is derived from software contributed to Berkeley by 99b50d902SRodney W. Grimes * Ozan Yigit at York University. 109b50d902SRodney W. Grimes * 119b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 129b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 139b50d902SRodney W. Grimes * are met: 149b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 159b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 169b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 179b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 189b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 199b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 209b50d902SRodney W. Grimes * must display the following acknowledgement: 219b50d902SRodney W. Grimes * This product includes software developed by the University of 229b50d902SRodney W. Grimes * California, Berkeley and its contributors. 239b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 249b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 259b50d902SRodney W. Grimes * without specific prior written permission. 269b50d902SRodney W. Grimes * 279b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 289b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 299b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 309b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 319b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 329b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 339b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 349b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 359b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 369b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 379b50d902SRodney W. Grimes * SUCH DAMAGE. 389b50d902SRodney W. Grimes */ 399b50d902SRodney W. Grimes 4090432ef8SJuli Mallett #ifndef lint 4190432ef8SJuli Mallett #if 0 4290432ef8SJuli Mallett static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93"; 4390432ef8SJuli Mallett #else 4490432ef8SJuli Mallett #if 0 4590432ef8SJuli Mallett static char rcsid[] = "$OpenBSD: misc.c,v 1.27 2002/04/26 16:15:16 espie Exp $"; 4690432ef8SJuli Mallett #endif 4790432ef8SJuli Mallett #endif 4890432ef8SJuli Mallett #endif /* not lint */ 4990432ef8SJuli Mallett 50acc9d408SJuli Mallett #include <sys/cdefs.h> 51acc9d408SJuli Mallett __FBSDID("$FreeBSD$"); 529b50d902SRodney W. Grimes 539b50d902SRodney W. Grimes #include <sys/types.h> 54acc9d408SJuli Mallett #include <errno.h> 55acc9d408SJuli Mallett #include <unistd.h> 569b50d902SRodney W. Grimes #include <stdio.h> 579b50d902SRodney W. Grimes #include <stdlib.h> 58acc9d408SJuli Mallett #include <stddef.h> 599b50d902SRodney W. Grimes #include <string.h> 60acc9d408SJuli Mallett #include <err.h> 619b50d902SRodney W. Grimes #include "mdef.h" 629b50d902SRodney W. Grimes #include "stdd.h" 639b50d902SRodney W. Grimes #include "extern.h" 649b50d902SRodney W. Grimes #include "pathnames.h" 659b50d902SRodney W. Grimes 66acc9d408SJuli Mallett 67acc9d408SJuli Mallett char *ep; /* first free char in strspace */ 68acc9d408SJuli Mallett static char *strspace; /* string space for evaluation */ 69acc9d408SJuli Mallett char *endest; /* end of string space */ 70acc9d408SJuli Mallett static size_t strsize = STRSPMAX; 71acc9d408SJuli Mallett static size_t bufsize = BUFSIZE; 72acc9d408SJuli Mallett 73acc9d408SJuli Mallett char *buf; /* push-back buffer */ 74acc9d408SJuli Mallett char *bufbase; /* the base for current ilevel */ 75acc9d408SJuli Mallett char *bbase[MAXINP]; /* the base for each ilevel */ 76acc9d408SJuli Mallett char *bp; /* first available character */ 77acc9d408SJuli Mallett char *endpbb; /* end of push-back buffer */ 78acc9d408SJuli Mallett 79acc9d408SJuli Mallett 809b50d902SRodney W. Grimes /* 819b50d902SRodney W. Grimes * find the index of second str in the first str. 829b50d902SRodney W. Grimes */ 83acc9d408SJuli Mallett ptrdiff_t 84bd2bfb58SJuli Mallett indx(const char *s1, const char *s2) 859b50d902SRodney W. Grimes { 86acc9d408SJuli Mallett char *t; 879b50d902SRodney W. Grimes 88acc9d408SJuli Mallett t = strstr(s1, s2); 89acc9d408SJuli Mallett if (t == NULL) 909b50d902SRodney W. Grimes return (-1); 91acc9d408SJuli Mallett else 92acc9d408SJuli Mallett return (t - s1); 939b50d902SRodney W. Grimes } 949b50d902SRodney W. Grimes /* 959b50d902SRodney W. Grimes * putback - push character back onto input 969b50d902SRodney W. Grimes */ 979b50d902SRodney W. Grimes void 98bd2bfb58SJuli Mallett putback(int c) 999b50d902SRodney W. Grimes { 1007c5eeb39SAndrey A. Chernov if (c == EOF) 101b63b4cdbSAndrey A. Chernov return; 102acc9d408SJuli Mallett if (bp >= endpbb) 103acc9d408SJuli Mallett enlarge_bufspace(); 1049b50d902SRodney W. Grimes *bp++ = c; 1059b50d902SRodney W. Grimes } 1069b50d902SRodney W. Grimes 1079b50d902SRodney W. Grimes /* 1089b50d902SRodney W. Grimes * pbstr - push string back onto input 1099b50d902SRodney W. Grimes * putback is replicated to improve 1109b50d902SRodney W. Grimes * performance. 1119b50d902SRodney W. Grimes */ 1129b50d902SRodney W. Grimes void 113bd2bfb58SJuli Mallett pbstr(const char *s) 1149b50d902SRodney W. Grimes { 115acc9d408SJuli Mallett size_t n; 1169b50d902SRodney W. Grimes 117acc9d408SJuli Mallett n = strlen(s); 118ccc5b4e6SJuli Mallett while ((size_t)(endpbb - bp) <= n) 119acc9d408SJuli Mallett enlarge_bufspace(); 120acc9d408SJuli Mallett while (n > 0) 121acc9d408SJuli Mallett *bp++ = s[--n]; 1229b50d902SRodney W. Grimes } 1239b50d902SRodney W. Grimes 1249b50d902SRodney W. Grimes /* 1259b50d902SRodney W. Grimes * pbnum - convert number to string, push back on input. 1269b50d902SRodney W. Grimes */ 1279b50d902SRodney W. Grimes void 128bd2bfb58SJuli Mallett pbnum(int n) 1299b50d902SRodney W. Grimes { 130acc9d408SJuli Mallett int num; 1319b50d902SRodney W. Grimes 1329b50d902SRodney W. Grimes num = (n < 0) ? -n : n; 1339b50d902SRodney W. Grimes do { 1349b50d902SRodney W. Grimes putback(num % 10 + '0'); 1359b50d902SRodney W. Grimes } 1369b50d902SRodney W. Grimes while ((num /= 10) > 0); 1379b50d902SRodney W. Grimes 1389b50d902SRodney W. Grimes if (n < 0) 1399b50d902SRodney W. Grimes putback('-'); 1409b50d902SRodney W. Grimes } 1419b50d902SRodney W. Grimes 1429b50d902SRodney W. Grimes /* 143acc9d408SJuli Mallett * pbunsigned - convert unsigned long to string, push back on input. 144acc9d408SJuli Mallett */ 145acc9d408SJuli Mallett void 146bd2bfb58SJuli Mallett pbunsigned(unsigned long n) 147acc9d408SJuli Mallett { 148acc9d408SJuli Mallett do { 149acc9d408SJuli Mallett putback(n % 10 + '0'); 150acc9d408SJuli Mallett } 151acc9d408SJuli Mallett while ((n /= 10) > 0); 152acc9d408SJuli Mallett } 153acc9d408SJuli Mallett 154acc9d408SJuli Mallett void 155d1fea89cSJuli Mallett initspaces(void) 156acc9d408SJuli Mallett { 157acc9d408SJuli Mallett int i; 158acc9d408SJuli Mallett 159acc9d408SJuli Mallett strspace = xalloc(strsize+1); 160acc9d408SJuli Mallett ep = strspace; 161acc9d408SJuli Mallett endest = strspace+strsize; 162acc9d408SJuli Mallett buf = (char *)xalloc(bufsize); 163acc9d408SJuli Mallett bufbase = buf; 164acc9d408SJuli Mallett bp = buf; 165acc9d408SJuli Mallett endpbb = buf + bufsize; 166acc9d408SJuli Mallett for (i = 0; i < MAXINP; i++) 167acc9d408SJuli Mallett bbase[i] = buf; 168acc9d408SJuli Mallett } 169acc9d408SJuli Mallett 170acc9d408SJuli Mallett void 171d1fea89cSJuli Mallett enlarge_strspace(void) 172acc9d408SJuli Mallett { 173acc9d408SJuli Mallett char *newstrspace; 174acc9d408SJuli Mallett int i; 175acc9d408SJuli Mallett 176acc9d408SJuli Mallett strsize *= 2; 177acc9d408SJuli Mallett newstrspace = malloc(strsize + 1); 178acc9d408SJuli Mallett if (!newstrspace) 179acc9d408SJuli Mallett errx(1, "string space overflow"); 180acc9d408SJuli Mallett memcpy(newstrspace, strspace, strsize/2); 181acc9d408SJuli Mallett for (i = 0; i <= sp; i++) 182acc9d408SJuli Mallett if (sstack[i]) 183acc9d408SJuli Mallett mstack[i].sstr = (mstack[i].sstr - strspace) 184acc9d408SJuli Mallett + newstrspace; 185acc9d408SJuli Mallett ep = (ep-strspace) + newstrspace; 186acc9d408SJuli Mallett free(strspace); 187acc9d408SJuli Mallett strspace = newstrspace; 188acc9d408SJuli Mallett endest = strspace + strsize; 189acc9d408SJuli Mallett } 190acc9d408SJuli Mallett 191acc9d408SJuli Mallett void 192d1fea89cSJuli Mallett enlarge_bufspace(void) 193acc9d408SJuli Mallett { 194acc9d408SJuli Mallett char *newbuf; 195acc9d408SJuli Mallett int i; 196acc9d408SJuli Mallett 197acc9d408SJuli Mallett bufsize *= 2; 198acc9d408SJuli Mallett newbuf = realloc(buf, bufsize); 199acc9d408SJuli Mallett if (!newbuf) 200acc9d408SJuli Mallett errx(1, "too many characters pushed back"); 201acc9d408SJuli Mallett for (i = 0; i < MAXINP; i++) 202acc9d408SJuli Mallett bbase[i] = (bbase[i]-buf)+newbuf; 203acc9d408SJuli Mallett bp = (bp-buf)+newbuf; 204acc9d408SJuli Mallett bufbase = (bufbase-buf)+newbuf; 205acc9d408SJuli Mallett buf = newbuf; 206acc9d408SJuli Mallett endpbb = buf+bufsize; 207acc9d408SJuli Mallett } 208acc9d408SJuli Mallett 209acc9d408SJuli Mallett /* 2109b50d902SRodney W. Grimes * chrsave - put single char on string space 2119b50d902SRodney W. Grimes */ 2129b50d902SRodney W. Grimes void 213bd2bfb58SJuli Mallett chrsave(int c) 2149b50d902SRodney W. Grimes { 215acc9d408SJuli Mallett if (ep >= endest) 216acc9d408SJuli Mallett enlarge_strspace(); 2179b50d902SRodney W. Grimes *ep++ = c; 2189b50d902SRodney W. Grimes } 2199b50d902SRodney W. Grimes 2209b50d902SRodney W. Grimes /* 2219b50d902SRodney W. Grimes * read in a diversion file, and dispose it. 2229b50d902SRodney W. Grimes */ 2239b50d902SRodney W. Grimes void 224bd2bfb58SJuli Mallett getdiv(int n) 2259b50d902SRodney W. Grimes { 226acc9d408SJuli Mallett int c; 2279b50d902SRodney W. Grimes 2289b50d902SRodney W. Grimes if (active == outfile[n]) 22995105358SPhilippe Charnier errx(1, "undivert: diversion still active"); 230acc9d408SJuli Mallett rewind(outfile[n]); 231acc9d408SJuli Mallett while ((c = getc(outfile[n])) != EOF) 232acc9d408SJuli Mallett putc(c, active); 2339b50d902SRodney W. Grimes (void) fclose(outfile[n]); 2349b50d902SRodney W. Grimes outfile[n] = NULL; 2359b50d902SRodney W. Grimes } 2369b50d902SRodney W. Grimes 2379b50d902SRodney W. Grimes void 238bd2bfb58SJuli Mallett onintr(int signo __unused) 2399b50d902SRodney W. Grimes { 240acc9d408SJuli Mallett #define intrmessage "m4: interrupted.\n" 241acc9d408SJuli Mallett write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1); 242acc9d408SJuli Mallett _exit(1); 2439b50d902SRodney W. Grimes } 2449b50d902SRodney W. Grimes 2459b50d902SRodney W. Grimes /* 2469b50d902SRodney W. Grimes * killdiv - get rid of the diversion files 2479b50d902SRodney W. Grimes */ 2489b50d902SRodney W. Grimes void 249d1fea89cSJuli Mallett killdiv(void) 2509b50d902SRodney W. Grimes { 251acc9d408SJuli Mallett int n; 2529b50d902SRodney W. Grimes 253acc9d408SJuli Mallett for (n = 0; n < maxout; n++) 2549b50d902SRodney W. Grimes if (outfile[n] != NULL) { 2559b50d902SRodney W. Grimes (void) fclose(outfile[n]); 2569b50d902SRodney W. Grimes } 2579b50d902SRodney W. Grimes } 2589b50d902SRodney W. Grimes 259acc9d408SJuli Mallett /* 260acc9d408SJuli Mallett * resizedivs: allocate more diversion files */ 2619b50d902SRodney W. Grimes void 262bd2bfb58SJuli Mallett resizedivs(int n) 263164c01f0SGregory Neil Shapiro { 264acc9d408SJuli Mallett int i; 265acc9d408SJuli Mallett 266acc9d408SJuli Mallett outfile = (FILE **)realloc(outfile, sizeof(FILE *) * n); 267acc9d408SJuli Mallett if (outfile == NULL) 268acc9d408SJuli Mallett errx(1, "too many diverts %d", n); 269acc9d408SJuli Mallett for (i = maxout; i < n; i++) 270acc9d408SJuli Mallett outfile[i] = NULL; 271acc9d408SJuli Mallett maxout = n; 272164c01f0SGregory Neil Shapiro } 273acc9d408SJuli Mallett 274acc9d408SJuli Mallett void * 275bd2bfb58SJuli Mallett xalloc(size_t n) 276acc9d408SJuli Mallett { 277acc9d408SJuli Mallett char *p = malloc(n); 278acc9d408SJuli Mallett 279acc9d408SJuli Mallett if (p == NULL) 280acc9d408SJuli Mallett err(1, "malloc"); 281acc9d408SJuli Mallett return p; 282acc9d408SJuli Mallett } 283acc9d408SJuli Mallett 284acc9d408SJuli Mallett char * 285bd2bfb58SJuli Mallett xstrdup(const char *s) 286acc9d408SJuli Mallett { 287acc9d408SJuli Mallett char *p = strdup(s); 288acc9d408SJuli Mallett if (p == NULL) 289acc9d408SJuli Mallett err(1, "strdup"); 290acc9d408SJuli Mallett return p; 291164c01f0SGregory Neil Shapiro } 292164c01f0SGregory Neil Shapiro 293164c01f0SGregory Neil Shapiro void 294d1fea89cSJuli Mallett usage(void) 2959b50d902SRodney W. Grimes { 296b1ea3d46SJuli Mallett fprintf(stderr, 297acc9d408SJuli Mallett "usage: m4 [-d flags] [-t name] [-gs] [-D name[=value]]...\n" 298acc9d408SJuli Mallett " [-U name]... [-I dirname]... file...\n"); 2999b50d902SRodney W. Grimes exit(1); 3009b50d902SRodney W. Grimes } 301acc9d408SJuli Mallett 302acc9d408SJuli Mallett int 303bd2bfb58SJuli Mallett obtain_char(struct input_file *f) 304acc9d408SJuli Mallett { 305acc9d408SJuli Mallett if (f->c == EOF) 306acc9d408SJuli Mallett return EOF; 307acc9d408SJuli Mallett else if (f->c == '\n') 308acc9d408SJuli Mallett f->lineno++; 309acc9d408SJuli Mallett 310acc9d408SJuli Mallett f->c = fgetc(f->file); 311acc9d408SJuli Mallett return f->c; 312acc9d408SJuli Mallett } 313acc9d408SJuli Mallett 314acc9d408SJuli Mallett void 315bd2bfb58SJuli Mallett set_input(struct input_file *f, FILE *real, const char *name) 316acc9d408SJuli Mallett { 317acc9d408SJuli Mallett f->file = real; 318acc9d408SJuli Mallett f->lineno = 1; 319acc9d408SJuli Mallett f->c = 0; 320acc9d408SJuli Mallett f->name = xstrdup(name); 321acc9d408SJuli Mallett } 322acc9d408SJuli Mallett 323acc9d408SJuli Mallett void 324bd2bfb58SJuli Mallett release_input(struct input_file *f) 325acc9d408SJuli Mallett { 326acc9d408SJuli Mallett if (f->file != stdin) 327acc9d408SJuli Mallett fclose(f->file); 328acc9d408SJuli Mallett f->c = EOF; 329acc9d408SJuli Mallett /* 330acc9d408SJuli Mallett * XXX can't free filename, as there might still be 331acc9d408SJuli Mallett * error information pointing to it. 332acc9d408SJuli Mallett */ 333acc9d408SJuli Mallett } 334acc9d408SJuli Mallett 335acc9d408SJuli Mallett void 336bd2bfb58SJuli Mallett doprintlineno(struct input_file *f) 337acc9d408SJuli Mallett { 338acc9d408SJuli Mallett pbunsigned(f->lineno); 339acc9d408SJuli Mallett } 340acc9d408SJuli Mallett 341acc9d408SJuli Mallett void 342bd2bfb58SJuli Mallett doprintfilename(struct input_file *f) 343acc9d408SJuli Mallett { 344acc9d408SJuli Mallett pbstr(rquote); 345acc9d408SJuli Mallett pbstr(f->name); 346acc9d408SJuli Mallett pbstr(lquote); 347acc9d408SJuli Mallett } 348acc9d408SJuli Mallett 349acc9d408SJuli Mallett /* 350acc9d408SJuli Mallett * buffer_mark/dump_buffer: allows one to save a mark in a buffer, 351acc9d408SJuli Mallett * and later dump everything that was added since then to a file. 352acc9d408SJuli Mallett */ 353acc9d408SJuli Mallett size_t 354d1fea89cSJuli Mallett buffer_mark(void) 355acc9d408SJuli Mallett { 356acc9d408SJuli Mallett return bp - buf; 357acc9d408SJuli Mallett } 358acc9d408SJuli Mallett 359acc9d408SJuli Mallett 360acc9d408SJuli Mallett void 361bd2bfb58SJuli Mallett dump_buffer(FILE *f, size_t m) 362acc9d408SJuli Mallett { 363acc9d408SJuli Mallett char *s; 364acc9d408SJuli Mallett 365ccc5b4e6SJuli Mallett for (s = bp; s - buf > (int)m;) 366acc9d408SJuli Mallett fputc(*--s, f); 367acc9d408SJuli Mallett } 368