Home | History | Annotate | Line # | Download | only in m4
misc.c revision 1.23
      1  1.19  christos /*	$OpenBSD: misc.c,v 1.41 2009/10/14 17:19:47 sthen Exp $	*/
      2  1.23      matt /*	$NetBSD: misc.c,v 1.23 2012/03/20 20:34:58 matt 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.17       jmc #if HAVE_NBTOOL_CONFIG_H
     36  1.17       jmc #include "nbtool_config.h"
     37  1.17       jmc #endif
     38   1.7     lukem #include <sys/cdefs.h>
     39  1.23      matt __RCSID("$NetBSD: misc.c,v 1.23 2012/03/20 20:34:58 matt Exp $");
     40   1.5     glass #include <sys/types.h>
     41   1.5     glass #include <errno.h>
     42  1.19  christos #include <unistd.h>
     43  1.19  christos #include <stdarg.h>
     44   1.5     glass #include <stdio.h>
     45   1.5     glass #include <stdlib.h>
     46  1.12        tv #include <stddef.h>
     47   1.5     glass #include <string.h>
     48  1.19  christos #include <err.h>
     49   1.1       cgd #include "mdef.h"
     50   1.5     glass #include "stdd.h"
     51   1.5     glass #include "extern.h"
     52   1.5     glass #include "pathnames.h"
     53  1.12        tv 
     54  1.19  christos 
     55  1.12        tv char *ep;		/* first free char in strspace */
     56  1.12        tv static char *strspace;	/* string space for evaluation */
     57  1.12        tv char *endest;		/* end of string space	       */
     58  1.12        tv static size_t strsize = STRSPMAX;
     59  1.12        tv static size_t bufsize = BUFSIZE;
     60  1.12        tv 
     61  1.19  christos unsigned char *buf;			/* push-back buffer	       */
     62  1.19  christos unsigned char *bufbase;			/* the base for current ilevel */
     63  1.19  christos unsigned char *bbase[MAXINP];		/* the base for each ilevel    */
     64  1.19  christos unsigned char *bp; 			/* first available character   */
     65  1.19  christos unsigned char *endpbb;			/* end of push-back buffer     */
     66  1.12        tv 
     67  1.12        tv 
     68   1.5     glass /*
     69   1.5     glass  * find the index of second str in the first str.
     70   1.5     glass  */
     71  1.12        tv ptrdiff_t
     72  1.19  christos indx(const char *s1, const char *s2)
     73   1.5     glass {
     74   1.7     lukem 	char *t;
     75   1.7     lukem 
     76   1.7     lukem 	t = strstr(s1, s2);
     77   1.7     lukem 	if (t == NULL)
     78   1.7     lukem 		return (-1);
     79  1.19  christos 	else
     80  1.19  christos 		return (t - s1);
     81   1.5     glass }
     82   1.5     glass /*
     83  1.19  christos  *  pushback - push character back onto input
     84   1.5     glass  */
     85   1.5     glass void
     86  1.19  christos pushback(int c)
     87   1.5     glass {
     88  1.12        tv 	if (c == EOF)
     89  1.12        tv 		return;
     90  1.12        tv 	if (bp >= endpbb)
     91  1.12        tv 		enlarge_bufspace();
     92  1.12        tv 	*bp++ = c;
     93   1.9       cgd }
     94   1.9       cgd 
     95   1.9       cgd /*
     96   1.5     glass  *  pbstr - push string back onto input
     97  1.19  christos  *          pushback is replicated to improve
     98   1.5     glass  *          performance.
     99   1.5     glass  */
    100   1.5     glass void
    101  1.19  christos pbstr(const char *s)
    102   1.5     glass {
    103  1.12        tv 	size_t n;
    104   1.2     glass 
    105  1.12        tv 	n = strlen(s);
    106  1.19  christos 	while ((size_t)(endpbb - bp) <= n)
    107  1.12        tv 		enlarge_bufspace();
    108  1.12        tv 	while (n > 0)
    109  1.12        tv 		*bp++ = s[--n];
    110   1.5     glass }
    111   1.5     glass 
    112   1.5     glass /*
    113   1.5     glass  *  pbnum - convert number to string, push back on input.
    114   1.5     glass  */
    115   1.5     glass void
    116  1.19  christos pbnum(int n)
    117  1.19  christos {
    118  1.19  christos 	pbnumbase(n, 10, 0);
    119  1.19  christos }
    120  1.19  christos 
    121  1.19  christos void
    122  1.19  christos pbnumbase(int n, int base, int d)
    123   1.5     glass {
    124  1.19  christos 	static char digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
    125   1.7     lukem 	int num;
    126  1.19  christos 	int printed = 0;
    127  1.19  christos 
    128  1.19  christos 	if (base > 36)
    129  1.19  christos 		m4errx(1, "base %d > 36: not supported.", base);
    130  1.19  christos 
    131  1.19  christos 	if (base < 2)
    132  1.19  christos 		m4errx(1, "bad base %d for conversion.", base);
    133   1.2     glass 
    134   1.5     glass 	num = (n < 0) ? -n : n;
    135   1.2     glass 	do {
    136  1.19  christos 		pushback(digits[num % base]);
    137  1.19  christos 		printed++;
    138   1.2     glass 	}
    139  1.19  christos 	while ((num /= base) > 0);
    140   1.2     glass 
    141   1.5     glass 	if (n < 0)
    142  1.19  christos 		printed++;
    143  1.19  christos 	while (printed++ < d)
    144  1.19  christos 		pushback('0');
    145  1.19  christos 
    146  1.19  christos 	if (n < 0)
    147  1.19  christos 		pushback('-');
    148   1.5     glass }
    149   1.5     glass 
    150   1.5     glass /*
    151  1.12        tv  *  pbunsigned - convert unsigned long to string, push back on input.
    152  1.12        tv  */
    153  1.12        tv void
    154  1.19  christos pbunsigned(unsigned long n)
    155  1.12        tv {
    156  1.12        tv 	do {
    157  1.19  christos 		pushback(n % 10 + '0');
    158  1.12        tv 	}
    159  1.12        tv 	while ((n /= 10) > 0);
    160  1.12        tv }
    161  1.12        tv 
    162  1.12        tv void
    163  1.23      matt initspaces(void)
    164  1.12        tv {
    165  1.12        tv 	int i;
    166  1.12        tv 
    167  1.19  christos 	strspace = xalloc(strsize+1, NULL);
    168  1.12        tv 	ep = strspace;
    169  1.12        tv 	endest = strspace+strsize;
    170  1.19  christos 	buf = (unsigned char *)xalloc(bufsize, NULL);
    171  1.12        tv 	bufbase = buf;
    172  1.12        tv 	bp = buf;
    173  1.12        tv 	endpbb = buf + bufsize;
    174  1.12        tv 	for (i = 0; i < MAXINP; i++)
    175  1.12        tv 		bbase[i] = buf;
    176  1.12        tv }
    177  1.12        tv 
    178  1.12        tv void
    179  1.23      matt enlarge_strspace(void)
    180  1.12        tv {
    181  1.12        tv 	char *newstrspace;
    182  1.12        tv 	int i;
    183  1.12        tv 
    184  1.12        tv 	strsize *= 2;
    185  1.12        tv 	newstrspace = malloc(strsize + 1);
    186  1.12        tv 	if (!newstrspace)
    187  1.12        tv 		errx(1, "string space overflow");
    188  1.12        tv 	memcpy(newstrspace, strspace, strsize/2);
    189  1.12        tv 	for (i = 0; i <= sp; i++)
    190  1.12        tv 		if (sstack[i])
    191  1.12        tv 			mstack[i].sstr = (mstack[i].sstr - strspace)
    192  1.12        tv 			    + newstrspace;
    193  1.12        tv 	ep = (ep-strspace) + newstrspace;
    194  1.12        tv 	free(strspace);
    195  1.12        tv 	strspace = newstrspace;
    196  1.12        tv 	endest = strspace + strsize;
    197  1.12        tv }
    198  1.12        tv 
    199  1.12        tv void
    200  1.23      matt enlarge_bufspace(void)
    201  1.12        tv {
    202  1.19  christos 	unsigned char *newbuf;
    203  1.12        tv 	int i;
    204  1.12        tv 
    205  1.19  christos 	bufsize += bufsize/2;
    206  1.19  christos 	newbuf = xrealloc(buf, bufsize, "too many characters pushed back");
    207  1.12        tv 	for (i = 0; i < MAXINP; i++)
    208  1.12        tv 		bbase[i] = (bbase[i]-buf)+newbuf;
    209  1.12        tv 	bp = (bp-buf)+newbuf;
    210  1.12        tv 	bufbase = (bufbase-buf)+newbuf;
    211  1.12        tv 	buf = newbuf;
    212  1.12        tv 	endpbb = buf+bufsize;
    213  1.12        tv }
    214  1.12        tv 
    215  1.12        tv /*
    216   1.5     glass  *  chrsave - put single char on string space
    217   1.5     glass  */
    218   1.5     glass void
    219  1.19  christos chrsave(int c)
    220   1.5     glass {
    221  1.12        tv 	if (ep >= endest)
    222  1.12        tv 		enlarge_strspace();
    223  1.12        tv 	*ep++ = c;
    224   1.5     glass }
    225   1.5     glass 
    226   1.5     glass /*
    227   1.5     glass  * read in a diversion file, and dispose it.
    228   1.5     glass  */
    229   1.5     glass void
    230  1.19  christos getdiv(int n)
    231   1.5     glass {
    232   1.7     lukem 	int c;
    233   1.2     glass 
    234   1.5     glass 	if (active == outfile[n])
    235  1.19  christos 		m4errx(1, "undivert: diversion still active.");
    236  1.12        tv 	rewind(outfile[n]);
    237  1.12        tv 	while ((c = getc(outfile[n])) != EOF)
    238  1.12        tv 		putc(c, active);
    239   1.5     glass 	(void) fclose(outfile[n]);
    240   1.5     glass 	outfile[n] = NULL;
    241   1.5     glass }
    242   1.2     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.22     joerg killdiv(void)
    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.19  christos void
    258  1.19  christos m4errx(int exval, const char *fmt, ...)
    259  1.19  christos {
    260  1.20     joerg 	fprintf(stderr, "%s: ", getprogname());
    261  1.19  christos 	fprintf(stderr, "%s at line %lu: ", CURRENT_NAME, CURRENT_LINE);
    262  1.19  christos 	if (fmt != NULL) {
    263  1.19  christos 		va_list ap;
    264  1.19  christos 
    265  1.19  christos 		va_start(ap, fmt);
    266  1.19  christos 		vfprintf(stderr, fmt, ap);
    267  1.19  christos 		va_end(ap);
    268  1.19  christos 	}
    269  1.19  christos 	fprintf(stderr, "\n");
    270  1.19  christos 	exit(exval);
    271  1.19  christos }
    272  1.19  christos 
    273  1.12        tv /*
    274  1.12        tv  * resizedivs: allocate more diversion files */
    275  1.12        tv void
    276  1.19  christos resizedivs(int n)
    277  1.12        tv {
    278  1.12        tv 	int i;
    279  1.12        tv 
    280  1.19  christos 	outfile = (FILE **)xrealloc(outfile, sizeof(FILE *) * n,
    281  1.19  christos 	    "too many diverts %d", n);
    282  1.12        tv 	for (i = maxout; i < n; i++)
    283  1.12        tv 		outfile[i] = NULL;
    284  1.12        tv 	maxout = n;
    285  1.12        tv }
    286  1.12        tv 
    287  1.12        tv void *
    288  1.19  christos xalloc(size_t n, const char *fmt, ...)
    289  1.19  christos {
    290  1.19  christos 	void *p = malloc(n);
    291  1.19  christos 
    292  1.19  christos 	if (p == NULL) {
    293  1.19  christos 		if (fmt == NULL)
    294  1.19  christos 			err(1, "malloc");
    295  1.19  christos 		else {
    296  1.19  christos 			va_list va;
    297  1.19  christos 
    298  1.19  christos 			va_start(va, fmt);
    299  1.19  christos 			verr(1, fmt, va);
    300  1.19  christos 			va_end(va);
    301  1.19  christos 		}
    302  1.19  christos 	}
    303  1.19  christos 	return p;
    304  1.19  christos }
    305  1.19  christos 
    306  1.19  christos void *
    307  1.19  christos xrealloc(void *old, size_t n, const char *fmt, ...)
    308   1.5     glass {
    309  1.19  christos 	char *p = realloc(old, n);
    310   1.2     glass 
    311  1.19  christos 	if (p == NULL) {
    312  1.19  christos 		free(old);
    313  1.19  christos 		if (fmt == NULL)
    314  1.19  christos 			err(1, "realloc");
    315  1.19  christos 		else {
    316  1.19  christos 			va_list va;
    317  1.19  christos 
    318  1.19  christos 			va_start(va, fmt);
    319  1.19  christos 			verr(1, fmt, va);
    320  1.19  christos 			va_end(va);
    321  1.19  christos 	    	}
    322  1.19  christos 	}
    323   1.5     glass 	return p;
    324   1.5     glass }
    325   1.2     glass 
    326   1.5     glass char *
    327  1.19  christos xstrdup(const char *s)
    328   1.5     glass {
    329   1.7     lukem 	char *p = strdup(s);
    330   1.5     glass 	if (p == NULL)
    331   1.7     lukem 		err(1, "strdup");
    332   1.5     glass 	return p;
    333   1.5     glass }
    334   1.2     glass 
    335  1.12        tv int
    336  1.19  christos obtain_char(struct input_file *f)
    337  1.12        tv {
    338  1.12        tv 	if (f->c == EOF)
    339  1.12        tv 		return EOF;
    340  1.19  christos 
    341  1.19  christos 	f->c = fgetc(f->file);
    342  1.19  christos 	if (f->c == '\n')
    343  1.12        tv 		f->lineno++;
    344  1.12        tv 
    345  1.12        tv 	return f->c;
    346  1.12        tv }
    347  1.12        tv 
    348  1.12        tv void
    349  1.19  christos set_input(struct input_file *f, FILE *real, const char *name)
    350  1.12        tv {
    351  1.12        tv 	f->file = real;
    352  1.12        tv 	f->lineno = 1;
    353  1.12        tv 	f->c = 0;
    354  1.12        tv 	f->name = xstrdup(name);
    355  1.19  christos 	emit_synchline();
    356  1.19  christos }
    357  1.19  christos 
    358  1.19  christos void
    359  1.23      matt do_emit_synchline(void)
    360  1.19  christos {
    361  1.19  christos 	fprintf(active, "#line %lu \"%s\"\n",
    362  1.19  christos 	    infile[ilevel].lineno, infile[ilevel].name);
    363  1.19  christos 	infile[ilevel].synch_lineno = infile[ilevel].lineno;
    364  1.12        tv }
    365  1.12        tv 
    366  1.12        tv void
    367  1.19  christos release_input(struct input_file *f)
    368  1.12        tv {
    369  1.12        tv 	if (f->file != stdin)
    370  1.12        tv 	    fclose(f->file);
    371  1.12        tv 	f->c = EOF;
    372  1.12        tv 	/*
    373  1.12        tv 	 * XXX can't free filename, as there might still be
    374  1.12        tv 	 * error information pointing to it.
    375  1.12        tv 	 */
    376  1.12        tv }
    377  1.12        tv 
    378  1.12        tv void
    379  1.19  christos doprintlineno(struct input_file *f)
    380   1.5     glass {
    381  1.21  christos 	pbunsigned(TOKEN_LINE(f));
    382  1.12        tv }
    383   1.2     glass 
    384  1.12        tv void
    385  1.19  christos doprintfilename(struct input_file *f)
    386  1.12        tv {
    387  1.12        tv 	pbstr(rquote);
    388  1.12        tv 	pbstr(f->name);
    389  1.12        tv 	pbstr(lquote);
    390  1.12        tv }
    391   1.2     glass 
    392  1.12        tv /*
    393  1.12        tv  * buffer_mark/dump_buffer: allows one to save a mark in a buffer,
    394  1.12        tv  * and later dump everything that was added since then to a file.
    395  1.12        tv  */
    396  1.12        tv size_t
    397  1.23      matt buffer_mark(void)
    398  1.12        tv {
    399  1.12        tv 	return bp - buf;
    400   1.5     glass }
    401   1.2     glass 
    402  1.12        tv 
    403   1.5     glass void
    404  1.19  christos dump_buffer(FILE *f, size_t m)
    405   1.5     glass {
    406  1.19  christos 	unsigned char *s;
    407  1.12        tv 
    408  1.19  christos 	for (s = bp; (size_t)(s - buf) > m;)
    409  1.12        tv 		fputc(*--s, f);
    410   1.5     glass }
    411