1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1996, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #ident "%Z%%M% %I% %E% SMI" /* from S5R3.1 1.7 */ 32 33 #include <stdio.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include "sed.h" 38 #include <regexp.h> 39 40 union reptr *abuf[ABUFSIZE+1]; 41 union reptr **aptr; 42 char ibuf[BUFSIZ]; 43 char *cbp; 44 char *ebp; 45 char genbuf[LBSIZE+1]; 46 char *lcomend; 47 int dolflag; 48 int sflag; 49 int jflag; 50 int delflag; 51 long long lnum; 52 char holdsp[LBSIZE+1]; 53 char *spend; 54 char *hspend; 55 int nflag; 56 long long tlno[NLINES]; 57 int f; 58 char *ifname; 59 int numpass; 60 union reptr *pending; 61 char *trans[040] = { 62 "\\01", 63 "\\02", 64 "\\03", 65 "\\04", 66 "\\05", 67 "\\06", 68 "\\07", 69 "-<", 70 "->", 71 "\n", 72 "\\13", 73 "\\14", 74 "\\15", 75 "\\16", 76 "\\17", 77 "\\20", 78 "\\21", 79 "\\22", 80 "\\23", 81 "\\24", 82 "\\25", 83 "\\26", 84 "\\27", 85 "\\30", 86 "\\31", 87 "\\32", 88 "\\33", 89 "\\34", 90 "\\35", 91 "\\36", 92 "\\37" 93 }; 94 char rub[] = {"\\177"}; 95 96 extern char TMMES[]; 97 98 execute(file) 99 char *file; 100 { 101 register char *p1, *p2; 102 register union reptr *ipc; 103 int c; 104 char *execp; 105 106 if (file) { 107 if ((f = open(file, 0)) < 0) { 108 (void) fprintf(stderr, "sed: "); 109 perror(file); 110 } 111 ifname = file; 112 } else { 113 f = 0; 114 ifname = "standard input"; 115 } 116 117 ebp = ibuf; 118 cbp = ibuf; 119 120 if(pending) { 121 ipc = pending; 122 pending = 0; 123 goto yes; 124 } 125 126 for(;;) { 127 if((execp = gline(linebuf)) == 0) { 128 (void) close(f); 129 return; 130 } 131 spend = execp; 132 133 for(ipc = ptrspace; ipc->r1.command; ) { 134 135 p1 = ipc->r1.ad1; 136 p2 = ipc->r1.ad2; 137 138 if(p1) { 139 140 if(ipc->r1.inar) { 141 if(*p2 == CEND) { 142 p1 = 0; 143 } else if(*p2 == CLNUM) { 144 c = (unsigned char)p2[1]; 145 if(lnum > tlno[c]) { 146 ipc->r1.inar = 0; 147 if(ipc->r1.negfl) 148 goto yes; 149 ipc++; 150 continue; 151 } 152 if(lnum == tlno[c]) { 153 ipc->r1.inar = 0; 154 } 155 } else if(match(p2, 0)) { 156 ipc->r1.inar = 0; 157 } 158 } else if(*p1 == CEND) { 159 if(!dolflag) { 160 if(ipc->r1.negfl) 161 goto yes; 162 ipc++; 163 continue; 164 } 165 166 } else if(*p1 == CLNUM) { 167 c = (unsigned char)p1[1]; 168 if(lnum != tlno[c]) { 169 if(ipc->r1.negfl) 170 goto yes; 171 ipc++; 172 continue; 173 } 174 if(p2) 175 ipc->r1.inar = 1; 176 } else if(match(p1, 0)) { 177 if(p2) 178 ipc->r1.inar = 1; 179 } else { 180 if(ipc->r1.negfl) 181 goto yes; 182 ipc++; 183 continue; 184 } 185 } 186 187 if(ipc->r1.negfl) { 188 ipc++; 189 continue; 190 } 191 yes: 192 command(ipc); 193 194 if(delflag) 195 break; 196 197 if(jflag) { 198 jflag = 0; 199 if((ipc = ipc->r2.lb1) == 0) { 200 ipc = ptrspace; 201 break; 202 } 203 } else 204 ipc++; 205 206 } 207 if(!nflag && !delflag) { 208 for(p1 = linebuf; p1 < spend; p1++) 209 (void) putc(*p1, stdout); 210 (void) putc('\n', stdout); 211 } 212 213 if(aptr > abuf) { 214 arout(); 215 } 216 217 delflag = 0; 218 219 } 220 } 221 match(expbuf, gf) 222 char *expbuf; 223 { 224 register char *p1; 225 226 if(gf) { 227 if(*expbuf) return(0); 228 locs = p1 = loc2; 229 } else { 230 p1 = linebuf; 231 locs = 0; 232 } 233 234 circf = *expbuf++; 235 return(step(p1, expbuf)); 236 } 237 238 substitute(ipc) 239 union reptr *ipc; 240 { 241 if(match(ipc->r1.re1, 0) == 0) return(0); 242 243 numpass = 0; 244 sflag = 0; /* Flags if any substitution was made */ 245 dosub(ipc->r1.rhs, ipc->r1.gfl); 246 247 if(ipc->r1.gfl) { 248 while(*loc2) { 249 if(match(ipc->r1.re1, 1) == 0) break; 250 dosub(ipc->r1.rhs, ipc->r1.gfl); 251 } 252 } 253 return(sflag); 254 } 255 256 dosub(rhsbuf,n) 257 char *rhsbuf; 258 int n; 259 { 260 register char *lp, *sp, *rp; 261 int c; 262 263 if(n > 0 && n < 999) 264 {numpass++; 265 if(n != numpass) return; 266 } 267 sflag = 1; 268 lp = linebuf; 269 sp = genbuf; 270 rp = rhsbuf; 271 while (lp < loc1) 272 *sp++ = *lp++; 273 while(c = *rp++) { 274 if (c == '&') 275 sp = place(sp, loc1, loc2); 276 else if (c == '\\') { 277 c = *rp++; 278 if (c >= '1' && c < NBRA+'1') 279 sp = place(sp, braslist[c-'1'], braelist[c-'1']); 280 else 281 *sp++ = c; 282 } else 283 *sp++ = c; 284 if (sp == &genbuf[LBSIZE+1]) { 285 (void) fprintf(stderr, "Output line too long.\n"); 286 *--sp = '\0'; 287 goto out; 288 } 289 } 290 lp = loc2; 291 loc2 = sp - genbuf + linebuf; 292 while(*sp++ = *lp++) 293 if (sp == &genbuf[LBSIZE+1]) { 294 (void) fprintf(stderr, "Output line too long.\n"); 295 *--sp = '\0'; 296 break; 297 } 298 out: 299 lp = linebuf; 300 sp = genbuf; 301 while (*lp++ = *sp++); 302 spend = lp-1; 303 } 304 305 char *place(asp, al1, al2) 306 char *asp, *al1, *al2; 307 { 308 register char *sp, *l1, *l2; 309 310 sp = asp; 311 l1 = al1; 312 l2 = al2; 313 while (l1 < l2) { 314 *sp++ = *l1++; 315 if (sp == &genbuf[LBSIZE+1]) 316 break; 317 } 318 return(sp); 319 } 320 321 command(ipc) 322 union reptr *ipc; 323 { 324 register int i; 325 register char *p1, *p2, *p3; 326 char *execp; 327 328 329 switch(ipc->r1.command) { 330 331 case ACOM: 332 if(aptr >= &abuf[ABUFSIZE]) { 333 (void) fprintf(stderr, "Too many appends or reads after line %lld\n", 334 lnum); 335 } else { 336 *aptr++ = ipc; 337 *aptr = 0; 338 } 339 break; 340 341 case CCOM: 342 delflag = 1; 343 if(!ipc->r1.inar || dolflag) { 344 for(p1 = ipc->r1.re1; *p1; ) 345 (void) putc(*p1++, stdout); 346 (void) putc('\n', stdout); 347 } 348 break; 349 case DCOM: 350 delflag++; 351 break; 352 case CDCOM: 353 p1 = p2 = linebuf; 354 355 while(*p1 != '\n') { 356 if(*p1++ == 0) { 357 delflag++; 358 return; 359 } 360 } 361 362 p1++; 363 while(*p2++ = *p1++); 364 spend = p2-1; 365 jflag++; 366 break; 367 368 case EQCOM: 369 (void) fprintf(stdout, "%lld\n", lnum); 370 break; 371 372 case GCOM: 373 p1 = linebuf; 374 p2 = holdsp; 375 while(*p1++ = *p2++); 376 spend = p1-1; 377 break; 378 379 case CGCOM: 380 *spend++ = '\n'; 381 p1 = spend; 382 p2 = holdsp; 383 do { 384 if (p1 == &linebuf[LBSIZE+1]) { 385 (void) fprintf(stderr, "Output line too long.\n"); 386 *--p1 = '\0'; 387 } 388 } while(*p1++ = *p2++); 389 spend = p1-1; 390 break; 391 392 case HCOM: 393 p1 = holdsp; 394 p2 = linebuf; 395 while(*p1++ = *p2++); 396 hspend = p1-1; 397 break; 398 399 case CHCOM: 400 *hspend++ = '\n'; 401 p1 = hspend; 402 p2 = linebuf; 403 do { 404 if (p1 == &holdsp[LBSIZE+1]) { 405 (void) fprintf(stderr, "Hold space overflowed.\n"); 406 *--p1 = '\0'; 407 } 408 } while(*p1++ = *p2++); 409 hspend = p1-1; 410 break; 411 412 case ICOM: 413 for(p1 = ipc->r1.re1; *p1; ) 414 (void) putc(*p1++, stdout); 415 (void) putc('\n', stdout); 416 break; 417 418 case BCOM: 419 jflag = 1; 420 break; 421 422 423 case LCOM: 424 p1 = linebuf; 425 p2 = genbuf; 426 genbuf[72] = 0; 427 while(*p1) 428 if((unsigned char)*p1 >= 040) { 429 if(*p1 == 0177) { 430 p3 = rub; 431 while(*p2++ = *p3++) 432 if(p2 >= lcomend) { 433 *p2 = '\\'; 434 (void) fprintf(stdout, "%s\n", genbuf); 435 p2 = genbuf; 436 } 437 p2--; 438 p1++; 439 continue; 440 } 441 if(!isprint(*p1 & 0377)) { 442 *p2++ = '\\'; 443 if(p2 >= lcomend) { 444 *p2 = '\\'; 445 (void) fprintf(stdout, "%s\n", genbuf); 446 p2 = genbuf; 447 } 448 *p2++ = (*p1 >> 6) + '0'; 449 if(p2 >= lcomend) { 450 *p2 = '\\'; 451 (void) fprintf(stdout, "%s\n", genbuf); 452 p2 = genbuf; 453 } 454 *p2++ = ((*p1 >> 3) & 07) + '0'; 455 if(p2 >= lcomend) { 456 *p2 = '\\'; 457 (void) fprintf(stdout, "%s\n", genbuf); 458 p2 = genbuf; 459 } 460 *p2++ = (*p1++ & 07) + '0'; 461 if(p2 >= lcomend) { 462 *p2 = '\\'; 463 (void) fprintf(stdout, "%s\n", genbuf); 464 p2 = genbuf; 465 } 466 } else { 467 *p2++ = *p1++; 468 if(p2 >= lcomend) { 469 *p2 = '\\'; 470 (void) fprintf(stdout, "%s\n", genbuf); 471 p2 = genbuf; 472 } 473 } 474 } else { 475 p3 = trans[(unsigned char)*p1-1]; 476 while(*p2++ = *p3++) 477 if(p2 >= lcomend) { 478 *p2 = '\\'; 479 (void) fprintf(stdout, "%s\n", genbuf); 480 p2 = genbuf; 481 } 482 p2--; 483 p1++; 484 } 485 *p2 = 0; 486 (void) fprintf(stdout, "%s\n", genbuf); 487 break; 488 489 case NCOM: 490 if(!nflag) { 491 for(p1 = linebuf; p1 < spend; p1++) 492 (void) putc(*p1, stdout); 493 (void) putc('\n', stdout); 494 } 495 496 if(aptr > abuf) 497 arout(); 498 if((execp = gline(linebuf)) == 0) { 499 pending = ipc; 500 delflag = 1; 501 break; 502 } 503 spend = execp; 504 505 break; 506 case CNCOM: 507 if(aptr > abuf) 508 arout(); 509 *spend++ = '\n'; 510 if((execp = gline(spend)) == 0) { 511 pending = ipc; 512 delflag = 1; 513 break; 514 } 515 spend = execp; 516 break; 517 518 case PCOM: 519 for(p1 = linebuf; p1 < spend; p1++) 520 (void) putc(*p1, stdout); 521 (void) putc('\n', stdout); 522 break; 523 case CPCOM: 524 cpcom: 525 for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; ) 526 (void) putc(*p1++, stdout); 527 (void) putc('\n', stdout); 528 break; 529 530 case QCOM: 531 if(!nflag) { 532 for(p1 = linebuf; p1 < spend; p1++) 533 (void) putc(*p1, stdout); 534 (void) putc('\n', stdout); 535 } 536 if(aptr > abuf) arout(); 537 (void) fclose(stdout); 538 exit(0); 539 case RCOM: 540 if(aptr >= &abuf[ABUFSIZE]) { 541 (void) fprintf(stderr, "Too many appends or reads after line %lld\n", 542 lnum); 543 } else { 544 *aptr++ = ipc; 545 *aptr = 0; 546 } 547 break; 548 549 case SCOM: 550 i = substitute(ipc); 551 if(ipc->r1.pfl && nflag && i) 552 if(ipc->r1.pfl == 1) { 553 for(p1 = linebuf; p1 < spend; p1++) 554 (void) putc(*p1, stdout); 555 (void) putc('\n', stdout); 556 } 557 else 558 goto cpcom; 559 if(i && ipc->r1.fcode) 560 goto wcom; 561 break; 562 563 case TCOM: 564 if(sflag == 0) break; 565 sflag = 0; 566 jflag = 1; 567 break; 568 569 wcom: 570 case WCOM: 571 (void) fprintf(ipc->r1.fcode, "%s\n", linebuf); 572 (void) fflush(ipc->r1.fcode); 573 break; 574 case XCOM: 575 p1 = linebuf; 576 p2 = genbuf; 577 while(*p2++ = *p1++); 578 p1 = holdsp; 579 p2 = linebuf; 580 while(*p2++ = *p1++); 581 spend = p2 - 1; 582 p1 = genbuf; 583 p2 = holdsp; 584 while(*p2++ = *p1++); 585 hspend = p2 - 1; 586 break; 587 588 case YCOM: 589 p1 = linebuf; 590 p2 = ipc->r1.re1; 591 while(*p1 = p2[(unsigned char)*p1]) p1++; 592 break; 593 } 594 595 } 596 597 char *gline(addr) 598 char *addr; 599 { 600 register char *p1, *p2; 601 register c; 602 sflag = 0; 603 p1 = addr; 604 p2 = cbp; 605 for (;;) { 606 if (p2 >= ebp) { 607 if(f < 0 || (c = read(f, ibuf, BUFSIZ)) == 0) { 608 return(0); 609 } 610 if(c < 0) { 611 (void) fprintf(stderr, "sed: error reading "); 612 perror(ifname); 613 exit(2); 614 } 615 p2 = ibuf; 616 ebp = ibuf+c; 617 } 618 if ((c = *p2++) == '\n') { 619 if(p2 >= ebp) { 620 if(f < 0 || (c = read(f, ibuf, BUFSIZ)) == 0) { 621 if(f >= 0) { 622 (void) close(f); 623 f = -1; 624 } 625 if(eargc == 0) 626 dolflag = 1; 627 } 628 if(c < 0) { 629 (void) fprintf(stderr, "sed: error reading "); 630 perror(ifname); 631 exit(2); 632 } 633 634 p2 = ibuf; 635 ebp = ibuf + c; 636 } 637 break; 638 } 639 if(c) 640 if(p1 < &linebuf[LBSIZE]) 641 *p1++ = c; 642 } 643 lnum++; 644 *p1 = 0; 645 cbp = p2; 646 647 return(p1); 648 } 649 650 char *comple(x1, ep, x3, x4) 651 char *x1, *x3; 652 char x4; 653 register char *ep; 654 { 655 register char *p; 656 657 p = compile(x1, ep + 1, x3, x4); 658 if(p == ep + 1) 659 return(ep); 660 *ep = circf; 661 return(p); 662 } 663 664 regerr(err) 665 register err; 666 { 667 switch(err) { 668 669 case 11: 670 comperr("Range endpoint too large: %s"); 671 break; 672 673 case 16: 674 comperr("Bad number: %s"); 675 break; 676 677 case 25: 678 comperr("``\\digit'' out of range: %s"); 679 break; 680 681 case 36: 682 comperr("Illegal or missing delimiter: %s"); 683 break; 684 685 case 41: 686 comperr("No remembered search string: %s"); 687 break; 688 689 case 42: 690 comperr("\\( \\) imbalance: %s"); 691 break; 692 693 case 43: 694 comperr("Too many \\(: %s"); 695 break; 696 697 case 44: 698 comperr("More than 2 numbers given in \\{ \\}: %s"); 699 break; 700 701 case 45: 702 comperr("} expected after \\: %s"); 703 break; 704 705 case 46: 706 comperr("First number exceeds second in \\{ \\}: %s"); 707 break; 708 709 case 49: 710 comperr("[ ] imbalance: %s"); 711 break; 712 713 case 50: 714 comperr(TMMES); 715 break; 716 717 default: 718 (void) fprintf(stderr, "Unknown regexp error code %d: %s\n", 719 err, linebuf); 720 exit(2); 721 break; 722 } 723 } 724 725 arout() 726 { 727 register char *p1; 728 FILE *fi; 729 char c; 730 int t; 731 732 aptr = abuf - 1; 733 while(*++aptr) { 734 if((*aptr)->r1.command == ACOM) { 735 for(p1 = (*aptr)->r1.re1; *p1; ) 736 (void) putc(*p1++, stdout); 737 (void) putc('\n', stdout); 738 } else { 739 if((fi = fopen((*aptr)->r1.re1, "r")) == NULL) 740 continue; 741 while((t = getc(fi)) != EOF) { 742 c = t; 743 (void) putc(c, stdout); 744 } 745 (void) fclose(fi); 746 } 747 } 748 aptr = abuf; 749 *aptr = 0; 750 } 751 752