sed0.c (23789B)
1 /* from Unix 7th Edition sed */ 2 /* Sccsid @(#)sed0.c 1.64 (gritter) 3/12/05> */ 3 /* 4 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * Redistributions of source code and documentation must retain the 10 * above copyright notice, this list of conditions and the following 11 * disclaimer. 12 * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed or owned by Caldera 18 * International, Inc. 19 * Neither the name of Caldera International, Inc. nor the names of 20 * other contributors may be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 24 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE 28 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 34 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 #include <unistd.h> 37 #include <stdlib.h> 38 #include <locale.h> 39 #include <libgen.h> 40 #include <stdarg.h> 41 #include <wchar.h> 42 #include "sed.h" 43 44 int ABUFSIZE; 45 struct reptr **abuf; 46 int aptr; 47 char *genbuf; 48 int gbend; 49 int lbend; 50 int hend; 51 char *linebuf; 52 char *holdsp; 53 int nflag; 54 long long *tlno; 55 char *cp; 56 57 int status; 58 int multibyte; 59 int invchar; 60 int needdol; 61 62 int eargc; 63 64 struct reptr *ptrspace; 65 struct reptr *pending; 66 char *badp; 67 68 static const char CGMES[] = "\1command garbled: %s"; 69 static const char TMMES[] = "Too much text: %s"; 70 static const char LTL[] = "Label too long: %s"; 71 static const char LINTL[] = "line too long"; 72 static const char AD0MES[] = "No addresses allowed: %s"; 73 static const char AD1MES[] = "Only one address allowed: %s"; 74 static FILE **fcode; 75 static FILE *fin; 76 static char *lastre; 77 static wchar_t sed_seof; 78 static int PTRSIZE; 79 static int eflag; 80 static int gflag; 81 static int nlno; 82 static char **fname; 83 static int nfiles; 84 static int rep; 85 static struct label *ltab; 86 static int lab; 87 static size_t LABSIZE; 88 static int labtab = 1; 89 static int depth; 90 static char **eargv; 91 static int *cmpend; 92 static size_t DEPTH; 93 static char bad; 94 static char compfl; 95 static char *progname; 96 static char *(*ycomp)(char **); 97 static int executing; 98 99 static void fcomp(void); 100 static char *compsub(char **, char *); 101 static int rline(void); 102 static char *address(char **); 103 static int cmp(const char *, const char *); 104 static void text(char **); 105 static int search(struct label *); 106 static void dechain(void); 107 static char *ycomp_sb(char **); 108 static char *ycomp_mb(char **); 109 static void lab_inc(void); 110 static void rep_inc(void); 111 static void depth_check(void); 112 static void *srealloc(void *, size_t); 113 static void *scalloc(size_t, size_t); 114 static char *sed_compile(char **); 115 static void wfile(void); 116 static void morefiles(void); 117 118 static char *null; 119 #define check(p, buf, sz, incr, op) \ 120 if (&p[1] >= &(buf)[sz]) { \ 121 size_t ppos = p - buf; \ 122 size_t opos = op - buf; \ 123 buf = srealloc(buf, (sz += incr) * sizeof *(buf)); \ 124 p = &(buf)[ppos]; \ 125 if (op != NULL) \ 126 op = &(buf)[opos]; \ 127 } 128 129 int 130 main(int argc, char **argv) 131 { 132 int c; 133 const char optstr[] = "nf:e:g"; 134 135 sed = 1; 136 progname = basename(argv[0]); 137 eargc = argc; 138 eargv = argv; 139 140 #ifdef __GLIBC__ 141 putenv("POSIXLY_CORRECT=1"); 142 #endif /* __GLIBC__ */ 143 #if defined (SUS) || defined (SU3) || defined (S42) 144 setlocale(LC_COLLATE, ""); 145 #endif /* SUS || SU3 || S42 */ 146 setlocale(LC_CTYPE, ""); 147 multibyte = MB_CUR_MAX > 1; 148 ycomp = multibyte ? ycomp_mb : ycomp_sb; 149 badp = &bad; 150 aptr_inc(); 151 lab_inc(); 152 lab_inc(); /* 0 reserved for end-pointer -> labtab = 1 */ 153 growsp(NULL); 154 rep_inc(); 155 pending = 0; 156 depth = 0; 157 morefiles(); 158 fcode[0] = stdout; 159 nfiles = 1; 160 morefiles(); 161 162 if(eargc == 1) 163 exit(0); 164 while ((c = getopt(eargc, eargv, optstr)) != EOF) { 165 switch (c) { 166 case 'n': 167 nflag++; 168 continue; 169 170 case 'f': 171 if((fin = fopen(optarg, "r")) == NULL) 172 fatal("Cannot open pattern-file: %s", optarg); 173 174 fcomp(); 175 fclose(fin); 176 continue; 177 178 case 'e': 179 eflag++; 180 fcomp(); 181 eflag = 0; 182 continue; 183 184 case 'g': 185 gflag++; 186 continue; 187 188 default: 189 exit(2); 190 } 191 } 192 193 eargv += optind, eargc -= optind; 194 195 196 if(compfl == 0 && *eargv) { 197 optarg = *eargv++; 198 eargc--; 199 eflag++; 200 fcomp(); 201 eflag = 0; 202 } 203 204 if(depth) 205 fatal("Too many {'s"); 206 207 L(labtab)->address = rep; 208 209 dechain(); 210 211 /* abort(); */ /*DEBUG*/ 212 213 executing++; 214 if(eargc <= 0) 215 execute((char *)NULL); 216 else while(--eargc >= 0) { 217 execute(*eargv++); 218 } 219 fclose(stdout); 220 return status; 221 } 222 223 static void 224 fcomp(void) 225 { 226 227 register char *op, *tp, *q; 228 int pt, pt1; 229 int lpt; 230 231 compfl = 1; 232 op = lastre; 233 234 if(rline() < 0) return; 235 if(*linebuf == '#') { 236 if(linebuf[1] == 'n') 237 nflag = 1; 238 } 239 else { 240 cp = linebuf; 241 goto comploop; 242 } 243 244 for(;;) { 245 if(rline() < 0) break; 246 247 cp = linebuf; 248 249 comploop: 250 /* fprintf(stdout, "cp: %s\n", cp); */ /*DEBUG*/ 251 while(*cp == ' ' || *cp == '\t') cp++; 252 if(*cp == '\0' || *cp == '#') continue; 253 if(*cp == ';') { 254 cp++; 255 goto comploop; 256 } 257 258 q = address(&P(rep)->ad1); 259 if(q == badp) 260 fatal(CGMES, linebuf); 261 262 if(q != 0 && q == P(rep)->ad1) { 263 if(op) 264 P(rep)->ad1 = op; 265 else 266 fatal("First RE may not be null"); 267 } else if(q == 0) { 268 P(rep)->ad1 = 0; 269 } else { 270 op = P(rep)->ad1; 271 if(*cp == ',' || *cp == ';') { 272 cp++; 273 q = address(&P(rep)->ad2); 274 if(q == badp || q == 0) 275 fatal(CGMES, linebuf); 276 if(q == P(rep)->ad2) 277 P(rep)->ad2 = op; 278 else 279 op = P(rep)->ad2; 280 281 } else 282 P(rep)->ad2 = 0; 283 } 284 285 while(*cp == ' ' || *cp == '\t') cp++; 286 287 swit: 288 switch(*cp++) { 289 290 default: 291 fatal("Unrecognized command: %s", linebuf); 292 /*NOTREACHED*/ 293 294 case '!': 295 P(rep)->negfl = 1; 296 goto swit; 297 298 case '{': 299 P(rep)->command = BCOM; 300 P(rep)->negfl = !(P(rep)->negfl); 301 depth_check(); 302 cmpend[depth++] = rep; 303 rep_inc(); 304 if(*cp == '\0') continue; 305 306 goto comploop; 307 308 case '}': 309 if(P(rep)->ad1) 310 fatal(AD0MES, linebuf); 311 312 if(--depth < 0) 313 fatal("Too many }'s"); 314 P(cmpend[depth])->bptr.lb1 = rep; 315 316 continue; 317 318 case '=': 319 P(rep)->command = EQCOM; 320 if(P(rep)->ad2) 321 fatal(AD1MES, linebuf); 322 break; 323 324 case ':': 325 if(P(rep)->ad1) 326 fatal(AD0MES, linebuf); 327 328 while(*cp++ == ' '); 329 cp--; 330 331 332 tp = L(lab)->asc; 333 while((*tp++ = *cp++)) 334 if(tp >= &(L(lab)->asc[sizeof 335 L(lab)->asc])) 336 fatal(LTL, linebuf); 337 *--tp = '\0'; 338 339 if(lpt = search(L(lab))) { 340 if(L(lpt)->address) 341 fatal("Duplicate labels: %s", 342 linebuf); 343 } else { 344 L(lab)->chain = 0; 345 lpt = lab; 346 lab_inc(); 347 } 348 L(lpt)->address = rep; 349 350 continue; 351 352 case 'a': 353 P(rep)->command = ACOM; 354 if(P(rep)->ad2) 355 fatal(AD1MES, linebuf); 356 if(*cp == '\\') cp++; 357 if(*cp++ != '\n') 358 fatal(CGMES, linebuf); 359 text(&P(rep)->bptr.re1); 360 break; 361 case 'c': 362 P(rep)->command = CCOM; 363 if(*cp == '\\') cp++; 364 if(*cp++ != ('\n')) 365 fatal(CGMES, linebuf); 366 text(&P(rep)->bptr.re1); 367 needdol = 1; 368 break; 369 case 'i': 370 P(rep)->command = ICOM; 371 if(P(rep)->ad2) 372 fatal(AD1MES, linebuf); 373 if(*cp == '\\') cp++; 374 if(*cp++ != ('\n')) 375 fatal(CGMES, linebuf); 376 text(&P(rep)->bptr.re1); 377 break; 378 379 case 'g': 380 P(rep)->command = GCOM; 381 break; 382 383 case 'G': 384 P(rep)->command = CGCOM; 385 break; 386 387 case 'h': 388 P(rep)->command = HCOM; 389 break; 390 391 case 'H': 392 P(rep)->command = CHCOM; 393 break; 394 395 case 't': 396 P(rep)->command = TCOM; 397 goto jtcommon; 398 399 case 'b': 400 P(rep)->command = BCOM; 401 jtcommon: 402 while(*cp++ == ' '); 403 cp--; 404 405 if(*cp == '\0') { 406 if((pt = L(labtab)->chain) != 0) { 407 while((pt1 = P(pt)->bptr.lb1) != 0) 408 pt = pt1; 409 P(pt)->bptr.lb1 = rep; 410 } else 411 L(labtab)->chain = rep; 412 break; 413 } 414 tp = L(lab)->asc; 415 while((*tp++ = *cp++)) 416 if(tp >= &(L(lab)->asc[sizeof 417 L(lab)->asc])) 418 fatal(LTL, linebuf); 419 cp--; 420 *--tp = '\0'; 421 422 if(lpt = search(L(lab))) { 423 if(L(lpt)->address) { 424 P(rep)->bptr.lb1 = L(lpt)->address; 425 } else { 426 pt = L(lpt)->chain; 427 while((pt1 = P(pt)->bptr.lb1) != 0) 428 pt = pt1; 429 P(pt)->bptr.lb1 = rep; 430 } 431 } else { 432 L(lab)->chain = rep; 433 L(lab)->address = 0; 434 lab_inc(); 435 } 436 break; 437 438 case 'n': 439 P(rep)->command = NCOM; 440 break; 441 442 case 'N': 443 P(rep)->command = CNCOM; 444 break; 445 446 case 'p': 447 P(rep)->command = PCOM; 448 break; 449 450 case 'P': 451 P(rep)->command = CPCOM; 452 break; 453 454 case 'r': 455 P(rep)->command = RCOM; 456 if(P(rep)->ad2) 457 fatal(AD1MES, linebuf); 458 #if !defined (SUS) && !defined (SU3) 459 if(*cp++ != ' ') 460 fatal(CGMES, linebuf); 461 #else /* SUS, SU3 */ 462 while (*cp == ' ' || *cp == '\t') 463 cp++; 464 #endif /* SUS, SU3 */ 465 text(&P(rep)->bptr.re1); 466 break; 467 468 case 'd': 469 P(rep)->command = DCOM; 470 break; 471 472 case 'D': 473 P(rep)->command = CDCOM; 474 P(rep)->bptr.lb1 = 1; 475 break; 476 477 case 'q': 478 P(rep)->command = QCOM; 479 if(P(rep)->ad2) 480 fatal(AD1MES, linebuf); 481 break; 482 483 case 'l': 484 P(rep)->command = LCOM; 485 break; 486 487 case 's': 488 P(rep)->command = SCOM; 489 sed_seof = fetch(&cp); 490 q = sed_compile(&P(rep)->bptr.re1); 491 if(q == badp) 492 fatal(CGMES, linebuf); 493 if(q == P(rep)->bptr.re1) { 494 if (op == NULL) 495 fatal("First RE may not be null"); 496 P(rep)->bptr.re1 = op; 497 } else { 498 op = P(rep)->bptr.re1; 499 } 500 501 if(compsub(&P(rep)->rhs, &P(rep)->nsub) == badp) 502 fatal(CGMES, linebuf); 503 sloop: if(*cp == 'g') { 504 cp++; 505 P(rep)->gfl = -1; 506 goto sloop; 507 } else if(gflag) 508 P(rep)->gfl = -1; 509 if (*cp >= '0' && *cp <= '9') { 510 while (*cp >= '0' && *cp <= '9') { 511 if (P(rep)->gfl == -1) 512 P(rep)->gfl = 0; 513 P(rep)->gfl = P(rep)->gfl * 10 514 + *cp++ - '0'; 515 } 516 goto sloop; 517 } 518 #if !defined (SUS) && !defined (SU3) 519 if (P(rep)->gfl > 0 && P(rep)->gfl > 512) 520 fatal("Suffix too large - 512 max: %s", linebuf); 521 #endif 522 523 if(*cp == 'p') { 524 cp++; 525 P(rep)->pfl = 1; 526 goto sloop; 527 } 528 529 if(*cp == 'P') { 530 cp++; 531 P(rep)->pfl = 2; 532 goto sloop; 533 } 534 535 if(*cp == 'w') { 536 cp++; 537 wfile(); 538 } 539 break; 540 541 case 'w': 542 P(rep)->command = WCOM; 543 wfile(); 544 break; 545 546 case 'x': 547 P(rep)->command = XCOM; 548 break; 549 550 case 'y': 551 P(rep)->command = YCOM; 552 sed_seof = fetch(&cp); 553 if (ycomp(&P(rep)->bptr.re1) == badp) 554 fatal(CGMES, linebuf); 555 break; 556 557 } 558 rep_inc(); 559 560 if(*cp++ != '\0') { 561 if(cp[-1] == ';') 562 goto comploop; 563 fatal(CGMES, linebuf); 564 } 565 566 } 567 P(rep)->command = 0; 568 lastre = op; 569 } 570 571 static char * 572 compsub(char **rhsbuf, char *nsubp) 573 { 574 register char *p, *op, *oq; 575 char *q; 576 wint_t c; 577 size_t sz = 32; 578 579 *rhsbuf = smalloc(sz); 580 p = *rhsbuf; 581 q = cp; 582 *nsubp = 0; 583 for(;;) { 584 op = p; 585 oq = q; 586 if((c = fetch(&q)) == '\\') { 587 check(p, *rhsbuf, sz, 32, op) 588 *p = '\\'; 589 oq = q; 590 c = fetch(&q); 591 do { 592 check(p, *rhsbuf, sz, 32, op) 593 *++p = *oq++; 594 } while (oq < q); 595 if(c > nbra + '0' && c <= '9') 596 return(badp); 597 if (c > *nsubp + '0' && c <= '9') 598 *nsubp = c - '0'; 599 check(p, *rhsbuf, sz, 32, op) 600 p++; 601 continue; 602 } else { 603 do { 604 check(p, *rhsbuf, sz, 32, op) 605 *p++ = *oq++; 606 } while (oq < q); 607 p--; 608 } 609 if(c == sed_seof) { 610 check(p, *rhsbuf, sz, 32, op) 611 *op++ = '\0'; 612 cp = q; 613 return(op); 614 } 615 check(p, *rhsbuf, sz, 32, op) 616 if(*p++ == '\0') { 617 return(badp); 618 } 619 620 } 621 } 622 623 #define rlinechk() if (c >= lbend-2) \ 624 growsp(LINTL) 625 626 static int 627 rline(void) 628 { 629 register char *q; 630 register int c; 631 register int t; 632 static char *saveq; 633 634 c = -1; 635 636 if(eflag) { 637 if(eflag > 0) { 638 eflag = -1; 639 q = optarg; 640 rlinechk(); 641 while(linebuf[++c] = *q++) { 642 rlinechk(); 643 if(linebuf[c] == '\\') { 644 if((linebuf[++c] = *q++) == '\0') { 645 rlinechk(); 646 saveq = 0; 647 return(-1); 648 } else 649 continue; 650 } 651 if(linebuf[c] == '\n') { 652 linebuf[c] = '\0'; 653 saveq = q; 654 return(1); 655 } 656 } 657 saveq = 0; 658 return(1); 659 } 660 if((q = saveq) == 0) return(-1); 661 662 while(linebuf[++c] = *q++) { 663 rlinechk(); 664 if(linebuf[c] == '\\') { 665 if((linebuf[++c] = *q++) == '0') { 666 rlinechk(); 667 saveq = 0; 668 return(-1); 669 } else 670 continue; 671 } 672 if(linebuf[c] == '\n') { 673 linebuf[c] = '\0'; 674 saveq = q; 675 return(1); 676 } 677 } 678 saveq = 0; 679 return(1); 680 } 681 682 while((t = getc(fin)) != EOF) { 683 rlinechk(); 684 linebuf[++c] = (char)t; 685 if(linebuf[c] == '\\') { 686 t = getc(fin); 687 rlinechk(); 688 linebuf[++c] = (char)t; 689 } 690 else if(linebuf[c] == '\n') { 691 linebuf[c] = '\0'; 692 return(1); 693 } 694 } 695 linebuf[++c] = '\0'; 696 return(-1); 697 } 698 699 static char * 700 address(char **expbuf) 701 { 702 register char *rcp, *ep; 703 long long lno; 704 705 *expbuf = NULL; 706 if(*cp == '$') { 707 cp++; 708 ep = *expbuf = smalloc(2 * sizeof *expbuf); 709 *ep++ = CEND; 710 *ep++ = ceof; 711 needdol = 1; 712 return(ep); 713 } 714 715 if(*cp == '/' || *cp == '\\') { 716 if (*cp == '\\') 717 cp++; 718 sed_seof = fetch(&cp); 719 return(sed_compile(expbuf)); 720 } 721 722 rcp = cp; 723 lno = 0; 724 725 while(*rcp >= '0' && *rcp <= '9') 726 lno = lno*10 + *rcp++ - '0'; 727 728 if(rcp > cp) { 729 if (nlno > 020000000000 || 730 (tlno = realloc(tlno, (nlno+1)*sizeof *tlno)) == NULL) 731 fatal("Too many line numbers"); 732 ep = *expbuf = smalloc(6 * sizeof *expbuf); 733 *ep++ = CLNUM; 734 slno(ep, nlno); 735 tlno[nlno++] = lno; 736 *ep++ = ceof; 737 cp = rcp; 738 return(ep); 739 } 740 return(0); 741 } 742 743 static int 744 cmp(const char *a, const char *b) 745 { 746 register const char *ra, *rb; 747 748 ra = a - 1; 749 rb = b - 1; 750 751 while(*++ra == *++rb) 752 if(*ra == '\0') return(0); 753 return(1); 754 } 755 756 static void 757 text(char **textbuf) 758 { 759 register char *p, *oq; 760 char *q; 761 size_t sz = 128; 762 763 *textbuf = smalloc(sz); 764 p = *textbuf; 765 q = cp; 766 for(;;) { 767 768 oq = q; 769 if(fetch(&q) == '\\') { 770 oq = q; 771 fetch(&q); 772 } 773 while(oq < q) 774 *p++ = *oq++; 775 if(p[-1] == '\0') { 776 cp = --q; 777 return; 778 } 779 check(p, *textbuf, sz, 128, null) 780 } 781 } 782 783 static int 784 search(struct label *ptr) 785 { 786 struct label *rp; 787 788 rp = L(labtab); 789 while(rp < ptr) { 790 if(cmp(rp->asc, ptr->asc) == 0) 791 return(rp - L(labtab) + 1); 792 rp++; 793 } 794 795 return(0); 796 } 797 798 799 static void 800 dechain(void) 801 { 802 struct label *lptr; 803 int rptr, trptr; 804 805 for(lptr = L(labtab); lptr < L(lab); lptr++) { 806 807 if(lptr->address == 0) 808 fatal("Undefined label: %s", lptr->asc); 809 810 if(lptr->chain) { 811 rptr = lptr->chain; 812 while((trptr = P(rptr)->bptr.lb1) != 0) { 813 P(rptr)->bptr.lb1 = lptr->address; 814 rptr = trptr; 815 } 816 P(rptr)->bptr.lb1 = lptr->address; 817 } 818 } 819 } 820 821 static char * 822 ycomp_sb(char **expbuf) 823 { 824 register int c, d; 825 register char *ep, *tsp; 826 char *sp; 827 828 *expbuf = smalloc(0400); 829 ep = *expbuf; 830 for(c = 0; !(c & 0400); c++) 831 ep[c] = '\0'; 832 sp = cp; 833 for(tsp = cp; *tsp != sed_seof; tsp++) { 834 if(*tsp == '\\') 835 tsp++; 836 if(*tsp == '\n' || *tsp == '\0') 837 return(badp); 838 } 839 tsp++; 840 841 while((c = *sp++ & 0377) != sed_seof) { 842 if(c == '\\') { 843 c = *sp == 'n' ? '\n' : *sp; 844 sp++; 845 } 846 if((ep[c] = d = *tsp++ & 0377) == '\\') { 847 ep[c] = *tsp == 'n' ? '\n' : *tsp; 848 tsp++; 849 } 850 if(d != '\\' && ep[c] == sed_seof || ep[c] == '\0') 851 return(badp); 852 } 853 if(*tsp != sed_seof) 854 return(badp); 855 cp = ++tsp; 856 857 for(c = 0; !(c & 0400); c++) 858 if(ep[c] == 0) 859 ep[c] = (char)c; 860 861 return(ep + 0400); 862 } 863 864 static char * 865 ycomp_mb(char **expbuf) 866 { 867 struct yitem **yt, *yp; 868 register wint_t c, d; 869 char *otsp, *tsp, *sp, *mp; 870 871 tsp = sp = cp; 872 while ((c = fetch(&tsp)) != sed_seof) { 873 if (c == '\\') 874 c = fetch(&tsp); 875 if (c == '\n' || c == '\0') 876 return badp; 877 } 878 yt = scalloc(200, sizeof *yt); 879 while ((c = fetch(&sp)) != sed_seof) { 880 if (c == '\\') { 881 if ((d = fetch(&sp)) == 'n') 882 c = '\n'; 883 else 884 c = d; 885 } 886 otsp = tsp; 887 d = fetch(&tsp); 888 yp = ylook(c, yt, 1); 889 yp->y_oc = c; 890 if ((yp->y_yc = d) == '\\') { 891 otsp = tsp; 892 if ((c = fetch(&tsp)) == 'n') 893 yp->y_yc = '\n'; 894 else 895 yp->y_yc = c; 896 } 897 if (d != '\\' && yp->y_yc == sed_seof || yp->y_yc == '\0') 898 return badp; 899 mp = yp->y_mc; 900 if (yp->y_yc != '\n') 901 while (otsp < tsp) 902 *mp++ = *otsp++; 903 else 904 *mp++ = '\n'; 905 *mp = '\0'; 906 } 907 if (fetch(&tsp) != sed_seof) 908 return badp; 909 cp = tsp; 910 *expbuf = (char *)yt; 911 return &(*expbuf)[1]; 912 } 913 914 static void 915 rep_inc(void) 916 { 917 register char *p; 918 const int chunk = 16; 919 920 if (++rep >= PTRSIZE) { 921 ptrspace = srealloc(ptrspace, 922 (PTRSIZE += chunk) * sizeof *ptrspace); 923 for (p = (char *)&ptrspace[PTRSIZE - chunk]; 924 p < (char *)&ptrspace[PTRSIZE]; p++) 925 *p = '\0'; 926 } 927 } 928 929 static void 930 lab_inc(void) 931 { 932 register char *p; 933 const int chunk = 8; 934 935 if (++lab >= LABSIZE) { 936 ltab = srealloc(ltab, (LABSIZE += chunk) * sizeof *ltab); 937 for (p = (char *)<ab[LABSIZE - chunk]; 938 p < (char *)<ab[LABSIZE]; p++) 939 *p = '\0'; 940 } 941 } 942 943 void 944 aptr_inc(void) 945 { 946 register char *p; 947 const int chunk = 8; 948 949 if (++aptr > ABUFSIZE) { 950 abuf = srealloc(abuf, (ABUFSIZE += chunk) * sizeof *abuf); 951 for (p = (char *)&abuf[ABUFSIZE - chunk]; 952 p < (char *)&abuf[ABUFSIZE]; p++) 953 *p = '\0'; 954 } 955 } 956 957 static void 958 depth_check(void) 959 { 960 if (depth + 1 > DEPTH) 961 cmpend = srealloc(cmpend, (DEPTH += 8) * sizeof *cmpend); 962 } 963 964 void 965 nonfatal(const char *afmt, ...) 966 { 967 va_list ap; 968 const char *fmt; 969 970 if (*afmt == '\1') { 971 fprintf(stderr, "%s: ", progname); 972 fmt = &afmt[1]; 973 } else 974 fmt = afmt; 975 va_start(ap, afmt); 976 vfprintf(stderr, fmt, ap); 977 va_end(ap); 978 fputc('\n', stderr); 979 status |= 1; 980 } 981 982 void 983 fatal(const char *afmt, ...) 984 { 985 va_list ap; 986 const char *fmt; 987 988 if (*afmt == '\1') { 989 fprintf(stderr, "%s: ", progname); 990 fmt = &afmt[1]; 991 } else 992 fmt = afmt; 993 va_start(ap, afmt); 994 vfprintf(stderr, fmt, ap); 995 va_end(ap); 996 fputc('\n', stderr); 997 exit(2); 998 } 999 1000 static void * 1001 srealloc(void *vp, size_t nbytes) 1002 { 1003 void *p; 1004 1005 if ((p = realloc(vp, nbytes)) == NULL) 1006 fatal(TMMES, linebuf); 1007 return p; 1008 } 1009 1010 void * 1011 smalloc(size_t nbytes) 1012 { 1013 return srealloc(NULL, nbytes); 1014 } 1015 1016 static void * 1017 scalloc(size_t nmemb, size_t size) 1018 { 1019 void *p; 1020 1021 if ((p = calloc(nmemb, size)) == NULL) 1022 fatal(TMMES, linebuf); 1023 return p; 1024 } 1025 1026 #if defined (SUS) || defined (SU3) || defined (S42) 1027 static char * 1028 sed_compile(char **ep) 1029 { 1030 struct re_emu *re; 1031 static char *pat; 1032 static size_t patsz; 1033 register char *p, *oc; 1034 wint_t c, d; 1035 1036 if (*cp != sed_seof) 1037 nbra = 0; 1038 if (patsz == 0) 1039 pat = smalloc(patsz = 32); 1040 p = pat; 1041 do { 1042 oc = cp; 1043 if ((c = fetch(&cp)) == sed_seof) 1044 *p = '\0'; 1045 else if (c == '\\') { 1046 oc = cp; 1047 if ((c = fetch(&cp)) == 'n') 1048 *p = '\n'; 1049 else { 1050 check(p, pat, patsz, 32, null); 1051 *p++ = '\\'; 1052 if (c == '(') 1053 nbra++; 1054 goto normchar; 1055 } 1056 } else if (c == '[') { 1057 check(p, pat, patsz, 32, null); 1058 *p++ = c; 1059 d = WEOF; 1060 do { 1061 oc = cp; 1062 c = fetch(&cp); 1063 if (c == '\0') 1064 goto normchar; 1065 do { 1066 check(p, pat, patsz, 32, null); 1067 *p++ = *oc++; 1068 } while (oc < cp); 1069 if (d == '[' && (c == ':' || c == '.' || 1070 c == '=')) { 1071 d = c; 1072 do { 1073 oc = cp; 1074 c = fetch(&cp); 1075 if (c == '\0') 1076 goto normchar; 1077 do { 1078 check(p, pat, patsz,32, 1079 null); 1080 *p++ = *oc++; 1081 } while (oc < cp); 1082 } while (c != d || peek(&cp) != ']'); 1083 oc = cp; 1084 c = fetch(&cp); 1085 do { 1086 check(p, pat, patsz, 32, null); 1087 *p++ = *oc++; 1088 } while (oc < cp); 1089 c = WEOF; /* == reset d and continue */ 1090 } 1091 d = c; 1092 } while (c != ']'); 1093 p--; 1094 } else { 1095 normchar: do { 1096 check(p, pat, patsz, 32, null) 1097 *p++ = *oc++; 1098 } while (oc < cp); 1099 p--; 1100 } 1101 check(p, pat, patsz, 32, null); 1102 } while (*p++ != '\0'); 1103 re = scalloc(1, sizeof *re); 1104 *ep = (char *)re; 1105 if (*pat == '^') 1106 **ep = 1; 1107 if (*pat != '\0') { 1108 int reflags = 0; 1109 1110 #ifdef REG_ANGLES 1111 reflags |= REG_ANGLES; 1112 #endif /* REG_ANGLES */ 1113 #if defined (SU3) && defined (REG_AVOIDNULL) 1114 reflags |= REG_AVOIDNULL; 1115 #endif /* SU3 && AVOIDNULL */ 1116 if (regcomp(&re->r_preg, pat, reflags) != 0) 1117 re = (struct re_emu *)badp; 1118 } else 1119 **ep = 2; 1120 p = (char *)re; 1121 if (p != badp && *pat) 1122 p++; 1123 return p; 1124 } 1125 #else /* !SUS, !SU3, !S42 */ 1126 static char * 1127 sed_compile(char **ep) 1128 { 1129 extern char *compile(char *, char *, char *, int); 1130 register char *p; 1131 size_t sz; 1132 1133 for (sz = 0, p = cp; *p; p++) 1134 if (*p == '[') 1135 sz += 32; 1136 sz += 2 * (p - cp) + 5; 1137 *ep = smalloc(sz); 1138 (*ep)[1] = '\0'; 1139 p = compile(NULL, &(*ep)[1], &(*ep)[sz], sed_seof); 1140 if (p == &(*ep)[1]) 1141 return *ep; 1142 **ep = circf; 1143 return p; 1144 } 1145 #endif /* !SUS, !SU3, !S42 */ 1146 1147 wint_t 1148 wc_get(char **sc, int move) 1149 { 1150 wint_t c; 1151 char *p = *sc; 1152 wchar_t wcbuf; 1153 int len; 1154 1155 if ((*p & 0200) == 0) { 1156 c = *p; 1157 p += (len = 1); 1158 invchar = 0; 1159 } else if ((len = mbtowc(&wcbuf, p, MB_LEN_MAX)) < 0) { 1160 if (!executing) 1161 fatal("invalid multibyte character: %s", p); 1162 c = (*p++ & 0377); 1163 mbtowc(NULL, NULL, 0); 1164 invchar = 1; 1165 } else if (len == 0) { 1166 c = '\0'; 1167 p++; 1168 invchar = 0; 1169 } else { 1170 c = wcbuf; 1171 p += len; 1172 invchar = 0; 1173 } 1174 if (move) 1175 *sc = p; 1176 return c; 1177 } 1178 1179 /* 1180 * Note that this hash is not optimized to distribute the items 1181 * equally to all buckets. y commands typically handle only a 1182 * small part of the alphabet, thus most characters will have 1183 * no entry in the hash table. If no list exists in the bucket 1184 * for the hash of these characters, the function can return 1185 * quickly. 1186 */ 1187 #define yhash(c) (c & 0177) 1188 1189 struct yitem * 1190 ylook(wint_t c, struct yitem **yt, int make) 1191 { 1192 struct yitem *yp; 1193 int h; 1194 1195 yp = yt[h = yhash(c)]; 1196 while (yp != NULL) { 1197 if (yp->y_oc == c) 1198 break; 1199 yp = yp->y_nxt; 1200 } 1201 if (make && yp == NULL) { 1202 yp = scalloc(1, sizeof *yp); 1203 yp->y_oc = c; 1204 yp->y_nxt = yt[h]; 1205 yt[h] = yp; 1206 } 1207 return yp; 1208 } 1209 1210 void 1211 growsp(const char *msg) 1212 { 1213 const int incr = 128; 1214 int olbend, ogbend, ohend; 1215 1216 olbend = lbend; 1217 ogbend = gbend; 1218 ohend = hend; 1219 if ((linebuf = realloc(linebuf, lbend += incr)) == NULL || 1220 (genbuf = realloc(genbuf, gbend += incr)) == NULL || 1221 (holdsp = realloc(holdsp, hend += incr)) == NULL) 1222 fatal(msg ? msg : "Cannot malloc space"); 1223 while (olbend < lbend) 1224 linebuf[olbend++] = '\0'; 1225 while (ogbend < gbend) 1226 genbuf[ogbend++] = '\0'; 1227 while (ohend < hend) 1228 holdsp[ohend++] = '\0'; 1229 } 1230 1231 static void 1232 wfile(void) 1233 { 1234 int i; 1235 1236 #if !defined (SUS) && !defined (SU3) 1237 if(*cp++ != ' ') 1238 fatal(CGMES, linebuf); 1239 #else /* SUS, SU3 */ 1240 while (*cp == ' ' || *cp == '\t') 1241 cp++; 1242 #endif /* SUS, SU3 */ 1243 1244 text(&fname[nfiles]); 1245 for(i = nfiles - 1; i >= 0; i--) 1246 if(fname[i] != NULL && cmp(fname[nfiles], fname[i]) == 0) { 1247 P(rep)->fcode = fcode[i]; 1248 free(fname[nfiles]); 1249 return; 1250 } 1251 1252 if((P(rep)->fcode = fopen(fname[nfiles], "w")) == NULL) 1253 fatal("Cannot create %s", fname[nfiles]); 1254 fcode[nfiles++] = P(rep)->fcode; 1255 morefiles(); 1256 } 1257 1258 static void 1259 morefiles(void) 1260 { 1261 if ((fname = realloc(fname, (nfiles+1) * sizeof *fname)) == 0 || 1262 (fcode = realloc(fcode, (nfiles+1) * sizeof *fcode)) == 0) 1263 fatal("Too many files in w commands"); 1264 fname[nfiles] = 0; 1265 fcode[nfiles] = 0; 1266 }