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