aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2003-04-12 16:10:42 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2003-04-12 16:10:42 +0000
commitfc4cb4dbb5e208139d3b7f81d00694212524ab5d (patch)
tree712e5083ae830063fdb26e10d4f30fbc1364f6fe
parentd4185b0e1589d1d4e847f25a730424bb75f0a744 (diff)
downloadbusybox-w32-fc4cb4dbb5e208139d3b7f81d00694212524ab5d.tar.gz
busybox-w32-fc4cb4dbb5e208139d3b7f81d00694212524ab5d.tar.bz2
busybox-w32-fc4cb4dbb5e208139d3b7f81d00694212524ab5d.zip
Fix logic error in grouped commands
-rw-r--r--editors/sed.c67
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 */
125static sed_cmd_t sed_cmd_head; 126static sed_cmd_t sed_cmd_head;
126static sed_cmd_t *sed_cmd_tail = &sed_cmd_head; 127static sed_cmd_t *sed_cmd_tail = &sed_cmd_head;
127static sed_cmd_t *block_cmd;
128 128
129static int in_block = 0;
130const char *const semicolon_whitespace = "; \n\r\t\v\0"; 129const char *const semicolon_whitespace = "; \n\r\t\v\0";
131static regex_t *previous_regex_ptr = NULL; 130static 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 }