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