1 /* $NetBSD: misc.c,v 1.15 2002/01/31 19:36:47 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 #if defined(__RCSID) && !defined(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.15 2002/01/31 19:36:47 tv Exp $"); 46 #endif 47 #endif /* not lint */ 48 49 #include <sys/types.h> 50 #include <errno.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <stddef.h> 54 #include <string.h> 55 #include "mdef.h" 56 #include "stdd.h" 57 #include "extern.h" 58 #include "pathnames.h" 59 60 char *ep; /* first free char in strspace */ 61 static char *strspace; /* string space for evaluation */ 62 char *endest; /* end of string space */ 63 static size_t strsize = STRSPMAX; 64 static size_t bufsize = BUFSIZE; 65 66 char *buf; /* push-back buffer */ 67 char *bufbase; /* the base for current ilevel */ 68 char *bbase[MAXINP]; /* the base for each ilevel */ 69 char *bp; /* first available character */ 70 char *endpbb; /* end of push-back buffer */ 71 72 73 /* 74 * find the index of second str in the first str. 75 */ 76 ptrdiff_t 77 indx(s1, s2) 78 const char *s1; 79 const char *s2; 80 { 81 char *t; 82 83 t = strstr(s1, s2); 84 if (t == NULL) 85 return (-1); 86 return (t - s1); 87 } 88 89 /* 90 * putback - push character back onto input 91 */ 92 void 93 putback(c) 94 int c; 95 { 96 if (c == EOF) 97 return; 98 if (bp >= endpbb) 99 enlarge_bufspace(); 100 *bp++ = c; 101 } 102 103 /* 104 * pbstr - push string back onto input 105 * putback is replicated to improve 106 * performance. 107 */ 108 void 109 pbstr(s) 110 const char *s; 111 { 112 size_t n; 113 114 n = strlen(s); 115 while (endpbb - bp <= n) 116 enlarge_bufspace(); 117 while (n > 0) 118 *bp++ = s[--n]; 119 } 120 121 /* 122 * pbnum - convert number to string, push back on input. 123 */ 124 void 125 pbnum(n) 126 int n; 127 { 128 int num; 129 130 num = (n < 0) ? -n : n; 131 do { 132 putback(num % 10 + '0'); 133 } 134 while ((num /= 10) > 0); 135 136 if (n < 0) 137 putback('-'); 138 } 139 140 /* 141 * pbunsigned - convert unsigned long to string, push back on input. 142 */ 143 void 144 pbunsigned(n) 145 unsigned long n; 146 { 147 do { 148 putback(n % 10 + '0'); 149 } 150 while ((n /= 10) > 0); 151 } 152 153 void 154 initspaces() 155 { 156 int i; 157 158 strspace = xalloc(strsize+1); 159 ep = strspace; 160 endest = strspace+strsize; 161 buf = (char *)xalloc(bufsize); 162 bufbase = buf; 163 bp = buf; 164 endpbb = buf + bufsize; 165 for (i = 0; i < MAXINP; i++) 166 bbase[i] = buf; 167 } 168 169 void 170 enlarge_strspace() 171 { 172 char *newstrspace; 173 int i; 174 175 strsize *= 2; 176 newstrspace = malloc(strsize + 1); 177 if (!newstrspace) 178 errx(1, "string space overflow"); 179 memcpy(newstrspace, strspace, strsize/2); 180 for (i = 0; i <= sp; i++) 181 if (sstack[i]) 182 mstack[i].sstr = (mstack[i].sstr - strspace) 183 + newstrspace; 184 ep = (ep-strspace) + newstrspace; 185 free(strspace); 186 strspace = newstrspace; 187 endest = strspace + strsize; 188 } 189 190 void 191 enlarge_bufspace() 192 { 193 char *newbuf; 194 int i; 195 196 bufsize *= 2; 197 newbuf = realloc(buf, bufsize); 198 if (!newbuf) 199 errx(1, "too many characters pushed back"); 200 for (i = 0; i < MAXINP; i++) 201 bbase[i] = (bbase[i]-buf)+newbuf; 202 bp = (bp-buf)+newbuf; 203 bufbase = (bufbase-buf)+newbuf; 204 buf = newbuf; 205 endpbb = buf+bufsize; 206 } 207 208 /* 209 * chrsave - put single char on string space 210 */ 211 void 212 chrsave(c) 213 int c; 214 { 215 if (ep >= endest) 216 enlarge_strspace(); 217 *ep++ = c; 218 } 219 220 /* 221 * read in a diversion file, and dispose it. 222 */ 223 void 224 getdiv(n) 225 int n; 226 { 227 int c; 228 229 if (active == outfile[n]) 230 errx(1, "undivert: diversion still active"); 231 rewind(outfile[n]); 232 while ((c = getc(outfile[n])) != EOF) 233 putc(c, active); 234 (void) fclose(outfile[n]); 235 outfile[n] = NULL; 236 } 237 238 void 239 onintr(signo) 240 int signo; 241 { 242 #define intrmessage "m4: interrupted.\n" 243 write(STDERR_FILENO, intrmessage, sizeof(intrmessage)); 244 _exit(1); 245 } 246 247 /* 248 * killdiv - get rid of the diversion files 249 */ 250 void 251 killdiv() 252 { 253 int n; 254 255 for (n = 0; n < maxout; n++) 256 if (outfile[n] != NULL) { 257 (void) fclose(outfile[n]); 258 } 259 } 260 261 /* 262 * resizedivs: allocate more diversion files */ 263 void 264 resizedivs(n) 265 int n; 266 { 267 int i; 268 269 outfile = (FILE **)realloc(outfile, sizeof(FILE *) * n); 270 if (outfile == NULL) 271 errx(1, "too many diverts %d", n); 272 for (i = maxout; i < n; i++) 273 outfile[i] = NULL; 274 maxout = n; 275 } 276 277 void * 278 xalloc(n) 279 size_t n; 280 { 281 char *p = malloc(n); 282 283 if (p == NULL) 284 err(1, "malloc"); 285 return p; 286 } 287 288 char * 289 xstrdup(s) 290 const char *s; 291 { 292 char *p = strdup(s); 293 if (p == NULL) 294 err(1, "strdup"); 295 return p; 296 } 297 298 void 299 usage(progname) 300 const char *progname; 301 { 302 fprintf(stderr, "usage: %s [-Pg] [-Dname[=val]] [-I dirname] [-Uname]\n", progname); 303 fprintf(stderr, "\t[-d flags] [-o trfile] [-t macro]\n"); 304 exit(1); 305 } 306 307 int 308 obtain_char(f) 309 struct input_file *f; 310 { 311 if (f->c == EOF) 312 return EOF; 313 else if (f->c == '\n') 314 f->lineno++; 315 316 f->c = fgetc(f->file); 317 return f->c; 318 } 319 320 void 321 set_input(f, real, name) 322 struct input_file *f; 323 FILE *real; 324 const char *name; 325 { 326 f->file = real; 327 f->lineno = 1; 328 f->c = 0; 329 f->name = xstrdup(name); 330 } 331 332 void 333 release_input(f) 334 struct input_file *f; 335 { 336 if (f->file != stdin) 337 fclose(f->file); 338 f->c = EOF; 339 /* 340 * XXX can't free filename, as there might still be 341 * error information pointing to it. 342 */ 343 } 344 345 void 346 doprintlineno(f) 347 struct input_file *f; 348 { 349 pbunsigned(f->lineno); 350 } 351 352 void 353 doprintfilename(f) 354 struct input_file *f; 355 { 356 pbstr(rquote); 357 pbstr(f->name); 358 pbstr(lquote); 359 } 360 361 /* 362 * buffer_mark/dump_buffer: allows one to save a mark in a buffer, 363 * and later dump everything that was added since then to a file. 364 */ 365 size_t 366 buffer_mark() 367 { 368 return bp - buf; 369 } 370 371 372 void 373 dump_buffer(f, m) 374 FILE *f; 375 size_t m; 376 { 377 char *s; 378 379 for (s = bp; s-buf > m;) 380 fputc(*--s, f); 381 } 382