|
|
1.1 ! root 1: /* ! 2: * sed/sed2.c ! 3: * A stream editor. ! 4: * Compiler. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <ctype.h> ! 9: #include <string.h> ! 10: #include "sed.h" ! 11: ! 12: FIL *codefil(); ! 13: char *codetrn(); ! 14: LAB *codelab(); ! 15: char *duplstr(); ! 16: SUB *codesub(); ! 17: ! 18: /* ! 19: * Compile a file of commands. ! 20: */ ! 21: compfil(name) ! 22: char *name; ! 23: { ! 24: register FILE *fp; ! 25: register int c; ! 26: register char *cp; ! 27: ! 28: if ((fp=fopen(name, "r")) == NULL) { ! 29: fprintf(stderr, "Cannot open %s\n", name); ! 30: exit(1); ! 31: } ! 32: cp = linebuf; ! 33: while ((c=getc(fp)) != EOF) { ! 34: if (cp >= &linebuf[LHPSIZE-2]) { ! 35: printc("Line too long"); ! 36: cp = linebuf; ! 37: while ((c=getc(fp))!='\n' && c!=EOF) ! 38: ; ! 39: if (c == EOF) ! 40: break; ! 41: } ! 42: if (c == '\n' || c == ';') { ! 43: *cp = '\0'; ! 44: ncp = linebuf; ! 45: compcom(); ! 46: cp = linebuf; ! 47: if (c == ';') ! 48: --lno; ! 49: continue; ! 50: } ! 51: if (c == '\\') { ! 52: if ((c=getc(fp))!='\n' && c!='\\' && c!=';') { ! 53: ungetc(c, fp); ! 54: c = '\\'; ! 55: } ! 56: } ! 57: *cp++ = c; ! 58: } ! 59: if (cp != linebuf) { ! 60: *cp++ = '\0'; ! 61: ncp = linebuf; ! 62: compcom(); ! 63: } ! 64: } ! 65: ! 66: /* ! 67: * Compile a string. ! 68: */ ! 69: compstr(cp) register char *cp; ! 70: { ! 71: register int c; ! 72: register char *lp; ! 73: ! 74: do { ! 75: lp = linebuf; ! 76: while ((c = *cp++) != '\0' && c != '\n' && c != ';') { ! 77: if (c == '\\' && (*cp == ';' || *cp == '\n')) ! 78: c = *cp++; /* "\;" means ';' */ ! 79: *lp++ = c; ! 80: } ! 81: *lp = '\0'; ! 82: ncp = linebuf; ! 83: compcom(); ! 84: } while (c != '\0'); ! 85: } ! 86: ! 87: /* ! 88: * Compile a command and return a pointer to the compiled ! 89: * structure. ! 90: */ ! 91: compcom() ! 92: { ! 93: QCL *qp; ! 94: int nadd; ! 95: register COM *cp; ! 96: register LAB *lp; ! 97: register int c; ! 98: ! 99: lno++; ! 100: while (isascii(c=getn()) && isspace(c)) ! 101: ; ! 102: if (c == '\0') ! 103: return; ! 104: ungetn(c); ! 105: cp = (COM *)salloc(sizeof (COM)); ! 106: if (getaddr(&cp->c_a[0]) == 0) ! 107: goto err; ! 108: nadd = addnone ? 0 : 1; ! 109: if ((c=getn()) == ',') { ! 110: if (addnone!=0 || getaddr(&cp->c_a[1])==0 || addnone!=0) ! 111: goto err; ! 112: c = getn(); ! 113: nadd++; ! 114: } ! 115: while (isascii(c) && isspace(c)) ! 116: c = getn(); ! 117: if (c == '!') { ! 118: cp->c_notf = 1; ! 119: c = getn(); ! 120: } else ! 121: cp->c_notf = 0; ! 122: cp->c_name = c; ! 123: cp->c_nadd = nadd; ! 124: switch (c) { ! 125: case '{': ! 126: qp = (QCL *)salloc(sizeof (QCL)); ! 127: qp->q_next = qcbp; ! 128: qcbp = qp; ! 129: qp->q_comp = cp; ! 130: if ((c=getn()) != '\0') { ! 131: *compp = cp; ! 132: compp = &cp->c_next; ! 133: ungetn(c); ! 134: compcom(); ! 135: return; ! 136: } ! 137: break; ! 138: case '}': ! 139: if ((qp=qcbp) == NULL) { ! 140: printc("Too many `}'"); ! 141: goto err; ! 142: } ! 143: qcbp = qcbp->q_next; ! 144: if (codenwl() == 0) ! 145: goto err; ! 146: qp->q_comp->c_p.p_com = qp->q_comp->c_next; ! 147: qp->q_comp->c_next = cp; ! 148: free(qp); ! 149: break; ! 150: case '=': ! 151: if (codenwl() == 0) ! 152: goto err; ! 153: break; ! 154: case ':': ! 155: if ((lp=codelab()) == NULL) ! 156: goto err; ! 157: if (lp->l_comp != NULL) { ! 158: printc("Label %s multiply defined", pattbuf); ! 159: goto err; ! 160: } ! 161: lp->l_comp = cp; ! 162: break; ! 163: case 'a': ! 164: if (nadd > 1) ! 165: goto adr; ! 166: if (getn() != '\n') ! 167: goto syn; ! 168: if (codelin() == 0) ! 169: goto err; ! 170: cp->c_p.p_buf = duplstr(pattbuf); ! 171: if (cp->c_a[0].a_lno == 0+1) { ! 172: cp->c_name = 'i'; ! 173: cp->c_a[0].a_lno = 1+1; ! 174: } ! 175: break; ! 176: case 'b': ! 177: if ((lp=codelab()) == NULL) ! 178: goto err; ! 179: cp->c_p.p_lab = lp; ! 180: lp->l_refc++; ! 181: break; ! 182: case 'c': ! 183: if (getn() != '\n') ! 184: goto syn; ! 185: if (codelin() == 0) ! 186: goto err; ! 187: cp->c_p.p_buf = duplstr(pattbuf); ! 188: break; ! 189: case 'd': ! 190: case 'D': ! 191: case 'g': ! 192: case 'G': ! 193: case 'h': ! 194: case 'H': ! 195: if (codenwl() == 0) ! 196: goto err; ! 197: break; ! 198: case 'i': ! 199: if (nadd > 1) ! 200: goto adr; ! 201: if (getn() != '\n') ! 202: goto syn; ! 203: if (codelin() == 0) ! 204: goto err; ! 205: cp->c_p.p_buf = duplstr(pattbuf); ! 206: break; ! 207: case 'l': ! 208: case 'n': ! 209: case 'N': ! 210: case 'p': ! 211: case 'P': ! 212: if (codenwl() == 0) ! 213: goto err; ! 214: break; ! 215: case 'q': ! 216: if (nadd > 1) ! 217: goto adr; ! 218: if (codenwl() == 0) ! 219: goto err; ! 220: break; ! 221: case 'r': ! 222: if (nadd > 1) ! 223: goto adr; ! 224: if (codelin() == 0) ! 225: goto err; ! 226: if (pattbuf[0] != ' ') ! 227: goto err; ! 228: cp->c_p.p_buf = duplstr(&pattbuf[1]); ! 229: break; ! 230: case 's': ! 231: if ((cp->c_p.p_sub=codesub()) == NULL) ! 232: goto err; ! 233: break; ! 234: case 't': ! 235: if ((lp=codelab()) == NULL) ! 236: goto err; ! 237: cp->c_p.p_lab = lp; ! 238: lp->l_refc++; ! 239: break; ! 240: case 'w': ! 241: if ((cp->c_p.p_fil=codefil()) == NULL) ! 242: goto err; ! 243: break; ! 244: case 'x': ! 245: if (codenwl() == 0) ! 246: goto err; ! 247: break; ! 248: case 'y': ! 249: if ((cp->c_p.p_buf=codetrn()) == NULL) ! 250: goto err; ! 251: break; ! 252: default: ! 253: printc("Bad command"); ! 254: goto err; ! 255: } ! 256: *compp = cp; ! 257: compp = &cp->c_next; ! 258: return; ! 259: ! 260: syn: ! 261: printc("Syntax error"); ! 262: free(cp); ! 263: return; ! 264: ! 265: adr: ! 266: printc("Bad address"); ! 267: err: ! 268: free(cp); ! 269: } ! 270: ! 271: /* ! 272: * Read a line address and compile it into the given address ! 273: * pointer. ! 274: */ ! 275: getaddr(ap) ! 276: register ADD *ap; ! 277: { ! 278: register int c, n; ! 279: ! 280: addnone = 0; ! 281: if ((c=getn()) == '/') { ! 282: if (compile('/') == 0) ! 283: return 0; ! 284: ap->a_lno = 0; ! 285: ap->a_pat = duplstr(pattbuf); ! 286: return 1; ! 287: } ! 288: if (c == '$') { ! 289: ap->a_lno = HUGE; ! 290: return 1; ! 291: } ! 292: if (isascii(c) && isdigit(c)) { ! 293: n = 0; ! 294: do { ! 295: n = n*10 + c-'0'; ! 296: } while (isascii(c=getn()) && isdigit(c)); ! 297: ungetn(c); ! 298: ap->a_lno = n+1; ! 299: return 1; ! 300: } ! 301: ungetn(c); ! 302: addnone = 1; ! 303: return 1; ! 304: } ! 305: ! 306: /* ! 307: * There shouldn't be any more input left. ! 308: */ ! 309: codenwl() ! 310: { ! 311: if (getn() != '\0') { ! 312: printc("Syntax error"); ! 313: return 0; ! 314: } ! 315: return 1; ! 316: } ! 317: ! 318: /* ! 319: * Parse a label, put it into the label table and return ! 320: * a pointer to the entry. ! 321: */ ! 322: LAB * ! 323: codelab() ! 324: { ! 325: char name[LNMSIZE]; ! 326: register LAB *lp; ! 327: register int c; ! 328: register char *np; ! 329: ! 330: while (isascii(c=getn()) && isspace(c)) ! 331: ; ! 332: np = name; ! 333: while (c != '\0') { ! 334: if (np < &name[LNMSIZE-1]) ! 335: *np++ = c; ! 336: c = getn(); ! 337: } ! 338: *np = '\0'; ! 339: for (lp=labp; lp; lp=lp->l_next) { ! 340: if (strcmp(lp->l_name, name) == 0) ! 341: return lp; ! 342: } ! 343: lp = (LAB *)salloc(sizeof (LAB)); ! 344: lp->l_next = labp; ! 345: labp = lp; ! 346: strcpy(lp->l_name, name); ! 347: lp->l_comp = NULL; ! 348: lp->l_refc = 0; ! 349: return lp; ! 350: } ! 351: ! 352: /* ! 353: * Parse a file name that will be used to write on and set it ! 354: * up in our write table. ! 355: */ ! 356: FIL * ! 357: codefil() ! 358: { ! 359: char name[FNMSIZE]; ! 360: register FIL *fp; ! 361: register int c; ! 362: register char *np; ! 363: ! 364: while (isascii(c=getn()) && isspace(c)) ! 365: ; ! 366: np = name; ! 367: while (c != '\0') { ! 368: if (np >= &name[FNMSIZE-1]) { ! 369: printc("Line buffer overflow"); ! 370: return NULL; ! 371: } ! 372: *np++ = c; ! 373: c = getn(); ! 374: } ! 375: *np = '\0'; ! 376: for (fp=filp; fp; fp=fp->f_next) { ! 377: if (strcmp(fp->f_name, name) == 0) ! 378: return fp; ! 379: } ! 380: fp = (FIL *)salloc(sizeof (FIL)); ! 381: fp->f_next = filp; ! 382: filp = fp; ! 383: strcpy(fp->f_name, name); ! 384: fp->f_filp = NULL; ! 385: return fp; ! 386: } ! 387: ! 388: /* ! 389: * Get a line of text for commands such as the append. ! 390: */ ! 391: codelin() ! 392: { ! 393: register int c; ! 394: register char *pp; ! 395: ! 396: pp = pattbuf; ! 397: while ((c=getn()) != '\0') { ! 398: if (pp >= &pattbuf[LHPSIZE-1]) { ! 399: printc("Line buffer overflow"); ! 400: return 0; ! 401: } ! 402: *pp++ = c; ! 403: } ! 404: *pp = '\0'; ! 405: return 1; ! 406: } ! 407: ! 408: /* ! 409: * Compile the substitute command. ! 410: */ ! 411: SUB * ! 412: codesub() ! 413: { ! 414: int nth, ec; ! 415: register SUB *sp; ! 416: register int c; ! 417: register char *pp; ! 418: ! 419: nth = 1; ! 420: if (isascii(c=getn()) && isdigit(c)) { ! 421: nth = 0; ! 422: while (isascii(c) && isdigit(c)) { ! 423: nth = nth*10 + c-'0'; ! 424: c = getn(); ! 425: } ! 426: } ! 427: if ((ec=c) == '\n') { ! 428: ungetn(c); ! 429: printc("Syntax error"); ! 430: return NULL; ! 431: } ! 432: if (compile(ec) == 0) ! 433: return NULL; ! 434: pp = holdbuf; ! 435: while ((c=getn()) != ec) { ! 436: if (pp >= &holdbuf[LHPSIZE-4]) { ! 437: printc("Pattern buffer overflow"); ! 438: return NULL; ! 439: } ! 440: switch (c) { ! 441: case '\0': ! 442: ungetn(c); ! 443: printc("Syntax error"); ! 444: return NULL; ! 445: case '&': ! 446: *pp++ = '\\'; ! 447: *pp++ = '0'; ! 448: continue; ! 449: case '\\': ! 450: if ((c=getn()) == '\\') { ! 451: *pp++ = '\\'; ! 452: *pp++ = '\\'; ! 453: continue; ! 454: } ! 455: if (c >= '1' && c <= '9') { ! 456: *pp++ = '\\'; ! 457: *pp++ = c; ! 458: continue; ! 459: } ! 460: default: ! 461: *pp++ = c; ! 462: continue; ! 463: } ! 464: } ! 465: *pp++ = '\0'; ! 466: sp = (SUB *)salloc(sizeof (SUB)); ! 467: sp->s_pat = duplstr(pattbuf); ! 468: sp->s_rep = duplstr(holdbuf); ! 469: sp->s_nth = nth; ! 470: sp->s_cop = 0; ! 471: sp->s_fil = NULL; ! 472: while ((c=getn()) != '\0') { ! 473: switch (c) { ! 474: case 'g': ! 475: sp->s_nth = 0; ! 476: continue; ! 477: case 'p': ! 478: sp->s_cop = 1; ! 479: continue; ! 480: case 'w': ! 481: sp->s_fil = codefil(); ! 482: continue; ! 483: default: ! 484: printc("Bad flag in substitute"); ! 485: free(sp->s_pat); ! 486: free(sp->s_rep); ! 487: free(sp); ! 488: return NULL; ! 489: } ! 490: } ! 491: return sp; ! 492: } ! 493: ! 494: /* ! 495: * Compile a regular expression. `ec' is the character upon which ! 496: * the regular expression ends. If an error is encountered, the ! 497: * pattern is cleared and input characters are thrown away until ! 498: * a new line is found. ! 499: */ ! 500: compile(ec) ! 501: { ! 502: int bstack[NBRC], bcount, blevel, n; ! 503: register int c; ! 504: register char *pp, *lpp; ! 505: ! 506: bcount = 1; ! 507: blevel = 0; ! 508: pp = &pattbuf[0]; ! 509: if ((c=getn()) == ec) { ! 510: if (*pp == CSNUL) { ! 511: printc("No saved pattern"); ! 512: goto err; ! 513: } ! 514: return 1; ! 515: } ! 516: if (c == '^') { ! 517: *pp++ = CSSOL; ! 518: c = getn(); ! 519: } ! 520: while (c != ec) { ! 521: if (pp > &pattbuf[LHPSIZE-4]) ! 522: goto ovf; ! 523: switch (c) { ! 524: case '\0': ! 525: case '.': ! 526: if ((c=getn()) != '*') { ! 527: *pp++ = CSDOT; ! 528: continue; ! 529: } ! 530: *pp++ = CMDOT; ! 531: c = getn(); ! 532: continue; ! 533: case '$': ! 534: if ((c=getn()) != ec) { ! 535: ungetn(c); ! 536: c = '$'; ! 537: goto character; ! 538: } ! 539: *pp++ = CSEOL; ! 540: continue; ! 541: case '[': ! 542: lpp = pp; ! 543: if ((c=getn()) == '^') ! 544: *pp++ = CSNCL; ! 545: else { ! 546: ungetn(c); ! 547: *pp++ = CSCCL; ! 548: } ! 549: *pp++ = 0; ! 550: if ((c=getn()) == ']') ! 551: *pp++ = c; ! 552: else ! 553: ungetn(c); ! 554: while ((c=getn()) != ']') { ! 555: if (c == '\n') ! 556: goto nwl; ! 557: if (c!='-' || pp==lpp+2) { ! 558: if (pp >= &pattbuf[LHPSIZE-4]) ! 559: goto ovf; ! 560: *pp++ = c; ! 561: if (sflag && isascii(c) && isallet(c)) ! 562: *pp++ = toother(c); ! 563: continue; ! 564: } ! 565: if ((c=getn()) == '\n') ! 566: goto nwl; ! 567: if (c == ']') { ! 568: *pp++ = '-'; ! 569: ungetn(c); ! 570: continue; ! 571: } ! 572: if ((n=pp[-1]) > c) ! 573: goto syn; ! 574: while (++n <= c) { ! 575: if (pp >= &pattbuf[LHPSIZE-4]) ! 576: goto ovf; ! 577: *pp++ = n; ! 578: if (sflag && isascii(c) && isallet(c)) ! 579: *pp++ = toother(c); ! 580: } ! 581: } ! 582: if ((c=getn()) == '*') { ! 583: (*lpp)++; ! 584: c = getn(); ! 585: } ! 586: if ((n=pp-(lpp+2)) > 255) { ! 587: printc("Character class too large"); ! 588: goto err; ! 589: } ! 590: *++lpp = n; ! 591: continue; ! 592: case '\\': ! 593: switch (c=getn()) { ! 594: case '\n': ! 595: goto nwl; ! 596: case '(': ! 597: if (bcount > NBRC) { ! 598: printc("Too many \\("); ! 599: goto err; ! 600: } ! 601: *pp++ = CSOPR; ! 602: *pp++ = bstack[blevel++] = bcount++; ! 603: c = getn(); ! 604: continue; ! 605: case ')': ! 606: if (blevel == 0) ! 607: goto syn; ! 608: *pp++ = CSCPR; ! 609: *pp++ = bstack[--blevel]; ! 610: c = getn(); ! 611: continue; ! 612: case 'n': ! 613: c = '\n'; ! 614: goto character; ! 615: default: ! 616: if (isascii(c) && isdigit(c)) { ! 617: *pp++ = CSBRN; ! 618: *pp++ = c-'0'; ! 619: c = getn(); ! 620: continue; ! 621: } ! 622: } ! 623: case '*': ! 624: default: ! 625: character: ! 626: if (sflag && isascii(c) && isallet(c)) { ! 627: *pp++ = CSSCC; ! 628: if (isupper(c)) ! 629: c = tolower(c); ! 630: } else ! 631: *pp++ = CSCHR; ! 632: *pp++ = c; ! 633: if ((c=getn()) == '*') { ! 634: pp[-2]++; ! 635: c = getn(); ! 636: } ! 637: } ! 638: } ! 639: *pp++ = CSNUL; ! 640: return 1; ! 641: ovf: ! 642: printc("Pattern buffer overflow"); ! 643: pattbuf[0] = CSNUL; ! 644: return 0; ! 645: nwl: ! 646: ungetn(c); ! 647: syn: ! 648: printc("Syntax error"); ! 649: err: ! 650: pattbuf[0] = CSNUL; ! 651: return 0; ! 652: } ! 653: ! 654: /* ! 655: * Compile the translate command. ! 656: */ ! 657: char * ! 658: codetrn() ! 659: { ! 660: int ec; ! 661: char *trnp; ! 662: register int c, n; ! 663: register char *bp; ! 664: ! 665: trnp = salloc(256); ! 666: bp = trnp; ! 667: for (n=0; n<256; n++) ! 668: *bp++ = n; ! 669: if ((ec=getn()) == '\0') { ! 670: printc("Syntax error"); ! 671: return NULL; ! 672: } ! 673: bp = pattbuf; ! 674: while ((c=getn()) != ec) { ! 675: if (c == '\0') { ! 676: printc("Syntax error"); ! 677: return NULL; ! 678: } ! 679: if (bp >= &pattbuf[LHPSIZE-1]) { ! 680: printc("Code buffer overflow"); ! 681: return NULL; ! 682: } ! 683: *bp++ = c&0377; ! 684: } ! 685: bp = pattbuf; ! 686: while ((c=getn()) != ec) { ! 687: if (c == '\0') { ! 688: printc("Syntax error"); ! 689: return NULL; ! 690: } ! 691: if (*bp == '\0') { ! 692: printc("Right part of translate too long"); ! 693: return NULL; ! 694: } ! 695: trnp[*bp++] = c; ! 696: } ! 697: return trnp; ! 698: } ! 699: ! 700: /* ! 701: * Given a string, return a pointer to a copy of it. ! 702: */ ! 703: char * ! 704: duplstr(s) register char *s; ! 705: { ! 706: return strcpy(salloc(strlen(s)+1), s); ! 707: } ! 708: ! 709: /* ! 710: * Get a character. ! 711: */ ! 712: getn() ! 713: { ! 714: register int c; ! 715: ! 716: if ((c = *ncp++) == '\0') ! 717: --ncp; ! 718: return c; ! 719: } ! 720: ! 721: /* ! 722: * Unget a character. ! 723: */ ! 724: ungetn(c) ! 725: { ! 726: if (*ncp!='\0' || c!='\0') ! 727: *--ncp = c; ! 728: } ! 729: ! 730: /* ! 731: * Go through the command list fixing up labels and files. ! 732: */ ! 733: load() ! 734: { ! 735: register LAB *lp; ! 736: register FIL *fp; ! 737: ! 738: *compp = NULL; ! 739: if (qcbp != NULL) ! 740: printc("Missing `}'"); ! 741: for (lp=labp; lp; lp=lp->l_next) { ! 742: if (lp->l_comp == NULL) ! 743: printc("Undefined label %s", lp->l_name); ! 744: } ! 745: for (fp=filp; fp; fp=fp->f_next) { ! 746: if (fp->f_filp == NULL) ! 747: if ((fp->f_filp=fopen(fp->f_name, "w")) == NULL) ! 748: printc("Cannot open %s", fp->f_name); ! 749: } ! 750: } ! 751: ! 752: /* ! 753: * Print out a compile error message. ! 754: */ ! 755: printc(s) ! 756: { ! 757: nerr++; ! 758: fprintf(stderr, "%d: %r", lno, &s); ! 759: putc('\n', stderr); ! 760: } ! 761: ! 762: /* end of sed/sed2.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.