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