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