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