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