|
|
1.1 ! root 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 ", 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 ", 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: baldelim(int c, char *s) /* replace c by balancing entry in s */ ! 146: { ! 147: for ( ; *s; s += 2) ! 148: if (*s == c) ! 149: return s[1]; ! 150: return c; ! 151: } ! 152: ! 153: void undefine(char *s) /* undefine macro */ ! 154: { ! 155: while (*s != ' ' && *s != '\t') /* skip "undef..." */ ! 156: s++; ! 157: while (*s == ' ' || *s == '\t') ! 158: s++; ! 159: freedef(s); ! 160: } ! 161: ! 162: ! 163: Arg args[10]; /* argument frames */ ! 164: Arg *argfp = args; /* frame pointer */ ! 165: int argcnt; /* number of arguments seen so far */ ! 166: ! 167: void 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 %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]); ! 191: argfp = ap; ! 192: pushsrc(Macro, stp->s_val.p); ! 193: } ! 194: ! 195: getarg(char *p) /* pick up single argument, store in p, return length */ ! 196: { ! 197: int n, c, npar; ! 198: ! 199: n = npar = 0; ! 200: for ( ;; ) { ! 201: c = input(); ! 202: if (c == EOF) ! 203: ERROR "end of file in getarg" FATAL; ! 204: if (npar == 0 && (c == ',' || c == ')')) ! 205: break; ! 206: if (c == '"') /* copy quoted stuff intact */ ! 207: do { ! 208: *p++ = c; ! 209: n++; ! 210: } while ((c = input()) != '"' && c != EOF); ! 211: else if (c == '(') ! 212: npar++; ! 213: else if (c == ')') ! 214: npar--; ! 215: n++; ! 216: *p++ = c; ! 217: } ! 218: *p = 0; ! 219: unput(c); ! 220: return(n + 1); ! 221: } ! 222: ! 223: #define PBSIZE 2000 ! 224: char pbuf[PBSIZE]; /* pushback buffer */ ! 225: char *pb = pbuf-1; /* next pushed back character */ ! 226: ! 227: char ebuf[200]; /* collect input here for error reporting */ ! 228: char *ep = ebuf; ! 229: ! 230: int begin = 0; ! 231: extern int thru; ! 232: extern struct symtab *thrudef; ! 233: extern char *untilstr; ! 234: ! 235: input(void) ! 236: { ! 237: register int c; ! 238: ! 239: if (thru && begin) { ! 240: do_thru(); ! 241: begin = 0; ! 242: } ! 243: c = nextchar(); ! 244: if (dbg > 1) ! 245: printf(" <%c>", c); ! 246: if (ep >= ebuf + sizeof ebuf) ! 247: ep = ebuf; ! 248: return *ep++ = c; ! 249: } ! 250: ! 251: nextchar(void) ! 252: { ! 253: register int c; ! 254: ! 255: loop: ! 256: switch (srcp->type) { ! 257: case Free: /* free string */ ! 258: free(srcp->sp); ! 259: popsrc(); ! 260: goto loop; ! 261: case Thru: /* end of pushed back line */ ! 262: begin = 1; ! 263: popsrc(); ! 264: c = '\n'; ! 265: break; ! 266: case Char: ! 267: if (pb >= pbuf) { ! 268: c = *pb--; ! 269: popsrc(); ! 270: break; ! 271: } else { /* can't happen? */ ! 272: popsrc(); ! 273: goto loop; ! 274: } ! 275: case String: ! 276: c = *srcp->sp++; ! 277: if (c == '\0') { ! 278: popsrc(); ! 279: goto loop; ! 280: } else { ! 281: if (*srcp->sp == '\0') /* empty, so pop */ ! 282: popsrc(); ! 283: break; ! 284: } ! 285: case Macro: ! 286: c = *srcp->sp++; ! 287: if (c == '\0') { ! 288: if (--argfp < args) ! 289: ERROR "argfp underflow" FATAL; ! 290: popsrc(); ! 291: goto loop; ! 292: } else if (c == '$' && isdigit(*srcp->sp)) { ! 293: int n = 0; ! 294: while (isdigit(*srcp->sp)) ! 295: n = 10 * n + *srcp->sp++ - '0'; ! 296: if (n > 0 && n <= MAXARGS) ! 297: pushsrc(String, argfp->argstk[n-1]); ! 298: goto loop; ! 299: } ! 300: break; ! 301: case File: ! 302: c = getc(curfile->fin); ! 303: if (c == EOF) { ! 304: if (curfile == infile) ! 305: ERROR "end of file inside .PS/.PE" FATAL; ! 306: if (curfile->fin != stdin) { ! 307: fclose(curfile->fin); ! 308: free(curfile->fname); /* assumes allocated */ ! 309: } ! 310: curfile--; ! 311: printlf(curfile->lineno, curfile->fname); ! 312: popsrc(); ! 313: thru = 0; /* chicken out */ ! 314: thrudef = 0; ! 315: if (untilstr) { ! 316: free(untilstr); ! 317: untilstr = 0; ! 318: } ! 319: goto loop; ! 320: } ! 321: if (c == '\n') ! 322: curfile->lineno++; ! 323: break; ! 324: } ! 325: return c; ! 326: } ! 327: ! 328: void do_thru(void) /* read one line, make into a macro expansion */ ! 329: { ! 330: int c, i; ! 331: char *p; ! 332: Arg *ap; ! 333: ! 334: ap = argfp+1; ! 335: if (ap >= args+10) ! 336: ERROR "arguments too deep" FATAL; ! 337: if (ap->argval == NULL) ! 338: ap->argval = malloc(1000); ! 339: p = ap->argval; ! 340: argcnt = 0; ! 341: c = nextchar(); ! 342: if (thru == 0) { /* end of file was seen, so thru is done */ ! 343: unput(c); ! 344: return; ! 345: } ! 346: for ( ; c != '\n' && c != EOF; ) { ! 347: if (c == ' ' || c == '\t') { ! 348: c = nextchar(); ! 349: continue; ! 350: } ! 351: ap->argstk[argcnt++] = p; ! 352: if (c == '"') { ! 353: do { ! 354: *p++ = c; ! 355: if ((c = nextchar()) == '\\') { ! 356: *p++ = c; ! 357: *p++ = nextchar(); ! 358: c = nextchar(); ! 359: } ! 360: } while (c != '"' && c != '\n' && c != EOF); ! 361: *p++ = '"'; ! 362: if (c == '"') ! 363: c = nextchar(); ! 364: } else { ! 365: do { ! 366: *p++ = c; ! 367: } while ((c = nextchar())!=' ' && c!='\t' && c!='\n' && c!=',' && c!=EOF); ! 368: if (c == ',') ! 369: c = nextchar(); ! 370: } ! 371: *p++ = '\0'; ! 372: } ! 373: if (c == EOF) ! 374: ERROR "unexpected end of file in do_thru" FATAL; ! 375: if (argcnt == 0) { /* ignore blank line */ ! 376: pushsrc(Thru, (char *) 0); ! 377: return; ! 378: } ! 379: for (i = argcnt; i < MAXARGS; i++) ! 380: ap->argstk[i] = ""; ! 381: if (dbg) ! 382: for (i = 0; i < argcnt; i++) ! 383: printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]); ! 384: if (strcmp(ap->argstk[0], ".PE") == 0) { ! 385: thru = 0; ! 386: thrudef = 0; ! 387: pushsrc(String, "\n.PE\n"); ! 388: return; ! 389: } ! 390: if (untilstr && strcmp(ap->argstk[0], untilstr) == 0) { ! 391: thru = 0; ! 392: thrudef = 0; ! 393: free(untilstr); ! 394: untilstr = 0; ! 395: return; ! 396: } ! 397: pushsrc(Thru, (char *) 0); ! 398: dprintf("do_thru pushing back <%s>\n", thrudef->s_val.p); ! 399: argfp = ap; ! 400: pushsrc(Macro, thrudef->s_val.p); ! 401: } ! 402: ! 403: unput(int c) ! 404: { ! 405: if (++pb >= pbuf + sizeof pbuf) ! 406: ERROR "pushback overflow" FATAL; ! 407: if (--ep < ebuf) ! 408: ep = ebuf + sizeof(ebuf) - 1; ! 409: *pb = c; ! 410: pushsrc(Char, pb); ! 411: return c; ! 412: } ! 413: ! 414: void pbstr(char *s) ! 415: { ! 416: pushsrc(String, s); ! 417: } ! 418: ! 419: double errcheck(double x, char *s) ! 420: { ! 421: extern int errno; ! 422: ! 423: if (errno == EDOM) { ! 424: errno = 0; ! 425: ERROR "%s argument out of domain", s WARNING; ! 426: } else if (errno == ERANGE) { ! 427: errno = 0; ! 428: ERROR "%s result out of range", s WARNING; ! 429: } ! 430: return x; ! 431: } ! 432: ! 433: char errbuf[200]; ! 434: ! 435: void eprint(void); ! 436: ! 437: void yyerror(char *s) ! 438: { ! 439: extern char *cmdname; ! 440: int ern = errno; /* cause some libraries clobber it */ ! 441: ! 442: if (synerr) ! 443: return; ! 444: fflush(stdout); ! 445: fprintf(stderr, "%s: %s", cmdname, s); ! 446: if (ern > 0) { ! 447: errno = ern; ! 448: perror("???"); ! 449: } ! 450: fprintf(stderr, " near line %d, file %s\n", ! 451: curfile->lineno, curfile->fname); ! 452: eprint(); ! 453: synerr = 1; ! 454: errno = 0; ! 455: } ! 456: ! 457: void eprint(void) /* try to print context around error */ ! 458: { ! 459: char *p, *q; ! 460: ! 461: p = ep - 1; ! 462: if (p > ebuf && *p == '\n') ! 463: p--; ! 464: for ( ; p >= ebuf && *p != '\n'; p--) ! 465: ; ! 466: while (*p == '\n') ! 467: p++; ! 468: fprintf(stderr, " context is\n\t"); ! 469: for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) ! 470: ; ! 471: while (p < q) ! 472: putc(*p++, stderr); ! 473: fprintf(stderr, " >>> "); ! 474: while (p < ep) ! 475: putc(*p++, stderr); ! 476: fprintf(stderr, " <<< "); ! 477: while (pb >= pbuf) ! 478: putc(*pb--, stderr); ! 479: fgets(ebuf, sizeof ebuf, curfile->fin); ! 480: fprintf(stderr, "%s", ebuf); ! 481: pbstr("\n.PE\n"); /* safety first */ ! 482: ep = ebuf; ! 483: } ! 484: ! 485: void yywrap(void) {} ! 486: ! 487: char *newfile = 0; /* filename for file copy */ ! 488: char *untilstr = 0; /* string that terminates a thru */ ! 489: int thru = 0; /* 1 if copying thru macro */ ! 490: struct symtab *thrudef = 0; /* macro being used */ ! 491: ! 492: void copyfile(char *s) /* remember file to start reading from */ ! 493: { ! 494: newfile = s; ! 495: } ! 496: ! 497: void copydef(struct symtab *p) /* remember macro symtab ptr */ ! 498: { ! 499: thrudef = p; ! 500: } ! 501: ! 502: struct symtab *copythru(char *s) /* collect the macro name or body for thru */ ! 503: { ! 504: struct symtab *p; ! 505: char *q, *addnewline(char *); ! 506: ! 507: p = lookup(s); ! 508: if (p != NULL) { ! 509: if (p->s_type == DEFNAME) { ! 510: p->s_val.p = addnewline(p->s_val.p); ! 511: return p; ! 512: } else ! 513: ERROR "%s used as define and name", s FATAL; ! 514: } ! 515: /* have to collect the definition */ ! 516: pbstr(s); /* first char is the delimiter */ ! 517: q = delimstr("thru body"); ! 518: s = "nameless"; ! 519: p = lookup(s); ! 520: if (p != NULL) { ! 521: if (p->s_val.p) ! 522: free(p->s_val.p); ! 523: p->s_val.p = q; ! 524: } else { ! 525: YYSTYPE u; ! 526: u.p = q; ! 527: p = makevar(tostring(s), DEFNAME, u); ! 528: } ! 529: p->s_val.p = addnewline(p->s_val.p); ! 530: dprintf("installing %s as `%s'\n", s, p->s_val.p); ! 531: return p; ! 532: } ! 533: ! 534: char *addnewline(char *p) /* add newline to end of p */ ! 535: { ! 536: int n; ! 537: ! 538: n = strlen(p); ! 539: if (p[n-1] != '\n') { ! 540: p = realloc(p, n+2); ! 541: p[n] = '\n'; ! 542: p[n+1] = '\0'; ! 543: } ! 544: return p; ! 545: } ! 546: ! 547: void copyuntil(char *s) /* string that terminates a thru */ ! 548: { ! 549: untilstr = s; ! 550: } ! 551: ! 552: void copy(void) /* begin input from file, etc. */ ! 553: { ! 554: FILE *fin; ! 555: ! 556: if (newfile) { ! 557: if ((fin = fopen(newfile, "r")) == NULL) ! 558: ERROR "can't open file %s", newfile FATAL; ! 559: curfile++; ! 560: curfile->fin = fin; ! 561: curfile->fname = newfile; ! 562: curfile->lineno = 0; ! 563: printlf(1, curfile->fname); ! 564: pushsrc(File, curfile->fname); ! 565: newfile = 0; ! 566: } ! 567: if (thrudef) { ! 568: thru = 1; ! 569: begin = 1; /* wrong place */ ! 570: } ! 571: } ! 572: ! 573: char shellbuf[1000], *shellp; ! 574: ! 575: void shell_init(void) /* set up to interpret a shell command */ ! 576: { ! 577: sprintf(shellbuf, "sh -c '"); ! 578: shellp = shellbuf + strlen(shellbuf); ! 579: } ! 580: ! 581: void shell_text(char *s) /* add string to command being collected */ ! 582: { ! 583: while (*shellp++ = *s++) ! 584: ; ! 585: shellp--; ! 586: } ! 587: ! 588: void shell_exec(void) /* do it */ ! 589: { ! 590: *shellp++ = '\''; ! 591: *shellp = '\0'; ! 592: system(shellbuf); ! 593: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.