diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-08-22 05:58:16 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-08-22 05:58:16 +0000 |
commit | b76cb68979e072a020a0c203bcd4ed2d2ec7afa8 (patch) | |
tree | 21beafc4807f4429ae4d11affbe0c18a1a248b7a | |
parent | 1071ccfd25ec2c218c9d87da98282620e5356626 (diff) | |
download | busybox-w32-b76cb68979e072a020a0c203bcd4ed2d2ec7afa8.tar.gz busybox-w32-b76cb68979e072a020a0c203bcd4ed2d2ec7afa8.tar.bz2 busybox-w32-b76cb68979e072a020a0c203bcd4ed2d2ec7afa8.zip |
A patch from Shu-Hao Chang <shuhao_chang@trend.com.tw> to
fixed sed handling of multiple -e commands
-rw-r--r-- | Changelog | 2 | ||||
-rw-r--r-- | editors/sed.c | 61 | ||||
-rw-r--r-- | sed.c | 61 |
3 files changed, 98 insertions, 26 deletions
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | * Rodney Brown <RDBrown@mira.net> | 14 | * Rodney Brown <RDBrown@mira.net> |
15 | -- Optimized gzip.c, shrinking it be ~1.5k | 15 | -- Optimized gzip.c, shrinking it be ~1.5k |
16 | * Shu-Hao Chang <shuhao_chang@trend.com.tw> | ||
17 | -- Fixed sed handling of multiple -e commands | ||
16 | 18 | ||
17 | -Erik Andersen, --not yet released-- | 19 | -Erik Andersen, --not yet released-- |
18 | 20 | ||
diff --git a/editors/sed.c b/editors/sed.c index 352c5c94f..4fe882d20 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -490,8 +490,23 @@ static void load_cmd_file(char *filename) | |||
490 | } | 490 | } |
491 | } | 491 | } |
492 | 492 | ||
493 | static void print_subst_w_backrefs(const char *line, const char *replace, regmatch_t *regmatch, int matches) | 493 | #define PIPE_MAGIC 0x7f |
494 | #define PIPE_GROW 64 | ||
495 | #define pipeputc(c) \ | ||
496 | { if (pipeline[pipeline_idx] == PIPE_MAGIC) { \ | ||
497 | pipeline = xrealloc(pipeline, pipeline_len+PIPE_GROW); \ | ||
498 | memset(pipeline+pipeline_len, 0, PIPE_GROW); \ | ||
499 | pipeline_len += PIPE_GROW; \ | ||
500 | pipeline[pipeline_len-1] = PIPE_MAGIC; } \ | ||
501 | pipeline[pipeline_idx++] = (c); } | ||
502 | |||
503 | static void print_subst_w_backrefs(const char *line, const char *replace, | ||
504 | regmatch_t *regmatch, char **pipeline_p, int *pipeline_idx_p, | ||
505 | int *pipeline_len_p, int matches) | ||
494 | { | 506 | { |
507 | char *pipeline = *pipeline_p; | ||
508 | int pipeline_idx = *pipeline_idx_p; | ||
509 | int pipeline_len = *pipeline_len_p; | ||
495 | int i; | 510 | int i; |
496 | 511 | ||
497 | /* go through the replacement string */ | 512 | /* go through the replacement string */ |
@@ -508,13 +523,13 @@ static void print_subst_w_backrefs(const char *line, const char *replace, regmat | |||
508 | /* print out the text held in regmatch[backref] */ | 523 | /* print out the text held in regmatch[backref] */ |
509 | if (backref <= matches && regmatch[backref].rm_so != -1) | 524 | if (backref <= matches && regmatch[backref].rm_so != -1) |
510 | for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; j++) | 525 | for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; j++) |
511 | fputc(line[j], stdout); | 526 | pipeputc(line[j]); |
512 | } | 527 | } |
513 | 528 | ||
514 | /* if we find a backslash escaped character, print the character */ | 529 | /* if we find a backslash escaped character, print the character */ |
515 | else if (replace[i] == '\\') { | 530 | else if (replace[i] == '\\') { |
516 | ++i; | 531 | ++i; |
517 | fputc(replace[i], stdout); | 532 | pipeputc(replace[i]); |
518 | } | 533 | } |
519 | 534 | ||
520 | /* if we find an unescaped '&' print out the whole matched text. | 535 | /* if we find an unescaped '&' print out the whole matched text. |
@@ -524,27 +539,41 @@ static void print_subst_w_backrefs(const char *line, const char *replace, regmat | |||
524 | else if (replace[i] == '&' && replace[i-1] != '\\') { | 539 | else if (replace[i] == '&' && replace[i-1] != '\\') { |
525 | int j; | 540 | int j; |
526 | for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) | 541 | for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) |
527 | fputc(line[j], stdout); | 542 | pipeputc(line[j]); |
528 | } | 543 | } |
529 | /* nothing special, just print this char of the replacement string to stdout */ | 544 | /* nothing special, just print this char of the replacement string to stdout */ |
530 | else | 545 | else |
531 | fputc(replace[i], stdout); | 546 | pipeputc(replace[i]); |
532 | } | 547 | } |
548 | *pipeline_p = pipeline; | ||
549 | *pipeline_idx_p = pipeline_idx; | ||
550 | *pipeline_len_p = pipeline_len; | ||
533 | } | 551 | } |
534 | 552 | ||
535 | static int do_subst_command(const struct sed_cmd *sed_cmd, const char *line) | 553 | static int do_subst_command(const struct sed_cmd *sed_cmd, char **line) |
536 | { | 554 | { |
537 | char *hackline = (char *)line; | 555 | char *hackline = *line; |
556 | char *pipeline = 0; | ||
557 | int pipeline_idx = 0; | ||
558 | int pipeline_len = 0; | ||
538 | int altered = 0; | 559 | int altered = 0; |
539 | regmatch_t *regmatch = NULL; | 560 | regmatch_t *regmatch = NULL; |
540 | 561 | ||
541 | /* we only proceed if the substitution 'search' expression matches */ | 562 | /* we only proceed if the substitution 'search' expression matches */ |
542 | if (regexec(sed_cmd->sub_match, line, 0, NULL, 0) == REG_NOMATCH) | 563 | if (regexec(sed_cmd->sub_match, hackline, 0, NULL, 0) == REG_NOMATCH) |
543 | return 0; | 564 | return 0; |
544 | 565 | ||
545 | /* whaddaya know, it matched. get the number of back references */ | 566 | /* whaddaya know, it matched. get the number of back references */ |
546 | regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1)); | 567 | regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1)); |
547 | 568 | ||
569 | /* allocate more PIPE_GROW bytes | ||
570 | if replaced string is larger than original */ | ||
571 | pipeline_len = strlen(hackline)+PIPE_GROW; | ||
572 | pipeline = xmalloc(pipeline_len); | ||
573 | memset(pipeline, 0, pipeline_len); | ||
574 | /* buffer magic */ | ||
575 | pipeline[pipeline_len-1] = PIPE_MAGIC; | ||
576 | |||
548 | /* and now, as long as we've got a line to try matching and if we can match | 577 | /* and now, as long as we've got a line to try matching and if we can match |
549 | * the search string, we make substitutions */ | 578 | * the search string, we make substitutions */ |
550 | while (*hackline && (regexec(sed_cmd->sub_match, hackline, | 579 | while (*hackline && (regexec(sed_cmd->sub_match, hackline, |
@@ -553,10 +582,11 @@ static int do_subst_command(const struct sed_cmd *sed_cmd, const char *line) | |||
553 | 582 | ||
554 | /* print everything before the match */ | 583 | /* print everything before the match */ |
555 | for (i = 0; i < regmatch[0].rm_so; i++) | 584 | for (i = 0; i < regmatch[0].rm_so; i++) |
556 | fputc(hackline[i], stdout); | 585 | pipeputc(hackline[i]); |
557 | 586 | ||
558 | /* then print the substitution string */ | 587 | /* then print the substitution string */ |
559 | print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, | 588 | print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, |
589 | &pipeline, &pipeline_idx, &pipeline_len, | ||
560 | sed_cmd->num_backrefs); | 590 | sed_cmd->num_backrefs); |
561 | 591 | ||
562 | /* advance past the match */ | 592 | /* advance past the match */ |
@@ -569,11 +599,14 @@ static int do_subst_command(const struct sed_cmd *sed_cmd, const char *line) | |||
569 | break; | 599 | break; |
570 | } | 600 | } |
571 | 601 | ||
572 | puts(hackline); | 602 | for (; *hackline; hackline++) pipeputc(*hackline); |
603 | if (pipeline[pipeline_idx] == PIPE_MAGIC) pipeline[pipeline_idx] = 0; | ||
573 | 604 | ||
574 | /* cleanup */ | 605 | /* cleanup */ |
575 | free(regmatch); | 606 | free(regmatch); |
576 | 607 | ||
608 | free(*line); | ||
609 | *line = pipeline; | ||
577 | return altered; | 610 | return altered; |
578 | } | 611 | } |
579 | 612 | ||
@@ -652,12 +685,14 @@ static void process_file(FILE *file) | |||
652 | 685 | ||
653 | /* we print the line once, unless we were told to be quiet */ | 686 | /* we print the line once, unless we were told to be quiet */ |
654 | if (!be_quiet) | 687 | if (!be_quiet) |
655 | altered |= do_subst_command(&sed_cmds[i], line); | 688 | altered |= do_subst_command(&sed_cmds[i], &line); |
656 | 689 | ||
657 | /* we also print the line if we were given the 'p' flag | 690 | /* we also print the line if we were given the 'p' flag |
658 | * (this is quite possibly the second printing) */ | 691 | * (this is quite possibly the second printing) */ |
659 | if (sed_cmds[i].sub_p) | 692 | if (sed_cmds[i].sub_p) |
660 | altered |= do_subst_command(&sed_cmds[i], line); | 693 | altered |= do_subst_command(&sed_cmds[i], &line); |
694 | if (altered && (i+1 >= ncmds || sed_cmds[i+1].cmd != 's')) | ||
695 | puts(line); | ||
661 | 696 | ||
662 | break; | 697 | break; |
663 | 698 | ||
@@ -490,8 +490,23 @@ static void load_cmd_file(char *filename) | |||
490 | } | 490 | } |
491 | } | 491 | } |
492 | 492 | ||
493 | static void print_subst_w_backrefs(const char *line, const char *replace, regmatch_t *regmatch, int matches) | 493 | #define PIPE_MAGIC 0x7f |
494 | #define PIPE_GROW 64 | ||
495 | #define pipeputc(c) \ | ||
496 | { if (pipeline[pipeline_idx] == PIPE_MAGIC) { \ | ||
497 | pipeline = xrealloc(pipeline, pipeline_len+PIPE_GROW); \ | ||
498 | memset(pipeline+pipeline_len, 0, PIPE_GROW); \ | ||
499 | pipeline_len += PIPE_GROW; \ | ||
500 | pipeline[pipeline_len-1] = PIPE_MAGIC; } \ | ||
501 | pipeline[pipeline_idx++] = (c); } | ||
502 | |||
503 | static void print_subst_w_backrefs(const char *line, const char *replace, | ||
504 | regmatch_t *regmatch, char **pipeline_p, int *pipeline_idx_p, | ||
505 | int *pipeline_len_p, int matches) | ||
494 | { | 506 | { |
507 | char *pipeline = *pipeline_p; | ||
508 | int pipeline_idx = *pipeline_idx_p; | ||
509 | int pipeline_len = *pipeline_len_p; | ||
495 | int i; | 510 | int i; |
496 | 511 | ||
497 | /* go through the replacement string */ | 512 | /* go through the replacement string */ |
@@ -508,13 +523,13 @@ static void print_subst_w_backrefs(const char *line, const char *replace, regmat | |||
508 | /* print out the text held in regmatch[backref] */ | 523 | /* print out the text held in regmatch[backref] */ |
509 | if (backref <= matches && regmatch[backref].rm_so != -1) | 524 | if (backref <= matches && regmatch[backref].rm_so != -1) |
510 | for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; j++) | 525 | for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; j++) |
511 | fputc(line[j], stdout); | 526 | pipeputc(line[j]); |
512 | } | 527 | } |
513 | 528 | ||
514 | /* if we find a backslash escaped character, print the character */ | 529 | /* if we find a backslash escaped character, print the character */ |
515 | else if (replace[i] == '\\') { | 530 | else if (replace[i] == '\\') { |
516 | ++i; | 531 | ++i; |
517 | fputc(replace[i], stdout); | 532 | pipeputc(replace[i]); |
518 | } | 533 | } |
519 | 534 | ||
520 | /* if we find an unescaped '&' print out the whole matched text. | 535 | /* if we find an unescaped '&' print out the whole matched text. |
@@ -524,27 +539,41 @@ static void print_subst_w_backrefs(const char *line, const char *replace, regmat | |||
524 | else if (replace[i] == '&' && replace[i-1] != '\\') { | 539 | else if (replace[i] == '&' && replace[i-1] != '\\') { |
525 | int j; | 540 | int j; |
526 | for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) | 541 | for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) |
527 | fputc(line[j], stdout); | 542 | pipeputc(line[j]); |
528 | } | 543 | } |
529 | /* nothing special, just print this char of the replacement string to stdout */ | 544 | /* nothing special, just print this char of the replacement string to stdout */ |
530 | else | 545 | else |
531 | fputc(replace[i], stdout); | 546 | pipeputc(replace[i]); |
532 | } | 547 | } |
548 | *pipeline_p = pipeline; | ||
549 | *pipeline_idx_p = pipeline_idx; | ||
550 | *pipeline_len_p = pipeline_len; | ||
533 | } | 551 | } |
534 | 552 | ||
535 | static int do_subst_command(const struct sed_cmd *sed_cmd, const char *line) | 553 | static int do_subst_command(const struct sed_cmd *sed_cmd, char **line) |
536 | { | 554 | { |
537 | char *hackline = (char *)line; | 555 | char *hackline = *line; |
556 | char *pipeline = 0; | ||
557 | int pipeline_idx = 0; | ||
558 | int pipeline_len = 0; | ||
538 | int altered = 0; | 559 | int altered = 0; |
539 | regmatch_t *regmatch = NULL; | 560 | regmatch_t *regmatch = NULL; |
540 | 561 | ||
541 | /* we only proceed if the substitution 'search' expression matches */ | 562 | /* we only proceed if the substitution 'search' expression matches */ |
542 | if (regexec(sed_cmd->sub_match, line, 0, NULL, 0) == REG_NOMATCH) | 563 | if (regexec(sed_cmd->sub_match, hackline, 0, NULL, 0) == REG_NOMATCH) |
543 | return 0; | 564 | return 0; |
544 | 565 | ||
545 | /* whaddaya know, it matched. get the number of back references */ | 566 | /* whaddaya know, it matched. get the number of back references */ |
546 | regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1)); | 567 | regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1)); |
547 | 568 | ||
569 | /* allocate more PIPE_GROW bytes | ||
570 | if replaced string is larger than original */ | ||
571 | pipeline_len = strlen(hackline)+PIPE_GROW; | ||
572 | pipeline = xmalloc(pipeline_len); | ||
573 | memset(pipeline, 0, pipeline_len); | ||
574 | /* buffer magic */ | ||
575 | pipeline[pipeline_len-1] = PIPE_MAGIC; | ||
576 | |||
548 | /* and now, as long as we've got a line to try matching and if we can match | 577 | /* and now, as long as we've got a line to try matching and if we can match |
549 | * the search string, we make substitutions */ | 578 | * the search string, we make substitutions */ |
550 | while (*hackline && (regexec(sed_cmd->sub_match, hackline, | 579 | while (*hackline && (regexec(sed_cmd->sub_match, hackline, |
@@ -553,10 +582,11 @@ static int do_subst_command(const struct sed_cmd *sed_cmd, const char *line) | |||
553 | 582 | ||
554 | /* print everything before the match */ | 583 | /* print everything before the match */ |
555 | for (i = 0; i < regmatch[0].rm_so; i++) | 584 | for (i = 0; i < regmatch[0].rm_so; i++) |
556 | fputc(hackline[i], stdout); | 585 | pipeputc(hackline[i]); |
557 | 586 | ||
558 | /* then print the substitution string */ | 587 | /* then print the substitution string */ |
559 | print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, | 588 | print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, |
589 | &pipeline, &pipeline_idx, &pipeline_len, | ||
560 | sed_cmd->num_backrefs); | 590 | sed_cmd->num_backrefs); |
561 | 591 | ||
562 | /* advance past the match */ | 592 | /* advance past the match */ |
@@ -569,11 +599,14 @@ static int do_subst_command(const struct sed_cmd *sed_cmd, const char *line) | |||
569 | break; | 599 | break; |
570 | } | 600 | } |
571 | 601 | ||
572 | puts(hackline); | 602 | for (; *hackline; hackline++) pipeputc(*hackline); |
603 | if (pipeline[pipeline_idx] == PIPE_MAGIC) pipeline[pipeline_idx] = 0; | ||
573 | 604 | ||
574 | /* cleanup */ | 605 | /* cleanup */ |
575 | free(regmatch); | 606 | free(regmatch); |
576 | 607 | ||
608 | free(*line); | ||
609 | *line = pipeline; | ||
577 | return altered; | 610 | return altered; |
578 | } | 611 | } |
579 | 612 | ||
@@ -652,12 +685,14 @@ static void process_file(FILE *file) | |||
652 | 685 | ||
653 | /* we print the line once, unless we were told to be quiet */ | 686 | /* we print the line once, unless we were told to be quiet */ |
654 | if (!be_quiet) | 687 | if (!be_quiet) |
655 | altered |= do_subst_command(&sed_cmds[i], line); | 688 | altered |= do_subst_command(&sed_cmds[i], &line); |
656 | 689 | ||
657 | /* we also print the line if we were given the 'p' flag | 690 | /* we also print the line if we were given the 'p' flag |
658 | * (this is quite possibly the second printing) */ | 691 | * (this is quite possibly the second printing) */ |
659 | if (sed_cmds[i].sub_p) | 692 | if (sed_cmds[i].sub_p) |
660 | altered |= do_subst_command(&sed_cmds[i], line); | 693 | altered |= do_subst_command(&sed_cmds[i], &line); |
694 | if (altered && (i+1 >= ncmds || sed_cmds[i+1].cmd != 's')) | ||
695 | puts(line); | ||
661 | 696 | ||
662 | break; | 697 | break; |
663 | 698 | ||