1 /* $NetBSD: misc.c,v 1.18 2007/10/05 07:36:45 lukem 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 #if HAVE_NBTOOL_CONFIG_H 37 #include "nbtool_config.h" 38 #endif 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.18 2007/10/05 07:36:45 lukem 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 <util.h> 56 #include "mdef.h" 57 #include "stdd.h" 58 #include "extern.h" 59 #include "pathnames.h" 60 61 char *ep; /* first free char in strspace */ 62 static char *strspace; /* string space for evaluation */ 63 char *endest; /* end of string space */ 64 static size_t strsize = STRSPMAX; 65 static size_t bufsize = BUFSIZE; 66 67 char *buf; /* push-back buffer */ 68 char *bufbase; /* the base for current ilevel */ 69 char *bbase[MAXINP]; /* the base for each ilevel */ 70 char *bp; /* first available character */ 71 char *endpbb; /* end of push-back buffer */ 72 73 74 /* 75 * find the index of second str in the first str. 76 */ 77 ptrdiff_t 78 indx(s1, s2) 79 const char *s1; 80 const char *s2; 81 { 82 char *t; 83 84 t = strstr(s1, s2); 85 if (t == NULL) 86 return (-1); 87 return (t - s1); 88 } 89 90 /* 91 * putback - push character back onto input 92 */ 93 void 94 putback(c) 95 int c; 96 { 97 if (c == EOF) 98 return; 99 if (bp >= endpbb) 100 enlarge_bufspace(); 101 *bp++ = c; 102 } 103 104 /* 105 * pbstr - push string back onto input 106 * putback is replicated to improve 107 * performance. 108 */ 109 void 110 pbstr(s) 111 const char *s; 112 { 113 size_t n; 114 115 n = strlen(s); 116 while (endpbb - bp <= n) 117 enlarge_bufspace(); 118 while (n > 0) 119 *bp++ = s[--n]; 120 } 121 122 /* 123 * pbnum - convert number to string, push back on input. 124 */ 125 void 126 pbnum(n) 127 int n; 128 { 129 int num; 130 131 num = (n < 0) ? -n : n; 132 do { 133 putback(num % 10 + '0'); 134 } 135 while ((num /= 10) > 0); 136 137 if (n < 0) 138 putback('-'); 139 } 140 141 /* 142 * pbunsigned - convert unsigned long to string, push back on input. 143 */ 144 void 145 pbunsigned(n) 146 unsigned long n; 147 { 148 do { 149 putback(n % 10 + '0'); 150 } 151 while ((n /= 10) > 0); 152 } 153 154 void 155 initspaces() 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() 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() 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(c) 214 int c; 215 { 216 if (ep >= endest) 217 enlarge_strspace(); 218 *ep++ = c; 219 } 220 221 /* 222 * read in a diversion file, and dispose it. 223 */ 224 void 225 getdiv(n) 226 int n; 227 { 228 int c; 229 230 if (active == outfile[n]) 231 errx(1, "undivert: diversion still active"); 232 rewind(outfile[n]); 233 while ((c = getc(outfile[n])) != EOF) 234 putc(c, active); 235 (void) fclose(outfile[n]); 236 outfile[n] = NULL; 237 } 238 239 void 240 onintr(signo) 241 int signo; 242 { 243 #define intrmessage "m4: interrupted.\n" 244 write(STDERR_FILENO, intrmessage, sizeof(intrmessage)); 245 (void)raise_default_signal(signo); 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