1 /* 2 * Copyright (c) 2005, 2008 Sun Microsystems, Inc. All Rights Reserved. 3 * Use is subject to license terms. 4 * 5 * Copyright (c) 1984 AT&T 6 * All Rights Reserved 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * http://www.apache.org/licenses/LICENSE-2.0. 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 16 * or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 #include "apr.h" 22 #include "apr_lib.h" 23 #include "libsed.h" 24 #include "sed.h" 25 #include "apr_strings.h" 26 #include "regexp.h" 27 28 char *trans[040] = { 29 "\\01", 30 "\\02", 31 "\\03", 32 "\\04", 33 "\\05", 34 "\\06", 35 "\\07", 36 "-<", 37 "->", 38 "\n", 39 "\\13", 40 "\\14", 41 "\\15", 42 "\\16", 43 "\\17", 44 "\\20", 45 "\\21", 46 "\\22", 47 "\\23", 48 "\\24", 49 "\\25", 50 "\\26", 51 "\\27", 52 "\\30", 53 "\\31", 54 "\\32", 55 "\\33", 56 "\\34", 57 "\\35", 58 "\\36", 59 "\\37" 60 }; 61 char rub[] = {"\\177"}; 62 63 extern int sed_step(char *p1, char *p2, int circf, step_vars_storage *vars); 64 static int substitute(sed_eval_t *eval, sed_reptr_t *ipc, 65 step_vars_storage *step_vars); 66 static apr_status_t execute(sed_eval_t *eval); 67 static int match(sed_eval_t *eval, char *expbuf, int gf, 68 step_vars_storage *step_vars); 69 static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n, 70 step_vars_storage *step_vars); 71 static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2); 72 static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, 73 step_vars_storage *step_vars); 74 static void wline(sed_eval_t *eval, char *buf, int sz); 75 static void arout(sed_eval_t *eval); 76 77 static void eval_errf(sed_eval_t *eval, const char *fmt, ...) 78 { 79 if (eval->errfn && eval->pool) { 80 va_list args; 81 const char* error; 82 va_start(args, fmt); 83 error = apr_pvsprintf(eval->pool, fmt, args); 84 eval->errfn(eval->data, error); 85 va_end(args); 86 } 87 } 88 89 #define INIT_BUF_SIZE 1024 90 91 /* 92 * grow_buffer 93 */ 94 static void grow_buffer(apr_pool_t *pool, char **buffer, 95 char **spend, unsigned int *cursize, 96 unsigned int newsize) 97 { 98 char* newbuffer = NULL; 99 int spendsize = 0; 100 if (*cursize >= newsize) 101 return; 102 /* Align it to 4 KB boundary */ 103 newsize = (newsize + ((1 << 12) - 1)) & ~((1 << 12) -1); 104 newbuffer = apr_pcalloc(pool, newsize); 105 if (*spend && *buffer && (*cursize > 0)) { 106 spendsize = *spend - *buffer; 107 } 108 if ((*cursize > 0) && *buffer) { 109 memcpy(newbuffer, *buffer, *cursize); 110 } 111 *buffer = newbuffer; 112 *cursize = newsize; 113 if (spend != buffer) { 114 *spend = *buffer + spendsize; 115 } 116 } 117 118 /* 119 * grow_line_buffer 120 */ 121 static void grow_line_buffer(sed_eval_t *eval, int newsize) 122 { 123 grow_buffer(eval->pool, &eval->linebuf, &eval->lspend, 124 &eval->lsize, newsize); 125 } 126 127 /* 128 * grow_hold_buffer 129 */ 130 static void grow_hold_buffer(sed_eval_t *eval, int newsize) 131 { 132 grow_buffer(eval->pool, &eval->holdbuf, &eval->hspend, 133 &eval->hsize, newsize); 134 } 135 136 /* 137 * grow_gen_buffer 138 */ 139 static void grow_gen_buffer(sed_eval_t *eval, int newsize, 140 char **gspend) 141 { 142 if (gspend == NULL) { 143 gspend = &eval->genbuf; 144 } 145 grow_buffer(eval->pool, &eval->genbuf, gspend, 146 &eval->gsize, newsize); 147 eval->lcomend = &eval->genbuf[71]; 148 } 149 150 /* 151 * appendmem_to_linebuf 152 */ 153 static void appendmem_to_linebuf(sed_eval_t *eval, const char* sz, int len) 154 { 155 unsigned int reqsize = (eval->lspend - eval->linebuf) + len; 156 if (eval->lsize < reqsize) { 157 grow_line_buffer(eval, reqsize); 158 } 159 memcpy(eval->lspend, sz, len); 160 eval->lspend += len; 161 } 162 163 /* 164 * append_to_linebuf 165 */ 166 static void append_to_linebuf(sed_eval_t *eval, const char* sz) 167 { 168 int len = strlen(sz); 169 /* Copy string including null character */ 170 appendmem_to_linebuf(eval, sz, len + 1); 171 --eval->lspend; /* lspend will now point to NULL character */ 172 } 173 174 /* 175 * copy_to_linebuf 176 */ 177 static void copy_to_linebuf(sed_eval_t *eval, const char* sz) 178 { 179 eval->lspend = eval->linebuf; 180 append_to_linebuf(eval, sz); 181 } 182 183 /* 184 * append_to_holdbuf 185 */ 186 static void append_to_holdbuf(sed_eval_t *eval, const char* sz) 187 { 188 int len = strlen(sz); 189 unsigned int reqsize = (eval->hspend - eval->holdbuf) + len + 1; 190 if (eval->hsize <= reqsize) { 191 grow_hold_buffer(eval, reqsize); 192 } 193 strcpy(eval->hspend, sz); 194 /* hspend will now point to NULL character */ 195 eval->hspend += len; 196 } 197 198 /* 199 * copy_to_holdbuf 200 */ 201 static void copy_to_holdbuf(sed_eval_t *eval, const char* sz) 202 { 203 eval->hspend = eval->holdbuf; 204 append_to_holdbuf(eval, sz); 205 } 206 207 /* 208 * append_to_genbuf 209 */ 210 static void append_to_genbuf(sed_eval_t *eval, const char* sz, char **gspend) 211 { 212 int len = strlen(sz); 213 unsigned int reqsize = (*gspend - eval->genbuf) + len + 1; 214 if (eval->gsize < reqsize) { 215 grow_gen_buffer(eval, reqsize, gspend); 216 } 217 strcpy(*gspend, sz); 218 /* *gspend will now point to NULL character */ 219 *gspend += len; 220 } 221 222 /* 223 * copy_to_genbuf 224 */ 225 static void copy_to_genbuf(sed_eval_t *eval, const char* sz) 226 { 227 int len = strlen(sz); 228 unsigned int reqsize = len + 1; 229 if (eval->gsize < reqsize) { 230 grow_gen_buffer(eval, reqsize, NULL); 231 } 232 } 233 234 /* 235 * sed_init_eval 236 */ 237 apr_status_t sed_init_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data, sed_write_fn_t *writefn, apr_pool_t* p) 238 { 239 memset(eval, 0, sizeof(*eval)); 240 eval->pool = p; 241 eval->writefn = writefn; 242 return sed_reset_eval(eval, commands, errfn, data); 243 } 244 245 /* 246 * sed_reset_eval 247 */ 248 apr_status_t sed_reset_eval(sed_eval_t *eval, sed_commands_t *commands, sed_err_fn_t *errfn, void *data) 249 { 250 int i; 251 252 eval->errfn = errfn; 253 eval->data = data; 254 255 eval->commands = commands; 256 257 eval->lnum = 0; 258 eval->fout = NULL; 259 260 if (eval->linebuf == NULL) { 261 eval->lsize = INIT_BUF_SIZE; 262 eval->linebuf = apr_pcalloc(eval->pool, eval->lsize); 263 } 264 if (eval->holdbuf == NULL) { 265 eval->hsize = INIT_BUF_SIZE; 266 eval->holdbuf = apr_pcalloc(eval->pool, eval->hsize); 267 } 268 if (eval->genbuf == NULL) { 269 eval->gsize = INIT_BUF_SIZE; 270 eval->genbuf = apr_pcalloc(eval->pool, eval->gsize); 271 } 272 eval->lspend = eval->linebuf; 273 eval->hspend = eval->holdbuf; 274 eval->lcomend = &eval->genbuf[71]; 275 276 for (i = 0; i < sizeof(eval->abuf) / sizeof(eval->abuf[0]); i++) 277 eval->abuf[i] = NULL; 278 eval->aptr = eval->abuf; 279 eval->pending = NULL; 280 eval->inar = apr_pcalloc(eval->pool, commands->nrep * sizeof(unsigned char)); 281 eval->nrep = commands->nrep; 282 283 eval->dolflag = 0; 284 eval->sflag = 0; 285 eval->jflag = 0; 286 eval->delflag = 0; 287 eval->lreadyflag = 0; 288 eval->quitflag = 0; 289 eval->finalflag = 1; /* assume we're evaluating only one file/stream */ 290 eval->numpass = 0; 291 eval->nullmatch = 0; 292 eval->col = 0; 293 294 for (i = 0; i < commands->nfiles; i++) { 295 const char* filename = commands->fname[i]; 296 if (apr_file_open(&eval->fcode[i], filename, 297 APR_WRITE | APR_CREATE, APR_OS_DEFAULT, 298 eval->pool) != APR_SUCCESS) { 299 eval_errf(eval, SEDERR_COMES, filename); 300 return APR_EGENERAL; 301 } 302 } 303 304 return APR_SUCCESS; 305 } 306 307 /* 308 * sed_destroy_eval 309 */ 310 void sed_destroy_eval(sed_eval_t *eval) 311 { 312 int i; 313 /* eval->linebuf, eval->holdbuf, eval->genbuf and eval->inar are allocated 314 * on pool. It will be freed when pool will be freed */ 315 for (i = 0; i < eval->commands->nfiles; i++) { 316 if (eval->fcode[i] != NULL) { 317 apr_file_close(eval->fcode[i]); 318 eval->fcode[i] = NULL; 319 } 320 } 321 } 322 323 /* 324 * sed_eval_file 325 */ 326 apr_status_t sed_eval_file(sed_eval_t *eval, apr_file_t *fin, void *fout) 327 { 328 for (;;) { 329 char buf[1024]; 330 apr_size_t read_bytes = 0; 331 332 read_bytes = sizeof(buf); 333 if (apr_file_read(fin, buf, &read_bytes) != APR_SUCCESS) 334 break; 335 336 if (sed_eval_buffer(eval, buf, read_bytes, fout) != APR_SUCCESS) 337 return APR_EGENERAL; 338 339 if (eval->quitflag) 340 return APR_SUCCESS; 341 } 342 343 return sed_finalize_eval(eval, fout); 344 } 345 346 /* 347 * sed_eval_buffer 348 */ 349 apr_status_t sed_eval_buffer(sed_eval_t *eval, const char *buf, int bufsz, void *fout) 350 { 351 apr_status_t rv; 352 353 if (eval->quitflag) 354 return APR_SUCCESS; 355 356 if (!sed_canbe_finalized(eval->commands)) { 357 /* Commands were not finalized properly. */ 358 const char* error = sed_get_finalize_error(eval->commands, eval->pool); 359 if (error) { 360 eval_errf(eval, error); 361 return APR_EGENERAL; 362 } 363 } 364 365 eval->fout = fout; 366 367 /* Process leftovers */ 368 if (bufsz && eval->lreadyflag) { 369 eval->lreadyflag = 0; 370 eval->lspend--; 371 *eval->lspend = '\0'; 372 rv = execute(eval); 373 if (rv != 0) 374 return APR_EGENERAL; 375 } 376 377 while (bufsz) { 378 char *n; 379 int llen; 380 381 n = memchr(buf, '\n', bufsz); 382 if (n == NULL) 383 break; 384 385 llen = n - buf; 386 if (llen == bufsz - 1) { 387 /* This might be the last line; delay its processing */ 388 eval->lreadyflag = 1; 389 break; 390 } 391 392 appendmem_to_linebuf(eval, buf, llen + 1); 393 --eval->lspend; 394 /* replace new line character with NULL */ 395 *eval->lspend = '\0'; 396 buf += (llen + 1); 397 bufsz -= (llen + 1); 398 rv = execute(eval); 399 if (rv != 0) 400 return APR_EGENERAL; 401 if (eval->quitflag) 402 break; 403 } 404 405 /* Save the leftovers for later */ 406 if (bufsz) { 407 appendmem_to_linebuf(eval, buf, bufsz); 408 } 409 410 return APR_SUCCESS; 411 } 412 413 /* 414 * sed_finalize_eval 415 */ 416 apr_status_t sed_finalize_eval(sed_eval_t *eval, void *fout) 417 { 418 if (eval->quitflag) 419 return APR_SUCCESS; 420 421 if (eval->finalflag) 422 eval->dolflag = 1; 423 424 eval->fout = fout; 425 426 /* Process leftovers */ 427 if (eval->lspend > eval->linebuf) { 428 apr_status_t rv; 429 430 if (eval->lreadyflag) { 431 eval->lreadyflag = 0; 432 eval->lspend--; 433 } else { 434 /* Code can probably reach here when last character in output 435 * buffer is not a newline. 436 */ 437 /* Assure space for NULL */ 438 append_to_linebuf(eval, ""); 439 } 440 441 *eval->lspend = '\0'; 442 rv = execute(eval); 443 if (rv != 0) 444 return APR_EGENERAL; 445 } 446 447 eval->quitflag = 1; 448 449 return APR_SUCCESS; 450 } 451 452 /* 453 * execute 454 */ 455 static apr_status_t execute(sed_eval_t *eval) 456 { 457 sed_reptr_t *ipc = eval->commands->ptrspace; 458 step_vars_storage step_vars; 459 460 eval->lnum++; 461 462 eval->sflag = 0; 463 464 if (eval->pending) { 465 ipc = eval->pending; 466 eval->pending = NULL; 467 } 468 469 memset(&step_vars, 0, sizeof(step_vars)); 470 471 while (ipc->command) { 472 char *p1; 473 char *p2; 474 apr_status_t rv; 475 int c; 476 477 p1 = ipc->ad1; 478 p2 = ipc->ad2; 479 480 if (p1) { 481 482 if (eval->inar[ipc->nrep]) { 483 if (*p2 == CEND) { 484 p1 = 0; 485 } else if (*p2 == CLNUM) { 486 c = (unsigned char)p2[1]; 487 if (eval->lnum > eval->commands->tlno[c]) { 488 eval->inar[ipc->nrep] = 0; 489 if (ipc->negfl) 490 goto yes; 491 ipc = ipc->next; 492 continue; 493 } 494 if (eval->lnum == eval->commands->tlno[c]) { 495 eval->inar[ipc->nrep] = 0; 496 } 497 } else if (match(eval, p2, 0, &step_vars)) { 498 eval->inar[ipc->nrep] = 0; 499 } 500 } else if (*p1 == CEND) { 501 if (!eval->dolflag) { 502 if (ipc->negfl) 503 goto yes; 504 ipc = ipc->next; 505 continue; 506 } 507 } else if (*p1 == CLNUM) { 508 c = (unsigned char)p1[1]; 509 if (eval->lnum != eval->commands->tlno[c]) { 510 if (ipc->negfl) 511 goto yes; 512 ipc = ipc->next; 513 continue; 514 } 515 if (p2) 516 eval->inar[ipc->nrep] = 1; 517 } else if (match(eval, p1, 0, &step_vars)) { 518 if (p2) 519 eval->inar[ipc->nrep] = 1; 520 } else { 521 if (ipc->negfl) 522 goto yes; 523 ipc = ipc->next; 524 continue; 525 } 526 } 527 528 if (ipc->negfl) { 529 ipc = ipc->next; 530 continue; 531 } 532 533 yes: 534 rv = command(eval, ipc, &step_vars); 535 if (rv != APR_SUCCESS) 536 return rv; 537 538 if (eval->quitflag) 539 return APR_SUCCESS; 540 541 if (eval->pending) 542 return APR_SUCCESS; 543 544 if (eval->delflag) 545 break; 546 547 if (eval->jflag) { 548 eval->jflag = 0; 549 if ((ipc = ipc->lb1) == 0) { 550 ipc = eval->commands->ptrspace; 551 break; 552 } 553 } else 554 ipc = ipc->next; 555 } 556 557 if (!eval->commands->nflag && !eval->delflag) 558 wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 559 560 if (eval->aptr > eval->abuf) 561 arout(eval); 562 563 eval->delflag = 0; 564 565 eval->lspend = eval->linebuf; 566 567 return APR_SUCCESS; 568 } 569 570 /* 571 * match 572 */ 573 static int match(sed_eval_t *eval, char *expbuf, int gf, 574 step_vars_storage *step_vars) 575 { 576 char *p1; 577 int circf; 578 579 if(gf) { 580 if(*expbuf) return(0); 581 step_vars->locs = p1 = step_vars->loc2; 582 } else { 583 p1 = eval->linebuf; 584 step_vars->locs = 0; 585 } 586 587 circf = *expbuf++; 588 return(sed_step(p1, expbuf, circf, step_vars)); 589 } 590 591 /* 592 * substitute 593 */ 594 static int substitute(sed_eval_t *eval, sed_reptr_t *ipc, 595 step_vars_storage *step_vars) 596 { 597 if(match(eval, ipc->re1, 0, step_vars) == 0) return(0); 598 599 eval->numpass = 0; 600 eval->sflag = 0; /* Flags if any substitution was made */ 601 if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS) 602 return -1; 603 604 if(ipc->gfl) { 605 while(*step_vars->loc2) { 606 if(match(eval, ipc->re1, 1, step_vars) == 0) break; 607 if (dosub(eval, ipc->rhs, ipc->gfl, step_vars) != APR_SUCCESS) 608 return -1; 609 } 610 } 611 return(eval->sflag); 612 } 613 614 /* 615 * dosub 616 */ 617 static apr_status_t dosub(sed_eval_t *eval, char *rhsbuf, int n, 618 step_vars_storage *step_vars) 619 { 620 char *lp, *sp, *rp; 621 int c; 622 apr_status_t rv = APR_SUCCESS; 623 624 if(n > 0 && n < 999) { 625 eval->numpass++; 626 if(n != eval->numpass) return APR_SUCCESS; 627 } 628 eval->sflag = 1; 629 lp = eval->linebuf; 630 sp = eval->genbuf; 631 rp = rhsbuf; 632 sp = place(eval, sp, lp, step_vars->loc1); 633 while ((c = *rp++) != 0) { 634 if (c == '&') { 635 sp = place(eval, sp, step_vars->loc1, step_vars->loc2); 636 if (sp == NULL) 637 return APR_EGENERAL; 638 } 639 else if (c == '\\') { 640 c = *rp++; 641 if (c >= '1' && c < NBRA+'1') { 642 sp = place(eval, sp, step_vars->braslist[c-'1'], 643 step_vars->braelist[c-'1']); 644 if (sp == NULL) 645 return APR_EGENERAL; 646 } 647 else 648 *sp++ = c; 649 } else 650 *sp++ = c; 651 if (sp >= eval->genbuf + eval->gsize) { 652 /* expand genbuf and set the sp appropriately */ 653 grow_gen_buffer(eval, eval->gsize + 1024, &sp); 654 } 655 } 656 lp = step_vars->loc2; 657 step_vars->loc2 = sp - eval->genbuf + eval->linebuf; 658 append_to_genbuf(eval, lp, &sp); 659 copy_to_linebuf(eval, eval->genbuf); 660 return rv; 661 } 662 663 /* 664 * place 665 */ 666 static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2) 667 { 668 char *sp = asp; 669 int n = al2 - al1; 670 unsigned int reqsize = (sp - eval->genbuf) + n + 1; 671 672 if (eval->gsize < reqsize) { 673 grow_gen_buffer(eval, reqsize, &sp); 674 } 675 memcpy(sp, al1, n); 676 return sp + n; 677 } 678 679 /* 680 * command 681 */ 682 static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, 683 step_vars_storage *step_vars) 684 { 685 int i; 686 char *p1, *p2, *p3; 687 int length; 688 char sz[32]; /* 32 bytes enough to store 64 bit integer in decimal */ 689 690 691 switch(ipc->command) { 692 693 case ACOM: 694 if(eval->aptr >= &eval->abuf[SED_ABUFSIZE]) { 695 eval_errf(eval, SEDERR_TMAMES, eval->lnum); 696 } else { 697 *eval->aptr++ = ipc; 698 *eval->aptr = NULL; 699 } 700 break; 701 702 case CCOM: 703 eval->delflag = 1; 704 if(!eval->inar[ipc->nrep] || eval->dolflag) { 705 for (p1 = ipc->re1; *p1; p1++) 706 ; 707 wline(eval, ipc->re1, p1 - ipc->re1); 708 } 709 break; 710 case DCOM: 711 eval->delflag++; 712 break; 713 case CDCOM: 714 p1 = eval->linebuf; 715 716 while(*p1 != '\n') { 717 if(*p1++ == 0) { 718 eval->delflag++; 719 return APR_SUCCESS; 720 } 721 } 722 723 p1++; 724 copy_to_linebuf(eval, p1); 725 eval->jflag++; 726 break; 727 728 case EQCOM: 729 length = apr_snprintf(sz, sizeof(sz), "%d", (int) eval->lnum); 730 wline(eval, sz, length); 731 break; 732 733 case GCOM: 734 copy_to_linebuf(eval, eval->holdbuf); 735 break; 736 737 case CGCOM: 738 append_to_linebuf(eval, "\n"); 739 append_to_linebuf(eval, eval->holdbuf); 740 break; 741 742 case HCOM: 743 copy_to_holdbuf(eval, eval->linebuf); 744 break; 745 746 case CHCOM: 747 append_to_holdbuf(eval, "\n"); 748 append_to_holdbuf(eval, eval->linebuf); 749 break; 750 751 case ICOM: 752 for (p1 = ipc->re1; *p1; p1++); 753 wline(eval, ipc->re1, p1 - ipc->re1); 754 break; 755 756 case BCOM: 757 eval->jflag = 1; 758 break; 759 760 761 case LCOM: 762 p1 = eval->linebuf; 763 p2 = eval->genbuf; 764 eval->genbuf[72] = 0; 765 while(*p1) 766 if((unsigned char)*p1 >= 040) { 767 if(*p1 == 0177) { 768 p3 = rub; 769 while ((*p2++ = *p3++) != 0) 770 if(p2 >= eval->lcomend) { 771 *p2 = '\\'; 772 wline(eval, eval->genbuf, 773 strlen(eval->genbuf)); 774 p2 = eval->genbuf; 775 } 776 p2--; 777 p1++; 778 continue; 779 } 780 if(!isprint(*p1 & 0377)) { 781 *p2++ = '\\'; 782 if(p2 >= eval->lcomend) { 783 *p2 = '\\'; 784 wline(eval, eval->genbuf, strlen(eval->genbuf)); 785 p2 = eval->genbuf; 786 } 787 *p2++ = (*p1 >> 6) + '0'; 788 if(p2 >= eval->lcomend) { 789 *p2 = '\\'; 790 wline(eval, eval->genbuf, strlen(eval->genbuf)); 791 p2 = eval->genbuf; 792 } 793 *p2++ = ((*p1 >> 3) & 07) + '0'; 794 if(p2 >= eval->lcomend) { 795 *p2 = '\\'; 796 wline(eval, eval->genbuf, strlen(eval->genbuf)); 797 p2 = eval->genbuf; 798 } 799 *p2++ = (*p1++ & 07) + '0'; 800 if(p2 >= eval->lcomend) { 801 *p2 = '\\'; 802 wline(eval, eval->genbuf, strlen(eval->genbuf)); 803 p2 = eval->genbuf; 804 } 805 } else { 806 *p2++ = *p1++; 807 if(p2 >= eval->lcomend) { 808 *p2 = '\\'; 809 wline(eval, eval->genbuf, strlen(eval->genbuf)); 810 p2 = eval->genbuf; 811 } 812 } 813 } else { 814 p3 = trans[(unsigned char)*p1-1]; 815 while ((*p2++ = *p3++) != 0) 816 if(p2 >= eval->lcomend) { 817 *p2 = '\\'; 818 wline(eval, eval->genbuf, strlen(eval->genbuf)); 819 p2 = eval->genbuf; 820 } 821 p2--; 822 p1++; 823 } 824 *p2 = 0; 825 wline(eval, eval->genbuf, strlen(eval->genbuf)); 826 break; 827 828 case NCOM: 829 if(!eval->commands->nflag) { 830 wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 831 } 832 833 if(eval->aptr > eval->abuf) 834 arout(eval); 835 eval->lspend = eval->linebuf; 836 eval->pending = ipc->next; 837 838 break; 839 case CNCOM: 840 if(eval->aptr > eval->abuf) 841 arout(eval); 842 append_to_linebuf(eval, "\n"); 843 eval->pending = ipc->next; 844 break; 845 846 case PCOM: 847 wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 848 break; 849 case CPCOM: 850 for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++); 851 wline(eval, eval->linebuf, p1 - eval->linebuf); 852 break; 853 854 case QCOM: 855 if (!eval->commands->nflag) 856 wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 857 858 if(eval->aptr > eval->abuf) 859 arout(eval); 860 861 eval->quitflag = 1; 862 break; 863 case RCOM: 864 if(eval->aptr >= &eval->abuf[SED_ABUFSIZE]) { 865 eval_errf(eval, SEDERR_TMRMES, eval->lnum); 866 } else { 867 *eval->aptr++ = ipc; 868 *eval->aptr = NULL; 869 } 870 break; 871 872 case SCOM: 873 i = substitute(eval, ipc, step_vars); 874 if (i == -1) { 875 return APR_EGENERAL; 876 } 877 if(ipc->pfl && eval->commands->nflag && i) { 878 if(ipc->pfl == 1) { 879 wline(eval, eval->linebuf, eval->lspend - eval->linebuf); 880 } else { 881 for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++); 882 wline(eval, eval->linebuf, p1 - eval->linebuf); 883 } 884 } 885 if (i && (ipc->findex >= 0) && eval->fcode[ipc->findex]) 886 apr_file_printf(eval->fcode[ipc->findex], "%s\n", 887 eval->linebuf); 888 break; 889 890 case TCOM: 891 if(eval->sflag == 0) break; 892 eval->sflag = 0; 893 eval->jflag = 1; 894 break; 895 896 case WCOM: 897 if (ipc->findex >= 0) 898 apr_file_printf(eval->fcode[ipc->findex], "%s\n", 899 eval->linebuf); 900 break; 901 case XCOM: 902 copy_to_genbuf(eval, eval->linebuf); 903 copy_to_linebuf(eval, eval->holdbuf); 904 copy_to_holdbuf(eval, eval->genbuf); 905 break; 906 907 case YCOM: 908 p1 = eval->linebuf; 909 p2 = ipc->re1; 910 while((*p1 = p2[(unsigned char)*p1]) != 0) p1++; 911 break; 912 } 913 return APR_SUCCESS; 914 } 915 916 /* 917 * arout 918 */ 919 static void arout(sed_eval_t *eval) 920 { 921 eval->aptr = eval->abuf - 1; 922 while (*++eval->aptr) { 923 if ((*eval->aptr)->command == ACOM) { 924 char *p1; 925 926 for (p1 = (*eval->aptr)->re1; *p1; p1++); 927 wline(eval, (*eval->aptr)->re1, p1 - (*eval->aptr)->re1); 928 } else { 929 apr_file_t *fi = NULL; 930 char buf[512]; 931 apr_size_t n = sizeof(buf); 932 933 if (apr_file_open(&fi, (*eval->aptr)->re1, APR_READ, 0, eval->pool) 934 != APR_SUCCESS) 935 continue; 936 while ((apr_file_read(fi, buf, &n)) == APR_SUCCESS) { 937 if (n == 0) 938 break; 939 eval->writefn(eval->fout, buf, n); 940 n = sizeof(buf); 941 } 942 apr_file_close(fi); 943 } 944 } 945 eval->aptr = eval->abuf; 946 *eval->aptr = NULL; 947 } 948 949 /* 950 * wline 951 */ 952 static void wline(sed_eval_t *eval, char *buf, int sz) 953 { 954 eval->writefn(eval->fout, buf, sz); 955 eval->writefn(eval->fout, "\n", 1); 956 } 957 958