diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2003-04-12 16:10:42 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2003-04-12 16:10:42 +0000 |
commit | fc4cb4dbb5e208139d3b7f81d00694212524ab5d (patch) | |
tree | 712e5083ae830063fdb26e10d4f30fbc1364f6fe | |
parent | d4185b0e1589d1d4e847f25a730424bb75f0a744 (diff) | |
download | busybox-w32-fc4cb4dbb5e208139d3b7f81d00694212524ab5d.tar.gz busybox-w32-fc4cb4dbb5e208139d3b7f81d00694212524ab5d.tar.bz2 busybox-w32-fc4cb4dbb5e208139d3b7f81d00694212524ab5d.zip |
Fix logic error in grouped commands
-rw-r--r-- | editors/sed.c | 67 |
1 files changed, 25 insertions, 42 deletions
diff --git a/editors/sed.c b/editors/sed.c index d90d63e43..bda359219 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -68,6 +68,13 @@ typedef struct sed_cmd_s { | |||
68 | regex_t *beg_match; /* sed -e '/match/cmd' */ | 68 | regex_t *beg_match; /* sed -e '/match/cmd' */ |
69 | regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ | 69 | regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ |
70 | 70 | ||
71 | int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */ | ||
72 | int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */ | ||
73 | |||
74 | /* inversion flag */ | ||
75 | int invert; /* the '!' after the address */ | ||
76 | // int block_cmd; /* This command is part of a group that has a command address */ | ||
77 | |||
71 | /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ | 78 | /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ |
72 | 79 | ||
73 | /* sed -e 's/sub_match/replace/' */ | 80 | /* sed -e 's/sub_match/replace/' */ |
@@ -80,9 +87,6 @@ typedef struct sed_cmd_s { | |||
80 | /* FILE COMMAND (r) SPECIFIC FIELDS */ | 87 | /* FILE COMMAND (r) SPECIFIC FIELDS */ |
81 | char *filename; | 88 | char *filename; |
82 | 89 | ||
83 | /* address storage */ | ||
84 | int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */ | ||
85 | int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */ | ||
86 | /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ | 90 | /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ |
87 | 91 | ||
88 | unsigned int num_backrefs:4; /* how many back references (\1..\9) */ | 92 | unsigned int num_backrefs:4; /* how many back references (\1..\9) */ |
@@ -98,9 +102,6 @@ typedef struct sed_cmd_s { | |||
98 | /* the command */ | 102 | /* the command */ |
99 | char cmd; /* p,d,s (add more at your leisure :-) */ | 103 | char cmd; /* p,d,s (add more at your leisure :-) */ |
100 | 104 | ||
101 | /* inversion flag */ | ||
102 | int invert; /* the '!' after the address */ | ||
103 | |||
104 | /* Branch commands */ | 105 | /* Branch commands */ |
105 | char *label; | 106 | char *label; |
106 | 107 | ||
@@ -124,9 +125,7 @@ static const char bad_format_in_subst[] = | |||
124 | /* linked list of sed commands */ | 125 | /* linked list of sed commands */ |
125 | static sed_cmd_t sed_cmd_head; | 126 | static sed_cmd_t sed_cmd_head; |
126 | static sed_cmd_t *sed_cmd_tail = &sed_cmd_head; | 127 | static sed_cmd_t *sed_cmd_tail = &sed_cmd_head; |
127 | static sed_cmd_t *block_cmd; | ||
128 | 128 | ||
129 | static int in_block = 0; | ||
130 | const char *const semicolon_whitespace = "; \n\r\t\v\0"; | 129 | const char *const semicolon_whitespace = "; \n\r\t\v\0"; |
131 | static regex_t *previous_regex_ptr = NULL; | 130 | static regex_t *previous_regex_ptr = NULL; |
132 | 131 | ||
@@ -484,7 +483,7 @@ static char *parse_cmd_str(sed_cmd_t * sed_cmd, char *cmdstr) | |||
484 | /* if it wasnt a single-letter command that takes no arguments | 483 | /* if it wasnt a single-letter command that takes no arguments |
485 | * then it must be an invalid command. | 484 | * then it must be an invalid command. |
486 | */ | 485 | */ |
487 | else if (strchr("dghnNpPqx=", sed_cmd->cmd) == 0) { | 486 | else if (strchr("dghnNpPqx={}", sed_cmd->cmd) == 0) { |
488 | bb_error_msg_and_die("Unsupported command %c", sed_cmd->cmd); | 487 | bb_error_msg_and_die("Unsupported command %c", sed_cmd->cmd); |
489 | } | 488 | } |
490 | 489 | ||
@@ -512,13 +511,6 @@ static char *add_cmd(sed_cmd_t * sed_cmd, char *cmdstr) | |||
512 | return (strpbrk(cmdstr, "\n\r")); | 511 | return (strpbrk(cmdstr, "\n\r")); |
513 | } | 512 | } |
514 | 513 | ||
515 | /* Test for end of block */ | ||
516 | if (*cmdstr == '}') { | ||
517 | in_block = 0; | ||
518 | cmdstr++; | ||
519 | return (cmdstr); | ||
520 | } | ||
521 | |||
522 | /* parse the command | 514 | /* parse the command |
523 | * format is: [addr][,addr]cmd | 515 | * format is: [addr][,addr]cmd |
524 | * |----||-----||-| | 516 | * |----||-----||-| |
@@ -571,28 +563,9 @@ static char *add_cmd(sed_cmd_t * sed_cmd, char *cmdstr) | |||
571 | if (*cmdstr == '\0') | 563 | if (*cmdstr == '\0') |
572 | bb_error_msg_and_die("missing command"); | 564 | bb_error_msg_and_die("missing command"); |
573 | 565 | ||
574 | /* This is the start of a block of commands */ | ||
575 | if (*cmdstr == '{') { | ||
576 | if (in_block != 0) { | ||
577 | bb_error_msg_and_die("cant handle sub-blocks"); | ||
578 | } | ||
579 | in_block = 1; | ||
580 | block_cmd = sed_cmd; | ||
581 | |||
582 | return (cmdstr + 1); | ||
583 | } | ||
584 | |||
585 | sed_cmd->cmd = *cmdstr; | 566 | sed_cmd->cmd = *cmdstr; |
586 | cmdstr++; | 567 | cmdstr++; |
587 | 568 | ||
588 | if (in_block == 1) { | ||
589 | sed_cmd->beg_match = block_cmd->beg_match; | ||
590 | sed_cmd->end_match = block_cmd->end_match; | ||
591 | sed_cmd->beg_line = block_cmd->beg_line; | ||
592 | sed_cmd->end_line = block_cmd->end_line; | ||
593 | sed_cmd->invert = block_cmd->invert; | ||
594 | } | ||
595 | |||
596 | cmdstr = parse_cmd_str(sed_cmd, cmdstr); | 569 | cmdstr = parse_cmd_str(sed_cmd, cmdstr); |
597 | 570 | ||
598 | /* Add the command to the command array */ | 571 | /* Add the command to the command array */ |
@@ -828,12 +801,14 @@ static void process_file(FILE * file) | |||
828 | if (pattern_space == NULL) { | 801 | if (pattern_space == NULL) { |
829 | return; | 802 | return; |
830 | } | 803 | } |
831 | 804 | ||
832 | /* go through every line in the file */ | 805 | /* go through every line in the file */ |
833 | do { | 806 | do { |
834 | char *next_line; | 807 | char *next_line; |
835 | sed_cmd_t *sed_cmd; | 808 | sed_cmd_t *sed_cmd; |
836 | int substituted = 0; | 809 | int substituted = 0; |
810 | /* This enables whole blocks of commands to be mask'ed out if the lead address doesnt match */ | ||
811 | int block_mask = 1; | ||
837 | 812 | ||
838 | /* Read one line in advance so we can act on the last line, the '$' address */ | 813 | /* Read one line in advance so we can act on the last line, the '$' address */ |
839 | next_line = bb_get_chomped_line_from_file(file); | 814 | next_line = bb_get_chomped_line_from_file(file); |
@@ -855,7 +830,7 @@ static void process_file(FILE * file) | |||
855 | && sed_cmd->beg_match == NULL | 830 | && sed_cmd->beg_match == NULL |
856 | && sed_cmd->end_match == NULL) || | 831 | && sed_cmd->end_match == NULL) || |
857 | /* this line number is the first address we're looking for */ | 832 | /* this line number is the first address we're looking for */ |
858 | (sed_cmd->beg_line && (sed_cmd->beg_line == linenum)) || | 833 | (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum)) || |
859 | /* this line matches our first address regex */ | 834 | /* this line matches our first address regex */ |
860 | (sed_cmd->beg_match | 835 | (sed_cmd->beg_match |
861 | && (regexec(sed_cmd->beg_match, pattern_space, 0, NULL, | 836 | && (regexec(sed_cmd->beg_match, pattern_space, 0, NULL, |
@@ -865,7 +840,12 @@ static void process_file(FILE * file) | |||
865 | && (next_line == NULL)) | 840 | && (next_line == NULL)) |
866 | ); | 841 | ); |
867 | 842 | ||
868 | if (sed_cmd->invert ^ matched) { | 843 | if (sed_cmd->cmd == '{') { |
844 | block_mask = block_mask & matched; | ||
845 | } | ||
846 | // matched &= block_mask; | ||
847 | |||
848 | if (sed_cmd->invert ^ (matched & block_mask)) { | ||
869 | /* Update last used regex incase a blank substitute BRE is found */ | 849 | /* Update last used regex incase a blank substitute BRE is found */ |
870 | if (sed_cmd->beg_match) { | 850 | if (sed_cmd->beg_match) { |
871 | previous_regex_ptr = sed_cmd->beg_match; | 851 | previous_regex_ptr = sed_cmd->beg_match; |
@@ -1060,11 +1040,10 @@ static void process_file(FILE * file) | |||
1060 | break; | 1040 | break; |
1061 | case 'x':{ | 1041 | case 'x':{ |
1062 | /* Swap hold and pattern space */ | 1042 | /* Swap hold and pattern space */ |
1063 | char *tmp; | 1043 | char *tmp = pattern_space; |
1064 | |||
1065 | tmp = pattern_space; | ||
1066 | pattern_space = hold_space; | 1044 | pattern_space = hold_space; |
1067 | hold_space = tmp; | 1045 | hold_space = tmp; |
1046 | break; | ||
1068 | } | 1047 | } |
1069 | } | 1048 | } |
1070 | } | 1049 | } |
@@ -1081,7 +1060,7 @@ static void process_file(FILE * file) | |||
1081 | * isn't the first time through) and.. */ | 1060 | * isn't the first time through) and.. */ |
1082 | || ((still_in_range == 1) | 1061 | || ((still_in_range == 1) |
1083 | /* this line number is the last address we're looking for or... */ | 1062 | /* this line number is the last address we're looking for or... */ |
1084 | && ((sed_cmd->end_line | 1063 | && ((sed_cmd->end_line > 0 |
1085 | && (sed_cmd->end_line == linenum)) | 1064 | && (sed_cmd->end_line == linenum)) |
1086 | /* this line matches our last address regex */ | 1065 | /* this line matches our last address regex */ |
1087 | || (sed_cmd->end_match | 1066 | || (sed_cmd->end_match |
@@ -1095,6 +1074,10 @@ static void process_file(FILE * file) | |||
1095 | } | 1074 | } |
1096 | } | 1075 | } |
1097 | 1076 | ||
1077 | if (sed_cmd->cmd == '}') { | ||
1078 | block_mask = 1; | ||
1079 | } | ||
1080 | |||
1098 | if (deleted) | 1081 | if (deleted) |
1099 | break; | 1082 | break; |
1100 | } | 1083 | } |