1 /* sed0.c 4.1 85/04/05 */ 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 rep->re1 = op; 445 } else { 446 op = rep->re1; 447 } 448 449 if((rep->rhs = p) > reend) { 450 fprintf(stderr, TMMES, linebuf); 451 exit(2); 452 } 453 454 if((p = compsub(rep->rhs)) == badp) { 455 fprintf(stderr, CGMES, linebuf); 456 exit(2); 457 } 458 if(*cp == 'g') { 459 cp++; 460 rep->gfl++; 461 } else if(gflag) 462 rep->gfl++; 463 464 if(*cp == 'p') { 465 cp++; 466 rep->pfl = 1; 467 } 468 469 if(*cp == 'P') { 470 cp++; 471 rep->pfl = 2; 472 } 473 474 if(*cp == 'w') { 475 cp++; 476 if(*cp++ != ' ') { 477 fprintf(stderr, CGMES, linebuf); 478 exit(2); 479 } 480 if(nfiles >= 10) { 481 fprintf(stderr, "Too many files in w commands\n"); 482 exit(2); 483 } 484 485 text(fname[nfiles]); 486 for(i = nfiles - 1; i >= 0; i--) 487 if(cmp(fname[nfiles],fname[i]) == 0) { 488 rep->fcode = fcode[i]; 489 goto done; 490 } 491 if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) { 492 fprintf(stderr, "cannot open %s\n", fname[nfiles]); 493 exit(2); 494 } 495 fcode[nfiles++] = rep->fcode; 496 } 497 break; 498 499 case 'w': 500 rep->command = WCOM; 501 if(*cp++ != ' ') { 502 fprintf(stderr, CGMES, linebuf); 503 exit(2); 504 } 505 if(nfiles >= 10){ 506 fprintf(stderr, "Too many files in w commands\n"); 507 exit(2); 508 } 509 510 text(fname[nfiles]); 511 for(i = nfiles - 1; i >= 0; i--) 512 if(cmp(fname[nfiles], fname[i]) == 0) { 513 rep->fcode = fcode[i]; 514 goto done; 515 } 516 517 if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) { 518 fprintf(stderr, "Cannot create %s\n", fname[nfiles]); 519 exit(2); 520 } 521 fcode[nfiles++] = rep->fcode; 522 break; 523 524 case 'x': 525 rep->command = XCOM; 526 break; 527 528 case 'y': 529 rep->command = YCOM; 530 seof = *cp++; 531 rep->re1 = p; 532 p = ycomp(rep->re1); 533 if(p == badp) { 534 fprintf(stderr, CGMES, linebuf); 535 exit(2); 536 } 537 if(p > reend) { 538 fprintf(stderr, TMMES, linebuf); 539 exit(2); 540 } 541 break; 542 543 } 544 done: 545 if(++rep >= ptrend) { 546 fprintf(stderr, "Too many commands, last: %s\n", linebuf); 547 exit(2); 548 } 549 550 rep->ad1 = p; 551 552 if(*cp++ != '\0') { 553 if(cp[-1] == ';') 554 goto comploop; 555 fprintf(stderr, CGMES, linebuf); 556 exit(2); 557 } 558 559 } 560 rep->command = 0; 561 lastre = op; 562 } 563 char *compsub(rhsbuf) 564 char *rhsbuf; 565 { 566 register char *p, *q; 567 568 p = rhsbuf; 569 q = cp; 570 for(;;) { 571 if((*p = *q++) == '\\') { 572 *p = *q++; 573 if(*p > numbra + '0' && *p <= '9') 574 return(badp); 575 *p++ |= 0200; 576 continue; 577 } 578 if(*p == seof) { 579 *p++ = '\0'; 580 cp = q; 581 return(p); 582 } 583 if(*p++ == '\0') { 584 return(badp); 585 } 586 587 } 588 } 589 590 char *compile(expbuf) 591 char *expbuf; 592 { 593 register c; 594 register char *ep, *sp; 595 char neg; 596 char *lastep, *cstart; 597 int cclcnt; 598 int closed; 599 char bracket[NBRA], *bracketp; 600 601 if(*cp == seof) { 602 cp++; 603 return(expbuf); 604 } 605 606 ep = expbuf; 607 lastep = 0; 608 bracketp = bracket; 609 closed = numbra = 0; 610 sp = cp; 611 if (*sp == '^') { 612 *ep++ = 1; 613 sp++; 614 } else { 615 *ep++ = 0; 616 } 617 for (;;) { 618 if (ep >= &expbuf[ESIZE]) { 619 cp = sp; 620 return(badp); 621 } 622 if((c = *sp++) == seof) { 623 if(bracketp != bracket) { 624 cp = sp; 625 return(badp); 626 } 627 cp = sp; 628 *ep++ = CEOF; 629 return(ep); 630 } 631 if(c != '*') 632 lastep = ep; 633 switch (c) { 634 635 case '\\': 636 if((c = *sp++) == '(') { 637 if(numbra >= NBRA) { 638 cp = sp; 639 return(badp); 640 } 641 *bracketp++ = numbra; 642 *ep++ = CBRA; 643 *ep++ = numbra++; 644 continue; 645 } 646 if(c == ')') { 647 if(bracketp <= bracket) { 648 cp = sp; 649 return(badp); 650 } 651 *ep++ = CKET; 652 *ep++ = *--bracketp; 653 closed++; 654 continue; 655 } 656 657 if(c >= '1' && c <= '9') { 658 if((c -= '1') >= closed) 659 return(badp); 660 661 *ep++ = CBACK; 662 *ep++ = c; 663 continue; 664 } 665 if(c == '\n') { 666 cp = sp; 667 return(badp); 668 } 669 if(c == 'n') { 670 c = '\n'; 671 } 672 goto defchar; 673 674 case '\0': 675 continue; 676 case '\n': 677 cp = sp; 678 return(badp); 679 680 case '.': 681 *ep++ = CDOT; 682 continue; 683 684 case '*': 685 if (lastep == 0) 686 goto defchar; 687 if(*lastep == CKET) { 688 cp = sp; 689 return(badp); 690 } 691 *lastep |= STAR; 692 continue; 693 694 case '$': 695 if (*sp != seof) 696 goto defchar; 697 *ep++ = CDOL; 698 continue; 699 700 case '[': 701 if(&ep[17] >= &expbuf[ESIZE]) { 702 fprintf(stderr, "RE too long: %s\n", linebuf); 703 exit(2); 704 } 705 706 *ep++ = CCL; 707 708 neg = 0; 709 if((c = *sp++) == '^') { 710 neg = 1; 711 c = *sp++; 712 } 713 714 cstart = sp; 715 do { 716 if(c == '\0') { 717 fprintf(stderr, CGMES, linebuf); 718 exit(2); 719 } 720 if (c=='-' && sp>cstart && *sp!=']') { 721 for (c = sp[-2]; c<*sp; c++) 722 ep[c>>3] |= bittab[c&07]; 723 } 724 if(c == '\\') { 725 switch(c = *sp++) { 726 case 'n': 727 c = '\n'; 728 break; 729 } 730 } 731 732 ep[c >> 3] |= bittab[c & 07]; 733 } while((c = *sp++) != ']'); 734 735 if(neg) 736 for(cclcnt = 0; cclcnt < 16; cclcnt++) 737 ep[cclcnt] ^= -1; 738 ep[0] &= 0376; 739 740 ep += 16; 741 742 continue; 743 744 defchar: 745 default: 746 *ep++ = CCHR; 747 *ep++ = c; 748 } 749 } 750 } 751 rline(lbuf) 752 char *lbuf; 753 { 754 register char *p, *q; 755 register t; 756 static char *saveq; 757 758 p = lbuf - 1; 759 760 if(eflag) { 761 if(eflag > 0) { 762 eflag = -1; 763 if(eargc-- <= 0) 764 exit(2); 765 q = *++eargv; 766 while(*++p = *q++) { 767 if(*p == '\\') { 768 if((*++p = *q++) == '\0') { 769 saveq = 0; 770 return(-1); 771 } else 772 continue; 773 } 774 if(*p == '\n') { 775 *p = '\0'; 776 saveq = q; 777 return(1); 778 } 779 } 780 saveq = 0; 781 return(1); 782 } 783 if((q = saveq) == 0) return(-1); 784 785 while(*++p = *q++) { 786 if(*p == '\\') { 787 if((*++p = *q++) == '0') { 788 saveq = 0; 789 return(-1); 790 } else 791 continue; 792 } 793 if(*p == '\n') { 794 *p = '\0'; 795 saveq = q; 796 return(1); 797 } 798 } 799 saveq = 0; 800 return(1); 801 } 802 803 while((t = getc(fin)) != EOF) { 804 *++p = t; 805 if(*p == '\\') { 806 t = getc(fin); 807 *++p = t; 808 } 809 else if(*p == '\n') { 810 *p = '\0'; 811 return(1); 812 } 813 } 814 *++p = '\0'; 815 return(-1); 816 } 817 818 char *address(expbuf) 819 char *expbuf; 820 { 821 register char *rcp; 822 long lno; 823 824 if(*cp == '$') { 825 cp++; 826 *expbuf++ = CEND; 827 *expbuf++ = CEOF; 828 return(expbuf); 829 } 830 831 if(*cp == '/') { 832 seof = '/'; 833 cp++; 834 return(compile(expbuf)); 835 } 836 837 rcp = cp; 838 lno = 0; 839 840 while(*rcp >= '0' && *rcp <= '9') 841 lno = lno*10 + *rcp++ - '0'; 842 843 if(rcp > cp) { 844 *expbuf++ = CLNUM; 845 *expbuf++ = nlno; 846 tlno[nlno++] = lno; 847 if(nlno >= NLINES) { 848 fprintf(stderr, "Too many line numbers\n"); 849 exit(2); 850 } 851 *expbuf++ = CEOF; 852 cp = rcp; 853 return(expbuf); 854 } 855 return(0); 856 } 857 cmp(a, b) 858 char *a,*b; 859 { 860 register char *ra, *rb; 861 862 ra = a - 1; 863 rb = b - 1; 864 865 while(*++ra == *++rb) 866 if(*ra == '\0') return(0); 867 return(1); 868 } 869 870 char *text(textbuf) 871 char *textbuf; 872 { 873 register char *p, *q; 874 875 p = textbuf; 876 q = cp; 877 while(*q == '\t' || *q == ' ') q++; 878 for(;;) { 879 880 if((*p = *q++) == '\\') 881 *p = *q++; 882 if(*p == '\0') { 883 cp = --q; 884 return(++p); 885 } 886 if(*p == '\n') { 887 while(*q == '\t' || *q == ' ') q++; 888 } 889 p++; 890 } 891 } 892 893 894 struct label *search(ptr) 895 struct label *ptr; 896 { 897 struct label *rp; 898 899 rp = labtab; 900 while(rp < ptr) { 901 if(cmp(rp->asc, ptr->asc) == 0) 902 return(rp); 903 rp++; 904 } 905 906 return(0); 907 } 908 909 910 dechain() 911 { 912 struct label *lptr; 913 union reptr *rptr, *trptr; 914 915 for(lptr = labtab; lptr < lab; lptr++) { 916 917 if(lptr->address == 0) { 918 fprintf(stderr, "Undefined label: %s\n", lptr->asc); 919 exit(2); 920 } 921 922 if(lptr->chain) { 923 rptr = lptr->chain; 924 while(trptr = rptr->lb1) { 925 rptr->lb1 = lptr->address; 926 rptr = trptr; 927 } 928 rptr->lb1 = lptr->address; 929 } 930 } 931 } 932 933 char *ycomp(expbuf) 934 char *expbuf; 935 { 936 register char c, *ep, *tsp; 937 char *sp; 938 939 ep = expbuf; 940 sp = cp; 941 for(tsp = cp; *tsp != seof; tsp++) { 942 if(*tsp == '\\') 943 tsp++; 944 if(*tsp == '\n') 945 return(badp); 946 } 947 tsp++; 948 949 while((c = *sp++ & 0177) != seof) { 950 if(c == '\\' && *sp == 'n') { 951 sp++; 952 c = '\n'; 953 } 954 if((ep[c] = *tsp++) == '\\' && *tsp == 'n') { 955 ep[c] = '\n'; 956 tsp++; 957 } 958 if(ep[c] == seof || ep[c] == '\0') 959 return(badp); 960 } 961 if(*tsp != seof) 962 return(badp); 963 cp = ++tsp; 964 965 for(c = 0; !(c & 0200); c++) 966 if(ep[c] == 0) 967 ep[c] = c; 968 969 return(ep + 0200); 970 } 971