input.c (11631B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <ctype.h> 5 #include <errno.h> 6 #include "pic.h" 7 #include "y.tab.h" 8 9 Infile infile[10]; 10 Infile *curfile = infile; 11 12 #define MAXSRC 50 13 Src src[MAXSRC]; /* input source stack */ 14 Src *srcp = src; 15 16 void do_thru(void); 17 int nextchar(void); 18 int getarg(char *); 19 void freedef(char *); 20 int baldelim(int, char *); 21 22 void pushsrc(int type, char *ptr) /* new input source */ 23 { 24 if (++srcp >= src + MAXSRC) 25 ERROR "inputs nested too deep" FATAL; 26 srcp->type = type; 27 srcp->sp = ptr; 28 if (dbg > 1) { 29 printf("\n%3d ", (int)(srcp - src)); 30 switch (srcp->type) { 31 case File: 32 printf("push file %s\n", ((Infile *)ptr)->fname); 33 break; 34 case Macro: 35 printf("push macro <%s>\n", ptr); 36 break; 37 case Char: 38 printf("push char <%c>\n", *ptr); 39 break; 40 case Thru: 41 printf("push thru\n"); 42 break; 43 case String: 44 printf("push string <%s>\n", ptr); 45 break; 46 case Free: 47 printf("push free <%s>\n", ptr); 48 break; 49 default: 50 ERROR "pushed bad type %d", srcp->type FATAL; 51 } 52 } 53 } 54 55 void popsrc(void) /* restore an old one */ 56 { 57 if (srcp <= src) 58 ERROR "too many inputs popped" FATAL; 59 if (dbg > 1) { 60 printf("%3d ", (int) (srcp - src)); 61 switch (srcp->type) { 62 case File: 63 printf("pop file\n"); 64 break; 65 case Macro: 66 printf("pop macro\n"); 67 break; 68 case Char: 69 printf("pop char <%c>\n", *srcp->sp); 70 break; 71 case Thru: 72 printf("pop thru\n"); 73 break; 74 case String: 75 printf("pop string\n"); 76 break; 77 case Free: 78 printf("pop free\n"); 79 break; 80 default: 81 ERROR "pop weird input %d", srcp->type FATAL; 82 } 83 } 84 srcp--; 85 } 86 87 void definition(char *s) /* collect definition for s and install */ 88 /* definitions picked up lexically */ 89 { 90 char *p; 91 struct symtab *stp; 92 93 p = delimstr("definition"); 94 stp = lookup(s); 95 if (stp != NULL) { /* it's there before */ 96 if (stp->s_type != DEFNAME) { 97 ERROR "%s used as variable and definition", s WARNING; 98 return; 99 } 100 free(stp->s_val.p); 101 stp->s_val.p = p; 102 } else { 103 YYSTYPE u; 104 u.p = p; 105 makevar(tostring(s), DEFNAME, u); 106 } 107 dprintf("installing %s as `%s'\n", s, p); 108 } 109 110 char *delimstr(char *s) /* get body of X ... X */ 111 /* message if too big */ 112 { 113 int c, delim, rdelim, n, deep; 114 static char *buf = NULL; 115 static int nbuf = 0; 116 char *p; 117 118 if (buf == NULL) 119 buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0])); 120 while ((delim = input()) == ' ' || delim == '\t' || delim == '\n') 121 ; 122 rdelim = baldelim(delim, "{}"); /* could be "(){}[]`'" */ 123 deep = 1; 124 for (p = buf; ; ) { 125 c = input(); 126 if (c == rdelim) 127 if (--deep == 0) 128 break; 129 if (c == delim) 130 deep++; 131 if (p >= buf + nbuf) { 132 n = p - buf; 133 buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0])); 134 p = buf + n; 135 } 136 if (c == EOF) 137 ERROR "end of file in %s %c %.20s... %c", s, delim, buf, delim FATAL; 138 *p++ = c; 139 } 140 *p = '\0'; 141 dprintf("delimstr %s %c <%s> %c\n", s, delim, buf, delim); 142 return tostring(buf); 143 } 144 145 int 146 baldelim(int c, char *s) /* replace c by balancing entry in s */ 147 { 148 for ( ; *s; s += 2) 149 if (*s == c) 150 return s[1]; 151 return c; 152 } 153 154 void undefine(char *s) /* undefine macro */ 155 { 156 while (*s != ' ' && *s != '\t') /* skip "undef..." */ 157 s++; 158 while (*s == ' ' || *s == '\t') 159 s++; 160 freedef(s); 161 } 162 163 164 Arg args[10]; /* argument frames */ 165 Arg *argfp = args; /* frame pointer */ 166 int argcnt; /* number of arguments seen so far */ 167 168 void dodef(struct symtab *stp) /* collect args and switch input to defn */ 169 { 170 int i, len; 171 char *p; 172 Arg *ap; 173 174 ap = argfp+1; 175 if (ap >= args+10) 176 ERROR "arguments too deep" FATAL; 177 argcnt = 0; 178 if (input() != '(') 179 ERROR "disaster in dodef" FATAL; 180 if (ap->argval == 0) 181 ap->argval = malloc(1000); 182 for (p = ap->argval; (len = getarg(p)) != -1; p += len) { 183 ap->argstk[argcnt++] = p; 184 if (input() == ')') 185 break; 186 } 187 for (i = argcnt; i < MAXARGS; i++) 188 ap->argstk[i] = ""; 189 if (dbg) 190 for (i = 0; i < argcnt; i++) 191 printf("arg %d.%d = <%s>\n", (int) (ap-args), i+1, ap->argstk[i]); 192 argfp = ap; 193 pushsrc(Macro, stp->s_val.p); 194 } 195 196 int 197 getarg(char *p) /* pick up single argument, store in p, return length */ 198 { 199 int n, c, npar; 200 201 n = npar = 0; 202 for ( ;; ) { 203 c = input(); 204 if (c == EOF) 205 ERROR "end of file in getarg" FATAL; 206 if (npar == 0 && (c == ',' || c == ')')) 207 break; 208 if (c == '"') /* copy quoted stuff intact */ 209 do { 210 *p++ = c; 211 n++; 212 } while ((c = input()) != '"' && c != EOF); 213 else if (c == '(') 214 npar++; 215 else if (c == ')') 216 npar--; 217 n++; 218 *p++ = c; 219 } 220 *p = 0; 221 unput(c); 222 return(n + 1); 223 } 224 225 #define PBSIZE 2000 226 char pbuf[PBSIZE]; /* pushback buffer */ 227 char *pb = pbuf-1; /* next pushed back character */ 228 229 char ebuf[200]; /* collect input here for error reporting */ 230 char *ep = ebuf; 231 232 int begin = 0; 233 extern int thru; 234 extern struct symtab *thrudef; 235 extern char *untilstr; 236 237 int 238 input(void) 239 { 240 register int c; 241 242 if (thru && begin) { 243 do_thru(); 244 begin = 0; 245 } 246 c = nextchar(); 247 if (dbg > 1) 248 printf(" <%c>", c); 249 if (ep >= ebuf + sizeof ebuf) 250 ep = ebuf; 251 return *ep++ = c; 252 } 253 254 int 255 nextchar(void) 256 { 257 register int c; 258 259 c = 0; /* Botch: gcc */ 260 261 loop: 262 switch (srcp->type) { 263 case Free: /* free string */ 264 free(srcp->sp); 265 popsrc(); 266 goto loop; 267 case Thru: /* end of pushed back line */ 268 begin = 1; 269 popsrc(); 270 c = '\n'; 271 break; 272 case Char: 273 if (pb >= pbuf) { 274 c = *pb--; 275 popsrc(); 276 break; 277 } else { /* can't happen? */ 278 popsrc(); 279 goto loop; 280 } 281 case String: 282 c = *srcp->sp++; 283 if (c == '\0') { 284 popsrc(); 285 goto loop; 286 } else { 287 if (*srcp->sp == '\0') /* empty, so pop */ 288 popsrc(); 289 break; 290 } 291 case Macro: 292 c = *srcp->sp++; 293 if (c == '\0') { 294 if (--argfp < args) 295 ERROR "argfp underflow" FATAL; 296 popsrc(); 297 goto loop; 298 } else if (c == '$' && isdigit((unsigned char) *srcp->sp)) { 299 int n = 0; 300 while (isdigit((unsigned char) *srcp->sp)) 301 n = 10 * n + *srcp->sp++ - '0'; 302 if (n > 0 && n <= MAXARGS) 303 pushsrc(String, argfp->argstk[n-1]); 304 goto loop; 305 } 306 break; 307 case File: 308 c = getc(curfile->fin); 309 if (c == EOF) { 310 if (curfile == infile) 311 ERROR "end of file inside .PS/.PE" FATAL; 312 if (curfile->fin != stdin) { 313 fclose(curfile->fin); 314 free(curfile->fname); /* assumes allocated */ 315 } 316 curfile--; 317 printlf(curfile->lineno, curfile->fname); 318 popsrc(); 319 thru = 0; /* chicken out */ 320 thrudef = 0; 321 if (untilstr) { 322 free(untilstr); 323 untilstr = 0; 324 } 325 goto loop; 326 } 327 if (c == '\n') 328 curfile->lineno++; 329 break; 330 } 331 return c; 332 } 333 334 void do_thru(void) /* read one line, make into a macro expansion */ 335 { 336 int c, i; 337 char *p; 338 Arg *ap; 339 340 ap = argfp+1; 341 if (ap >= args+10) 342 ERROR "arguments too deep" FATAL; 343 if (ap->argval == NULL) 344 ap->argval = malloc(1000); 345 p = ap->argval; 346 argcnt = 0; 347 c = nextchar(); 348 if (thru == 0) { /* end of file was seen, so thru is done */ 349 unput(c); 350 return; 351 } 352 for ( ; c != '\n' && c != EOF; ) { 353 if (c == ' ' || c == '\t') { 354 c = nextchar(); 355 continue; 356 } 357 ap->argstk[argcnt++] = p; 358 if (c == '"') { 359 do { 360 *p++ = c; 361 if ((c = nextchar()) == '\\') { 362 *p++ = c; 363 *p++ = nextchar(); 364 c = nextchar(); 365 } 366 } while (c != '"' && c != '\n' && c != EOF); 367 *p++ = '"'; 368 if (c == '"') 369 c = nextchar(); 370 } else { 371 do { 372 *p++ = c; 373 } while ((c = nextchar())!=' ' && c!='\t' && c!='\n' && c!=',' && c!=EOF); 374 if (c == ',') 375 c = nextchar(); 376 } 377 *p++ = '\0'; 378 } 379 if (c == EOF) 380 ERROR "unexpected end of file in do_thru" FATAL; 381 if (argcnt == 0) { /* ignore blank line */ 382 pushsrc(Thru, (char *) 0); 383 return; 384 } 385 for (i = argcnt; i < MAXARGS; i++) 386 ap->argstk[i] = ""; 387 if (dbg) 388 for (i = 0; i < argcnt; i++) 389 printf("arg %d.%d = <%s>\n", (int) (ap-args), i+1, ap->argstk[i]); 390 if (strcmp(ap->argstk[0], ".PE") == 0) { 391 thru = 0; 392 thrudef = 0; 393 pushsrc(String, "\n.PE\n"); 394 return; 395 } 396 if (untilstr && strcmp(ap->argstk[0], untilstr) == 0) { 397 thru = 0; 398 thrudef = 0; 399 free(untilstr); 400 untilstr = 0; 401 return; 402 } 403 pushsrc(Thru, (char *) 0); 404 dprintf("do_thru pushing back <%s>\n", thrudef->s_val.p); 405 argfp = ap; 406 pushsrc(Macro, thrudef->s_val.p); 407 } 408 409 int 410 unput(int c) 411 { 412 if (++pb >= pbuf + sizeof pbuf) 413 ERROR "pushback overflow" FATAL; 414 if (--ep < ebuf) 415 ep = ebuf + sizeof(ebuf) - 1; 416 *pb = c; 417 pushsrc(Char, pb); 418 return c; 419 } 420 421 void pbstr(char *s) 422 { 423 pushsrc(String, s); 424 } 425 426 double errcheck(double x, char *s) 427 { 428 if (errno == EDOM) { 429 errno = 0; 430 ERROR "%s argument out of domain", s WARNING; 431 } else if (errno == ERANGE) { 432 errno = 0; 433 ERROR "%s result out of range", s WARNING; 434 } 435 return x; 436 } 437 438 char errbuf[1000]; 439 440 void eprint(void); 441 442 void yyerror(char *s) 443 { 444 extern char *cmdname; 445 int ern = errno; /* cause some libraries clobber it */ 446 447 if (synerr) 448 return; 449 fflush(stdout); 450 fprintf(stderr, "%s: %s", cmdname, s); 451 if (ern > 0) { 452 errno = ern; 453 perror("???"); 454 } 455 fprintf(stderr, " near %s:%d\n", 456 curfile->fname, curfile->lineno+1); 457 eprint(); 458 synerr = 1; 459 errno = 0; 460 } 461 462 void eprint(void) /* try to print context around error */ 463 { 464 char *p, *q; 465 466 p = ep - 1; 467 if (p > ebuf && *p == '\n') 468 p--; 469 for ( ; p >= ebuf && *p != '\n'; p--) 470 ; 471 while (*p == '\n') 472 p++; 473 fprintf(stderr, " context is\n\t"); 474 for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) 475 ; 476 while (p < q) 477 putc(*p++, stderr); 478 fprintf(stderr, " >>> "); 479 while (p < ep) 480 putc(*p++, stderr); 481 fprintf(stderr, " <<< "); 482 while (pb >= pbuf) 483 putc(*pb--, stderr); 484 fgets(ebuf, sizeof ebuf, curfile->fin); 485 fprintf(stderr, "%s", ebuf); 486 pbstr("\n.PE\n"); /* safety first */ 487 ep = ebuf; 488 } 489 490 void yywrap(void) {} 491 492 char *newfile = 0; /* filename for file copy */ 493 char *untilstr = 0; /* string that terminates a thru */ 494 int thru = 0; /* 1 if copying thru macro */ 495 struct symtab *thrudef = 0; /* macro being used */ 496 497 void copyfile(char *s) /* remember file to start reading from */ 498 { 499 newfile = s; 500 } 501 502 void copydef(struct symtab *p) /* remember macro symtab ptr */ 503 { 504 thrudef = p; 505 } 506 507 struct symtab *copythru(char *s) /* collect the macro name or body for thru */ 508 { 509 struct symtab *p; 510 char *q, *addnewline(char *); 511 512 p = lookup(s); 513 if (p != NULL) { 514 if (p->s_type == DEFNAME) { 515 p->s_val.p = addnewline(p->s_val.p); 516 return p; 517 } else 518 ERROR "%s used as define and name", s FATAL; 519 } 520 /* have to collect the definition */ 521 pbstr(s); /* first char is the delimiter */ 522 q = delimstr("thru body"); 523 s = "nameless"; 524 p = lookup(s); 525 if (p != NULL) { 526 if (p->s_val.p) 527 free(p->s_val.p); 528 p->s_val.p = q; 529 } else { 530 YYSTYPE u; 531 u.p = q; 532 p = makevar(tostring(s), DEFNAME, u); 533 } 534 p->s_val.p = addnewline(p->s_val.p); 535 dprintf("installing %s as `%s'\n", s, p->s_val.p); 536 return p; 537 } 538 539 char *addnewline(char *p) /* add newline to end of p */ 540 { 541 int n; 542 543 n = strlen(p); 544 if (p[n-1] != '\n') { 545 p = realloc(p, n+2); 546 p[n] = '\n'; 547 p[n+1] = '\0'; 548 } 549 return p; 550 } 551 552 void copyuntil(char *s) /* string that terminates a thru */ 553 { 554 untilstr = s; 555 } 556 557 void copy(void) /* begin input from file, etc. */ 558 { 559 FILE *fin; 560 561 if (newfile) { 562 if ((fin = fopen(newfile, "r")) == NULL) 563 ERROR "can't open file %s", newfile FATAL; 564 curfile++; 565 curfile->fin = fin; 566 curfile->fname = newfile; 567 curfile->lineno = 0; 568 printlf(1, curfile->fname); 569 pushsrc(File, curfile->fname); 570 newfile = 0; 571 } 572 if (thrudef) { 573 thru = 1; 574 begin = 1; /* wrong place */ 575 } 576 } 577 578 char shellbuf[1000], *shellp; 579 580 void shell_init(void) /* set up to interpret a shell command */ 581 { 582 sprintf(shellbuf, "rc -c '"); 583 shellp = shellbuf + strlen(shellbuf); 584 } 585 586 void shell_text(char *s) /* add string to command being collected */ 587 { 588 while ((*shellp++ = *s++)) 589 ; 590 shellp--; 591 } 592 593 void shell_exec(void) /* do it */ 594 { 595 *shellp++ = '\''; 596 *shellp = '\0'; 597 system(shellbuf); 598 }