1: /* sed0.c 4.2 85/06/19 */ 2: 3: #include <stdio.h> 4: #include "sed.h" 5: 6: struct label *labtab = ltab; 7: char CGMES[] = "command garbled: %s\n"; 8: char TMMES[] = "Too much text: %s\n"; 9: char LTL[] = "Label too long: %s\n"; 10: char AD0MES[] = "No addresses allowed: %s\n"; 11: char AD1MES[] = "Only one address allowed: %s\n"; 12: char bittab[] = { 13: 1, 14: 2, 15: 4, 16: 8, 17: 16, 18: 32, 19: 64, 20: 128 21: }; 22: 23: main(argc, argv) 24: char *argv[]; 25: { 26: 27: eargc = argc; 28: eargv = argv; 29: 30: badp = &bad; 31: aptr = abuf; 32: lab = labtab + 1; /* 0 reserved for end-pointer */ 33: rep = ptrspace; 34: rep->ad1 = respace; 35: lbend = &linebuf[LBSIZE]; 36: hend = &holdsp[LBSIZE]; 37: lcomend = &genbuf[71]; 38: ptrend = &ptrspace[PTRSIZE]; 39: reend = &respace[RESIZE]; 40: labend = &labtab[LABSIZE]; 41: lnum = 0; 42: pending = 0; 43: depth = 0; 44: spend = linebuf; 45: hspend = holdsp; 46: fcode[0] = stdout; 47: nfiles = 1; 48: 49: if(eargc == 1) 50: exit(0); 51: 52: 53: while (--eargc > 0 && (++eargv)[0][0] == '-') 54: switch (eargv[0][1]) { 55: 56: case 'n': 57: nflag++; 58: continue; 59: 60: case 'f': 61: if(eargc-- <= 0) exit(2); 62: 63: if((fin = fopen(*++eargv, "r")) == NULL) { 64: fprintf(stderr, "Cannot open pattern-file: %s\n", *eargv); 65: exit(2); 66: } 67: 68: fcomp(); 69: fclose(fin); 70: continue; 71: 72: case 'e': 73: eflag++; 74: fcomp(); 75: eflag = 0; 76: continue; 77: 78: case 'g': 79: gflag++; 80: continue; 81: 82: default: 83: fprintf(stdout, "Unknown flag: %c\n", eargv[0][1]); 84: continue; 85: } 86: 87: 88: if(compfl == 0) { 89: eargv--; 90: eargc++; 91: eflag++; 92: fcomp(); 93: eargv++; 94: eargc--; 95: eflag = 0; 96: } 97: 98: if(depth) { 99: fprintf(stderr, "Too many {'s"); 100: exit(2); 101: } 102: 103: labtab->address = rep; 104: 105: dechain(); 106: 107: /* abort(); /*DEBUG*/ 108: 109: if(eargc <= 0) 110: execute((char *)NULL); 111: else while(--eargc >= 0) { 112: execute(*eargv++); 113: } 114: fclose(stdout); 115: exit(0); 116: } 117: fcomp() 118: { 119: 120: register char *p, *op, *tp; 121: char *address(); 122: union reptr *pt, *pt1; 123: int i; 124: struct label *lpt; 125: 126: compfl = 1; 127: op = lastre; 128: 129: if(rline(linebuf) < 0) return; 130: if(*linebuf == '#') { 131: if(linebuf[1] == 'n') 132: nflag = 1; 133: } 134: else { 135: cp = linebuf; 136: goto comploop; 137: } 138: 139: for(;;) { 140: if(rline(linebuf) < 0) break; 141: 142: cp = linebuf; 143: 144: comploop: 145: /* fprintf(stdout, "cp: %s\n", cp); /*DEBUG*/ 146: while(*cp == ' ' || *cp == '\t') cp++; 147: if(*cp == '\0' || *cp == '#') continue; 148: if(*cp == ';') { 149: cp++; 150: goto comploop; 151: } 152: 153: p = address(rep->ad1); 154: if(p == badp) { 155: fprintf(stderr, CGMES, linebuf); 156: exit(2); 157: } 158: 159: if(p == rep->ad1) { 160: if(op) 161: rep->ad1 = op; 162: else { 163: fprintf(stderr, "First RE may not be null\n"); 164: exit(2); 165: } 166: } else if(p == 0) { 167: p = rep->ad1; 168: rep->ad1 = 0; 169: } else { 170: op = rep->ad1; 171: if(*cp == ',' || *cp == ';') { 172: cp++; 173: if((rep->ad2 = p) > reend) { 174: fprintf(stderr, TMMES, linebuf); 175: exit(2); 176: } 177: p = address(rep->ad2); 178: if(p == badp || p == 0) { 179: fprintf(stderr, CGMES, linebuf); 180: exit(2); 181: } 182: if(p == rep->ad2) 183: rep->ad2 = op; 184: else 185: op = rep->ad2; 186: 187: } else 188: rep->ad2 = 0; 189: } 190: 191: if(p > reend) { 192: fprintf(stderr, "Too much text: %s\n", linebuf); 193: exit(2); 194: } 195: 196: while(*cp == ' ' || *cp == '\t') cp++; 197: 198: swit: 199: switch(*cp++) { 200: 201: default: 202: fprintf(stderr, "Unrecognized command: %s\n", linebuf); 203: exit(2); 204: 205: case '!': 206: rep->negfl = 1; 207: goto swit; 208: 209: case '{': 210: rep->command = BCOM; 211: rep->negfl = !(rep->negfl); 212: cmpend[depth++] = &rep->lb1; 213: if(++rep >= ptrend) { 214: fprintf(stderr, "Too many commands: %s\n", linebuf); 215: exit(2); 216: } 217: rep->ad1 = p; 218: if(*cp == '\0') continue; 219: 220: goto comploop; 221: 222: case '}': 223: if(rep->ad1) { 224: fprintf(stderr, AD0MES, linebuf); 225: exit(2); 226: } 227: 228: if(--depth < 0) { 229: fprintf(stderr, "Too many }'s\n"); 230: exit(2); 231: } 232: *cmpend[depth] = rep; 233: 234: rep->ad1 = p; 235: continue; 236: 237: case '=': 238: rep->command = EQCOM; 239: if(rep->ad2) { 240: fprintf(stderr, AD1MES, linebuf); 241: exit(2); 242: } 243: break; 244: 245: case ':': 246: if(rep->ad1) { 247: fprintf(stderr, AD0MES, linebuf); 248: exit(2); 249: } 250: 251: while(*cp++ == ' '); 252: cp--; 253: 254: 255: tp = lab->asc; 256: while((*tp++ = *cp++)) 257: if(tp >= &(lab->asc[8])) { 258: fprintf(stderr, LTL, linebuf); 259: exit(2); 260: } 261: *--tp = '\0'; 262: 263: if(lpt = search(lab)) { 264: if(lpt->address) { 265: fprintf(stderr, "Duplicate labels: %s\n", linebuf); 266: exit(2); 267: } 268: } else { 269: lab->chain = 0; 270: lpt = lab; 271: if(++lab >= labend) { 272: fprintf(stderr, "Too many labels: %s\n", linebuf); 273: exit(2); 274: } 275: } 276: lpt->address = rep; 277: rep->ad1 = p; 278: 279: continue; 280: 281: case 'a': 282: rep->command = ACOM; 283: if(rep->ad2) { 284: fprintf(stderr, AD1MES, linebuf); 285: exit(2); 286: } 287: if(*cp == '\\') cp++; 288: if(*cp++ != '\n') { 289: fprintf(stderr, CGMES, linebuf); 290: exit(2); 291: } 292: rep->re1 = p; 293: p = text(rep->re1); 294: break; 295: case 'c': 296: rep->command = CCOM; 297: if(*cp == '\\') cp++; 298: if(*cp++ != ('\n')) { 299: fprintf(stderr, CGMES, linebuf); 300: exit(2); 301: } 302: rep->re1 = p; 303: p = text(rep->re1); 304: break; 305: case 'i': 306: rep->command = ICOM; 307: if(rep->ad2) { 308: fprintf(stderr, AD1MES, linebuf); 309: exit(2); 310: } 311: if(*cp == '\\') cp++; 312: if(*cp++ != ('\n')) { 313: fprintf(stderr, CGMES, linebuf); 314: exit(2); 315: } 316: rep->re1 = p; 317: p = text(rep->re1); 318: break; 319: 320: case 'g': 321: rep->command = GCOM; 322: break; 323: 324: case 'G': 325: rep->command = CGCOM; 326: break; 327: 328: case 'h': 329: rep->command = HCOM; 330: break; 331: 332: case 'H': 333: rep->command = CHCOM; 334: break; 335: 336: case 't': 337: rep->command = TCOM; 338: goto jtcommon; 339: 340: case 'b': 341: rep->command = BCOM; 342: jtcommon: 343: while(*cp++ == ' '); 344: cp--; 345: 346: if(*cp == '\0') { 347: if(pt = labtab->chain) { 348: while(pt1 = pt->lb1) 349: pt = pt1; 350: pt->lb1 = rep; 351: } else 352: labtab->chain = rep; 353: break; 354: } 355: tp = lab->asc; 356: while((*tp++ = *cp++)) 357: if(tp >= &(lab->asc[8])) { 358: fprintf(stderr, LTL, linebuf); 359: exit(2); 360: } 361: cp--; 362: *--tp = '\0'; 363: 364: if(lpt = search(lab)) { 365: if(lpt->address) { 366: rep->lb1 = lpt->address; 367: } else { 368: pt = lpt->chain; 369: while(pt1 = pt->lb1) 370: pt = pt1; 371: pt->lb1 = rep; 372: } 373: } else { 374: lab->chain = rep; 375: lab->address = 0; 376: if(++lab >= labend) { 377: fprintf(stderr, "Too many labels: %s\n", linebuf); 378: exit(2); 379: } 380: } 381: break; 382: 383: case 'n': 384: rep->command = NCOM; 385: break; 386: 387: case 'N': 388: rep->command = CNCOM; 389: break; 390: 391: case 'p': 392: rep->command = PCOM; 393: break; 394: 395: case 'P': 396: rep->command = CPCOM; 397: break; 398: 399: case 'r': 400: rep->command = RCOM; 401: if(rep->ad2) { 402: fprintf(stderr, AD1MES, linebuf); 403: exit(2); 404: } 405: if(*cp++ != ' ') { 406: fprintf(stderr, CGMES, linebuf); 407: exit(2); 408: } 409: rep->re1 = p; 410: p = text(rep->re1); 411: break; 412: 413: case 'd': 414: rep->command = DCOM; 415: break; 416: 417: case 'D': 418: rep->command = CDCOM; 419: rep->lb1 = ptrspace; 420: break; 421: 422: case 'q': 423: rep->command = QCOM; 424: if(rep->ad2) { 425: fprintf(stderr, AD1MES, linebuf); 426: exit(2); 427: } 428: break; 429: 430: case 'l': 431: rep->command = LCOM; 432: break; 433: 434: case 's': 435: rep->command = SCOM; 436: seof = *cp++; 437: rep->re1 = p; 438: p = compile(rep->re1); 439: if(p == badp) { 440: fprintf(stderr, CGMES, linebuf); 441: exit(2); 442: } 443: if(p == rep->re1) { 444: if(op) 445: rep->re1 = op; 446: else { 447: fprintf(stderr, 448: "First RE may not be null\n"); 449: exit(2); 450: } 451: } else { 452: op = rep->re1; 453: } 454: 455: if((rep->rhs = p) > reend) { 456: fprintf(stderr, TMMES, linebuf); 457: exit(2); 458: } 459: 460: if((p = compsub(rep->rhs)) == badp) { 461: fprintf(stderr, CGMES, linebuf); 462: exit(2); 463: } 464: if(*cp == 'g') { 465: cp++; 466: rep->gfl++; 467: } else if(gflag) 468: rep->gfl++; 469: 470: if(*cp == 'p') { 471: cp++; 472: rep->pfl = 1; 473: } 474: 475: if(*cp == 'P') { 476: cp++; 477: rep->pfl = 2; 478: } 479: 480: if(*cp == 'w') { 481: cp++; 482: if(*cp++ != ' ') { 483: fprintf(stderr, CGMES, linebuf); 484: exit(2); 485: } 486: if(nfiles >= 10) { 487: fprintf(stderr, "Too many files in w commands\n"); 488: exit(2); 489: } 490: 491: text(fname[nfiles]); 492: for(i = nfiles - 1; i >= 0; i--) 493: if(cmp(fname[nfiles],fname[i]) == 0) { 494: rep->fcode = fcode[i]; 495: goto done; 496: } 497: if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) { 498: fprintf(stderr, "cannot open %s\n", fname[nfiles]); 499: exit(2); 500: } 501: fcode[nfiles++] = rep->fcode; 502: } 503: break; 504: 505: case 'w': 506: rep->command = WCOM; 507: if(*cp++ != ' ') { 508: fprintf(stderr, CGMES, linebuf); 509: exit(2); 510: } 511: if(nfiles >= 10){ 512: fprintf(stderr, "Too many files in w commands\n"); 513: exit(2); 514: } 515: 516: text(fname[nfiles]); 517: for(i = nfiles - 1; i >= 0; i--) 518: if(cmp(fname[nfiles], fname[i]) == 0) { 519: rep->fcode = fcode[i]; 520: goto done; 521: } 522: 523: if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) { 524: fprintf(stderr, "Cannot create %s\n", fname[nfiles]); 525: exit(2); 526: } 527: fcode[nfiles++] = rep->fcode; 528: break; 529: 530: case 'x': 531: rep->command = XCOM; 532: break; 533: 534: case 'y': 535: rep->command = YCOM; 536: seof = *cp++; 537: rep->re1 = p; 538: p = ycomp(rep->re1); 539: if(p == badp) { 540: fprintf(stderr, CGMES, linebuf); 541: exit(2); 542: } 543: if(p > reend) { 544: fprintf(stderr, TMMES, linebuf); 545: exit(2); 546: } 547: break; 548: 549: } 550: done: 551: if(++rep >= ptrend) { 552: fprintf(stderr, "Too many commands, last: %s\n", linebuf); 553: exit(2); 554: } 555: 556: rep->ad1 = p; 557: 558: if(*cp++ != '\0') { 559: if(cp[-1] == ';') 560: goto comploop; 561: fprintf(stderr, CGMES, linebuf); 562: exit(2); 563: } 564: 565: } 566: rep->command = 0; 567: lastre = op; 568: } 569: char *compsub(rhsbuf) 570: char *rhsbuf; 571: { 572: register char *p, *q; 573: 574: p = rhsbuf; 575: q = cp; 576: for(;;) { 577: if((*p = *q++) == '\\') { 578: *p = *q++; 579: if(*p > numbra + '0' && *p <= '9') 580: return(badp); 581: *p++ |= 0200; 582: continue; 583: } 584: if(*p == seof) { 585: *p++ = '\0'; 586: cp = q; 587: return(p); 588: } 589: if(*p++ == '\0') { 590: return(badp); 591: } 592: 593: } 594: } 595: 596: char *compile(expbuf) 597: char *expbuf; 598: { 599: register c; 600: register char *ep, *sp; 601: char neg; 602: char *lastep, *cstart; 603: int cclcnt; 604: int closed; 605: char bracket[NBRA], *bracketp; 606: 607: if(*cp == seof) { 608: cp++; 609: return(expbuf); 610: } 611: 612: ep = expbuf; 613: lastep = 0; 614: bracketp = bracket; 615: closed = numbra = 0; 616: sp = cp; 617: if (*sp == '^') { 618: *ep++ = 1; 619: sp++; 620: } else { 621: *ep++ = 0; 622: } 623: for (;;) { 624: if (ep >= &expbuf[ESIZE]) { 625: cp = sp; 626: return(badp); 627: } 628: if((c = *sp++) == seof) { 629: if(bracketp != bracket) { 630: cp = sp; 631: return(badp); 632: } 633: cp = sp; 634: *ep++ = CEOF; 635: return(ep); 636: } 637: if(c != '*') 638: lastep = ep; 639: switch (c) { 640: 641: case '\\': 642: if((c = *sp++) == '(') { 643: if(numbra >= NBRA) { 644: cp = sp; 645: return(badp); 646: } 647: *bracketp++ = numbra; 648: *ep++ = CBRA; 649: *ep++ = numbra++; 650: continue; 651: } 652: if(c == ')') { 653: if(bracketp <= bracket) { 654: cp = sp; 655: return(badp); 656: } 657: *ep++ = CKET; 658: *ep++ = *--bracketp; 659: closed++; 660: continue; 661: } 662: 663: if(c >= '1' && c <= '9') { 664: if((c -= '1') >= closed) 665: return(badp); 666: 667: *ep++ = CBACK; 668: *ep++ = c; 669: continue; 670: } 671: if(c == '\n') { 672: cp = sp; 673: return(badp); 674: } 675: if(c == 'n') { 676: c = '\n'; 677: } 678: goto defchar; 679: 680: case '\0': 681: continue; 682: case '\n': 683: cp = sp; 684: return(badp); 685: 686: case '.': 687: *ep++ = CDOT; 688: continue; 689: 690: case '*': 691: if (lastep == 0) 692: goto defchar; 693: if(*lastep == CKET) { 694: cp = sp; 695: return(badp); 696: } 697: *lastep |= STAR; 698: continue; 699: 700: case '$': 701: if (*sp != seof) 702: goto defchar; 703: *ep++ = CDOL; 704: continue; 705: 706: case '[': 707: if(&ep[17] >= &expbuf[ESIZE]) { 708: fprintf(stderr, "RE too long: %s\n", linebuf); 709: exit(2); 710: } 711: 712: *ep++ = CCL; 713: 714: neg = 0; 715: if((c = *sp++) == '^') { 716: neg = 1; 717: c = *sp++; 718: } 719: 720: cstart = sp; 721: do { 722: if(c == '\0') { 723: fprintf(stderr, CGMES, linebuf); 724: exit(2); 725: } 726: if (c=='-' && sp>cstart && *sp!=']') { 727: for (c = sp[-2]; c<*sp; c++) 728: ep[c>>3] |= bittab[c&07]; 729: } 730: if(c == '\\') { 731: switch(c = *sp++) { 732: case 'n': 733: c = '\n'; 734: break; 735: } 736: } 737: 738: ep[c >> 3] |= bittab[c & 07]; 739: } while((c = *sp++) != ']'); 740: 741: if(neg) 742: for(cclcnt = 0; cclcnt < 16; cclcnt++) 743: ep[cclcnt] ^= -1; 744: ep[0] &= 0376; 745: 746: ep += 16; 747: 748: continue; 749: 750: defchar: 751: default: 752: *ep++ = CCHR; 753: *ep++ = c; 754: } 755: } 756: } 757: rline(lbuf) 758: char *lbuf; 759: { 760: register char *p, *q; 761: register t; 762: static char *saveq; 763: 764: p = lbuf - 1; 765: 766: if(eflag) { 767: if(eflag > 0) { 768: eflag = -1; 769: if(eargc-- <= 0) 770: exit(2); 771: q = *++eargv; 772: while(*++p = *q++) { 773: if(*p == '\\') { 774: if((*++p = *q++) == '\0') { 775: saveq = 0; 776: return(-1); 777: } else 778: continue; 779: } 780: if(*p == '\n') { 781: *p = '\0'; 782: saveq = q; 783: return(1); 784: } 785: } 786: saveq = 0; 787: return(1); 788: } 789: if((q = saveq) == 0) return(-1); 790: 791: while(*++p = *q++) { 792: if(*p == '\\') { 793: if((*++p = *q++) == '0') { 794: saveq = 0; 795: return(-1); 796: } else 797: continue; 798: } 799: if(*p == '\n') { 800: *p = '\0'; 801: saveq = q; 802: return(1); 803: } 804: } 805: saveq = 0; 806: return(1); 807: } 808: 809: while((t = getc(fin)) != EOF) { 810: *++p = t; 811: if(*p == '\\') { 812: t = getc(fin); 813: *++p = t; 814: } 815: else if(*p == '\n') { 816: *p = '\0'; 817: return(1); 818: } 819: } 820: *++p = '\0'; 821: return(-1); 822: } 823: 824: char *address(expbuf) 825: char *expbuf; 826: { 827: register char *rcp; 828: long lno; 829: 830: if(*cp == '$') { 831: cp++; 832: *expbuf++ = CEND; 833: *expbuf++ = CEOF; 834: return(expbuf); 835: } 836: 837: if(*cp == '/') { 838: seof = '/'; 839: cp++; 840: return(compile(expbuf)); 841: } 842: 843: rcp = cp; 844: lno = 0; 845: 846: while(*rcp >= '0' && *rcp <= '9') 847: lno = lno*10 + *rcp++ - '0'; 848: 849: if(rcp > cp) { 850: *expbuf++ = CLNUM; 851: *expbuf++ = nlno; 852: tlno[nlno++] = lno; 853: if(nlno >= NLINES) { 854: fprintf(stderr, "Too many line numbers\n"); 855: exit(2); 856: } 857: *expbuf++ = CEOF; 858: cp = rcp; 859: return(expbuf); 860: } 861: return(0); 862: } 863: cmp(a, b) 864: char *a,*b; 865: { 866: register char *ra, *rb; 867: 868: ra = a - 1; 869: rb = b - 1; 870: 871: while(*++ra == *++rb) 872: if(*ra == '\0') return(0); 873: return(1); 874: } 875: 876: char *text(textbuf) 877: char *textbuf; 878: { 879: register char *p, *q; 880: 881: p = textbuf; 882: q = cp; 883: while(*q == '\t' || *q == ' ') q++; 884: for(;;) { 885: 886: if((*p = *q++) == '\\') 887: *p = *q++; 888: if(*p == '\0') { 889: cp = --q; 890: return(++p); 891: } 892: if(*p == '\n') { 893: while(*q == '\t' || *q == ' ') q++; 894: } 895: p++; 896: } 897: } 898: 899: 900: struct label *search(ptr) 901: struct label *ptr; 902: { 903: struct label *rp; 904: 905: rp = labtab; 906: while(rp < ptr) { 907: if(cmp(rp->asc, ptr->asc) == 0) 908: return(rp); 909: rp++; 910: } 911: 912: return(0); 913: } 914: 915: 916: dechain() 917: { 918: struct label *lptr; 919: union reptr *rptr, *trptr; 920: 921: for(lptr = labtab; lptr < lab; lptr++) { 922: 923: if(lptr->address == 0) { 924: fprintf(stderr, "Undefined label: %s\n", lptr->asc); 925: exit(2); 926: } 927: 928: if(lptr->chain) { 929: rptr = lptr->chain; 930: while(trptr = rptr->lb1) { 931: rptr->lb1 = lptr->address; 932: rptr = trptr; 933: } 934: rptr->lb1 = lptr->address; 935: } 936: } 937: } 938: 939: char *ycomp(expbuf) 940: char *expbuf; 941: { 942: register char c, *ep, *tsp; 943: char *sp; 944: 945: ep = expbuf; 946: sp = cp; 947: for(tsp = cp; *tsp != seof; tsp++) { 948: if(*tsp == '\\') 949: tsp++; 950: if(*tsp == '\n') 951: return(badp); 952: } 953: tsp++; 954: 955: while((c = *sp++ & 0177) != seof) { 956: if(c == '\\' && *sp == 'n') { 957: sp++; 958: c = '\n'; 959: } 960: if((ep[c] = *tsp++) == '\\' && *tsp == 'n') { 961: ep[c] = '\n'; 962: tsp++; 963: } 964: if(ep[c] == seof || ep[c] == '\0') 965: return(badp); 966: } 967: if(*tsp != seof) 968: return(badp); 969: cp = ++tsp; 970: 971: for(c = 0; !(c & 0200); c++) 972: if(ep[c] == 0) 973: ep[c] = c; 974: 975: return(ep + 0200); 976: }