Magellan Linux

Contents of /trunk/busybox/patches/busybox-1.19.0-sed.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1519 - (show annotations) (download)
Mon Sep 5 21:52:12 2011 UTC (12 years, 8 months ago) by niro
File size: 8081 byte(s)
-added upstream patches
1 --- busybox-1.19.0/editors/sed.c
2 +++ busybox-1.19.0-sed/editors/sed.c
3 @@ -75,6 +75,13 @@
4 #include "libbb.h"
5 #include "xregex.h"
6
7 +#if 0
8 +# define dbg(...) bb_error_msg(__VA_ARGS__)
9 +#else
10 +# define dbg(...) ((void)0)
11 +#endif
12 +
13 +
14 enum {
15 OPT_in_place = 1 << 0,
16 };
17 @@ -89,6 +96,7 @@ typedef struct sed_cmd_s {
18 regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */
19 regex_t *sub_match; /* For 's/sub_match/string/' */
20 int beg_line; /* 'sed 1p' 0 == apply commands to all lines */
21 + int beg_line_orig; /* copy of the above, needed for -i */
22 int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($) */
23
24 FILE *sw_file; /* File (sw) command writes to, -1 for none. */
25 @@ -123,7 +131,7 @@ struct globals {
26 regex_t *previous_regex_ptr;
27
28 /* linked list of sed commands */
29 - sed_cmd_t sed_cmd_head, *sed_cmd_tail;
30 + sed_cmd_t *sed_cmd_head, **sed_cmd_tail;
31
32 /* Linked list of append lines */
33 llist_t *append_head;
34 @@ -148,7 +156,7 @@ struct BUG_G_too_big {
35 #if ENABLE_FEATURE_CLEAN_UP
36 static void sed_free_and_close_stuff(void)
37 {
38 - sed_cmd_t *sed_cmd = G.sed_cmd_head.next;
39 + sed_cmd_t *sed_cmd = G.sed_cmd_head;
40
41 llist_free(G.append_head, free);
42
43 @@ -599,6 +607,7 @@ static void add_cmd(const char *cmdstr)
44
45 /* first part (if present) is an address: either a '$', a number or a /regex/ */
46 cmdstr += get_address(cmdstr, &sed_cmd->beg_line, &sed_cmd->beg_match);
47 + sed_cmd->beg_line_orig = sed_cmd->beg_line;
48
49 /* second part (if present) will begin with a comma */
50 if (*cmdstr == ',') {
51 @@ -630,8 +639,8 @@ static void add_cmd(const char *cmdstr)
52 cmdstr = parse_cmd_args(sed_cmd, cmdstr);
53
54 /* Add the command to the command array */
55 - G.sed_cmd_tail->next = sed_cmd;
56 - G.sed_cmd_tail = G.sed_cmd_tail->next;
57 + *G.sed_cmd_tail = sed_cmd;
58 + G.sed_cmd_tail = &sed_cmd->next;
59 }
60
61 /* If we glued multiple lines together, free the memory. */
62 @@ -777,7 +786,7 @@ static sed_cmd_t *branch_to(char *label)
63 {
64 sed_cmd_t *sed_cmd;
65
66 - for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) {
67 + for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
68 if (sed_cmd->cmd == ':' && sed_cmd->string && !strcmp(sed_cmd->string, label)) {
69 return sed_cmd;
70 }
71 @@ -953,24 +962,24 @@ static void process_files(void)
72
73 /* For every line, go through all the commands */
74 restart:
75 - for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) {
76 + for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
77 int old_matched, matched;
78
79 old_matched = sed_cmd->in_match;
80
81 /* Determine if this command matches this line: */
82
83 - //bb_error_msg("match1:%d", sed_cmd->in_match);
84 - //bb_error_msg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line
85 - // && !sed_cmd->beg_match && !sed_cmd->end_match));
86 - //bb_error_msg("match3:%d", (sed_cmd->beg_line > 0
87 - // && (sed_cmd->end_line || sed_cmd->end_match
88 - // ? (sed_cmd->beg_line <= linenum)
89 - // : (sed_cmd->beg_line == linenum)
90 - // )
91 - // )
92 - //bb_error_msg("match4:%d", (beg_match(sed_cmd, pattern_space)));
93 - //bb_error_msg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL));
94 + dbg("match1:%d", sed_cmd->in_match);
95 + dbg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line
96 + && !sed_cmd->beg_match && !sed_cmd->end_match));
97 + dbg("match3:%d", (sed_cmd->beg_line > 0
98 + && (sed_cmd->end_line || sed_cmd->end_match
99 + ? (sed_cmd->beg_line <= linenum)
100 + : (sed_cmd->beg_line == linenum)
101 + )
102 + ));
103 + dbg("match4:%d", (beg_match(sed_cmd, pattern_space)));
104 + dbg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL));
105
106 /* Are we continuing a previous multi-line match? */
107 sed_cmd->in_match = sed_cmd->in_match
108 @@ -981,7 +990,14 @@ static void process_files(void)
109 || (sed_cmd->beg_line > 0
110 && (sed_cmd->end_line || sed_cmd->end_match
111 /* note: even if end is numeric and is < linenum too,
112 - * GNU sed matches! We match too */
113 + * GNU sed matches! We match too, therefore we don't
114 + * check here that linenum <= end.
115 + * Example:
116 + * printf '1\n2\n3\n4\n' | sed -n '1{N;N;d};1p;2,3p;3p;4p'
117 + * first three input lines are deleted;
118 + * 4th line is matched and printed
119 + * by "2,3" (!) and by "4" ranges
120 + */
121 ? (sed_cmd->beg_line <= linenum) /* N,end */
122 : (sed_cmd->beg_line == linenum) /* N */
123 )
124 @@ -994,16 +1010,14 @@ static void process_files(void)
125 /* Snapshot the value */
126 matched = sed_cmd->in_match;
127
128 - //bb_error_msg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d",
129 - //sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum);
130 + dbg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d",
131 + sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum);
132
133 /* Is this line the end of the current match? */
134
135 if (matched) {
136 /* once matched, "n,xxx" range is dead, disabling it */
137 - if (sed_cmd->beg_line > 0
138 - && !(option_mask32 & OPT_in_place) /* but not for -i */
139 - ) {
140 + if (sed_cmd->beg_line > 0) {
141 sed_cmd->beg_line = -2;
142 }
143 sed_cmd->in_match = !(
144 @@ -1017,7 +1031,8 @@ static void process_files(void)
145 /* or does this line matches our last address regex */
146 || (sed_cmd->end_match && old_matched
147 && (regexec(sed_cmd->end_match,
148 - pattern_space, 0, NULL, 0) == 0))
149 + pattern_space, 0, NULL, 0) == 0)
150 + )
151 );
152 }
153
154 @@ -1407,11 +1422,12 @@ int sed_main(int argc UNUSED_PARAM, char
155 add_input_file(stdin);
156 } else {
157 int i;
158 - FILE *file;
159
160 for (i = 0; argv[i]; i++) {
161 struct stat statbuf;
162 int nonstdoutfd;
163 + FILE *file;
164 + sed_cmd_t *sed_cmd;
165
166 if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) {
167 add_input_file(stdin);
168 @@ -1423,11 +1439,13 @@ int sed_main(int argc UNUSED_PARAM, char
169 status = EXIT_FAILURE;
170 continue;
171 }
172 + add_input_file(file);
173 if (!(opt & OPT_in_place)) {
174 - add_input_file(file);
175 continue;
176 }
177
178 + /* -i: process each FILE separately: */
179 +
180 G.outname = xasprintf("%sXXXXXX", argv[i]);
181 nonstdoutfd = xmkstemp(G.outname);
182 G.nonstdout = xfdopen_for_write(nonstdoutfd);
183 @@ -1438,15 +1456,20 @@ int sed_main(int argc UNUSED_PARAM, char
184 * but GNU sed 4.2.1 does not preserve them either */
185 fchmod(nonstdoutfd, statbuf.st_mode);
186 fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid);
187 - add_input_file(file);
188 +
189 process_files();
190 fclose(G.nonstdout);
191 -
192 G.nonstdout = stdout;
193 +
194 /* unlink(argv[i]); */
195 xrename(G.outname, argv[i]);
196 free(G.outname);
197 G.outname = NULL;
198 +
199 + /* Re-enable disabled range matches */
200 + for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
201 + sed_cmd->beg_line = sed_cmd->beg_line_orig;
202 + }
203 }
204 /* Here, to handle "sed 'cmds' nonexistent_file" case we did:
205 * if (G.current_input_file >= G.input_file_count)
206 --- busybox-1.19.0/testsuite/sed.tests
207 +++ busybox-1.19.0-sed/testsuite/sed.tests
208 @@ -6,7 +6,7 @@
209
210 . ./testing.sh
211
212 -# testing "description" "arguments" "result" "infile" "stdin"
213 +# testing "description" "commands" "result" "infile" "stdin"
214
215 # Corner cases
216 testing "sed no files (stdin)" 'sed ""' "hello\n" "" "hello\n"
217 @@ -225,7 +225,7 @@ testing "sed s/xxx/[/" "sed -e 's/xxx/[/
218 #testing "sed -g (exhaustive)" "sed -e 's/[[:space:]]*/,/g'" ",1,2,3,4,5," \
219 # "" "12345"
220
221 -# testing "description" "arguments" "result" "infile" "stdin"
222 +# testing "description" "commands" "result" "infile" "stdin"
223
224 testing "sed n command must reset 'substituted' bit" \
225 "sed 's/1/x/;T;n;: next;s/3/y/;t quit;n;b next;: quit;q'" \
226 @@ -291,6 +291,10 @@ testing "sed understands \r" \
227 "sed 's/r/\r/'" \
228 "\rrr\n" "" "rrr\n"
229
230 -# testing "description" "arguments" "result" "infile" "stdin"
231 +testing "sed -i finishes ranges correctly" \
232 + "sed '1,2d' -i input; echo \$?; cat input" \
233 + "0\n3\n4\n" "1\n2\n3\n4\n" ""
234 +
235 +# testing "description" "commands" "result" "infile" "stdin"
236
237 exit $FAILCOUNT