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