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