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