1 /* $OpenBSD: misc.c,v 1.21 2001/07/18 16:18:17 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 static char rcsid[] = "$OpenBSD: misc.c,v 1.21 2001/07/18 16:18:17 espie 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 static 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 static char *endpbb; /* end of push-back buffer */ 73 74 75 static void enlarge_bufspace __P((void)); 76 static void enlarge_strspace __P((void)); 77 /* 78 * find the index of second str in the first str. 79 */ 80 ptrdiff_t 81 indx(s1, s2) 82 const char *s1; 83 const char *s2; 84 { 85 char *t; 86 87 t = strstr(s1, s2); 88 if (t == NULL) 89 return (-1); 90 else 91 return (t - s1); 92 } 93 /* 94 * putback - push character back onto input 95 */ 96 void 97 putback(c) 98 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(s) 114 const char *s; 115 { 116 size_t n; 117 118 n = strlen(s); 119 while (endpbb - bp <= n) 120 enlarge_bufspace(); 121 while (n > 0) 122 *bp++ = s[--n]; 123 } 124 125 /* 126 * pbnum - convert number to string, push back on input. 127 */ 128 void 129 pbnum(n) 130 int n; 131 { 132 int num; 133 134 num = (n < 0) ? -n : n; 135 do { 136 putback(num % 10 + '0'); 137 } 138 while ((num /= 10) > 0); 139 140 if (n < 0) 141 putback('-'); 142 } 143 144 /* 145 * pbunsigned - convert unsigned long to string, push back on input. 146 */ 147 void 148 pbunsigned(n) 149 unsigned long n; 150 { 151 do { 152 putback(n % 10 + '0'); 153 } 154 while ((n /= 10) > 0); 155 } 156 157 void 158 initspaces() 159 { 160 int i; 161 162 strspace = xalloc(strsize+1); 163 ep = strspace; 164 endest = strspace+strsize; 165 buf = (char *)xalloc(bufsize); 166 bufbase = buf; 167 bp = buf; 168 endpbb = buf + bufsize; 169 for (i = 0; i < MAXINP; i++) 170 bbase[i] = buf; 171 } 172 173 static void 174 enlarge_strspace() 175 { 176 char *newstrspace; 177 int i; 178 179 strsize *= 2; 180 newstrspace = malloc(strsize + 1); 181 if (!newstrspace) 182 errx(1, "string space overflow"); 183 memcpy(newstrspace, strspace, strsize/2); 184 for (i = 0; i <= sp; i++) 185 if (sstack[i]) 186 mstack[i].sstr = (mstack[i].sstr - strspace) 187 + newstrspace; 188 ep = (ep-strspace) + newstrspace; 189 free(strspace); 190 strspace = newstrspace; 191 endest = strspace + strsize; 192 } 193 194 static void 195 enlarge_bufspace() 196 { 197 char *newbuf; 198 int i; 199 200 bufsize *= 2; 201 newbuf = realloc(buf, bufsize); 202 if (!newbuf) 203 errx(1, "too many characters pushed back"); 204 for (i = 0; i < MAXINP; i++) 205 bbase[i] = (bbase[i]-buf)+newbuf; 206 bp = (bp-buf)+newbuf; 207 bufbase = (bufbase-buf)+newbuf; 208 buf = newbuf; 209 endpbb = buf+bufsize; 210 } 211 212 /* 213 * chrsave - put single char on string space 214 */ 215 void 216 chrsave(c) 217 int c; 218 { 219 if (ep >= endest) 220 enlarge_strspace(); 221 *ep++ = c; 222 } 223 224 /* 225 * read in a diversion file, and dispose it. 226 */ 227 void 228 getdiv(n) 229 int n; 230 { 231 int c; 232 233 if (active == outfile[n]) 234 errx(1, "undivert: diversion still active"); 235 rewind(outfile[n]); 236 while ((c = getc(outfile[n])) != EOF) 237 putc(c, active); 238 (void) fclose(outfile[n]); 239 outfile[n] = NULL; 240 } 241 242 void 243 onintr(signo) 244 int signo; 245 { 246 #define intrmessage "m4: interrupted.\n" 247 write(STDERR_FILENO, intrmessage, sizeof(intrmessage)); 248 _exit(1); 249 } 250 251 /* 252 * killdiv - get rid of the diversion files 253 */ 254 void 255 killdiv() 256 { 257 int n; 258 259 for (n = 0; n < maxout; n++) 260 if (outfile[n] != NULL) { 261 (void) fclose(outfile[n]); 262 } 263 } 264 265 /* 266 * resizedivs: allocate more diversion files */ 267 void 268 resizedivs(n) 269 int n; 270 { 271 int i; 272 273 outfile = (FILE **)realloc(outfile, sizeof(FILE *) * n); 274 if (outfile == NULL) 275 errx(1, "too many diverts %d", n); 276 for (i = maxout; i < n; i++) 277 outfile[i] = NULL; 278 maxout = n; 279 } 280 281 void * 282 xalloc(n) 283 size_t n; 284 { 285 char *p = malloc(n); 286 287 if (p == NULL) 288 err(1, "malloc"); 289 return p; 290 } 291 292 char * 293 xstrdup(s) 294 const char *s; 295 { 296 char *p = strdup(s); 297 if (p == NULL) 298 err(1, "strdup"); 299 return p; 300 } 301 302 void 303 usage() 304 { 305 fprintf(stderr, "usage: m4 [-Dname[=val]] [-Uname] [-I dirname...]\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(f->name); 359 } 360