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