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