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