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