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