1 /* $OpenBSD: misc.c,v 1.26 2001/11/16 23:50:40 deraadt Exp $ */ 2 /* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls 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 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93"; 43 #else 44 static char rcsid[] = "$OpenBSD: misc.c,v 1.26 2001/11/16 23:50:40 deraadt Exp $"; 45 #endif 46 #endif /* not lint */ 47 48 #include <sys/types.h> 49 #include <errno.h> 50 #include <unistd.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <stddef.h> 54 #include <string.h> 55 #include <err.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 else 89 return (t - s1); 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)-1); 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() 302 { 303 fprintf(stderr, "usage: m4 [-Dname[=val]] [-Uname] [-I dirname...]\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