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