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