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