Home | History | Annotate | Line # | Download | only in m4
misc.c revision 1.22.2.1
      1      1.19  christos /*	$OpenBSD: misc.c,v 1.41 2009/10/14 17:19:47 sthen Exp $	*/
      2  1.22.2.1      yamt /*	$NetBSD: misc.c,v 1.22.2.1 2012/04/17 00:09:35 yamt 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.22.2.1      yamt __RCSID("$NetBSD: misc.c,v 1.22.2.1 2012/04/17 00:09:35 yamt 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.22.2.1      yamt 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.22.2.1      yamt 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.22.2.1      yamt 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.22.2.1      yamt 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.22.2.1      yamt 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