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