diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-05-18 14:28:40 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-05-18 14:28:40 +0000 |
commit | b6c4855f1db16af926a0616cf91e0f65b0e2a3c6 (patch) | |
tree | e12e90f661576ae93f54a02b47f7e538c3b10927 | |
parent | 29eb3599e4014c225365f2c5539cf8a3ef46136e (diff) | |
download | busybox-w32-b6c4855f1db16af926a0616cf91e0f65b0e2a3c6.tar.gz busybox-w32-b6c4855f1db16af926a0616cf91e0f65b0e2a3c6.tar.bz2 busybox-w32-b6c4855f1db16af926a0616cf91e0f65b0e2a3c6.zip |
printf: fix printf -%s- foo, printf -- -%s- foo (bug 3354)
function old new delta
printf_main 577 548 -29
-rw-r--r-- | coreutils/printf.c | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/coreutils/printf.c b/coreutils/printf.c index a9ef61f68..a12f7cae7 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c | |||
@@ -185,13 +185,10 @@ static void print_direc(char *start, size_t length, int field_width, int precisi | |||
185 | free(p); | 185 | free(p); |
186 | } | 186 | } |
187 | 187 | ||
188 | /* Print the text in FORMAT, using ARGV (with ARGC elements) for | 188 | /* Print the text in FORMAT, using ARGV for arguments to any '%' directives. |
189 | arguments to any '%' directives. | 189 | Return advanced ARGV. */ |
190 | Return the number of elements of ARGV used. */ | 190 | static char **print_formatted(char *format, char **argv) |
191 | |||
192 | static int print_formatted(char *format, int argc, char **argv) | ||
193 | { | 191 | { |
194 | int save_argc = argc; /* Preserve original value. */ | ||
195 | char *f; /* Pointer into 'format'. */ | 192 | char *f; /* Pointer into 'format'. */ |
196 | char *direc_start; /* Start of % directive. */ | 193 | char *direc_start; /* Start of % directive. */ |
197 | size_t direc_length; /* Length of % directive. */ | 194 | size_t direc_length; /* Length of % directive. */ |
@@ -209,10 +206,9 @@ static int print_formatted(char *format, int argc, char **argv) | |||
209 | break; | 206 | break; |
210 | } | 207 | } |
211 | if (*f == 'b') { | 208 | if (*f == 'b') { |
212 | if (argc > 0) { | 209 | if (*argv) { |
213 | print_esc_string(*argv); | 210 | print_esc_string(*argv); |
214 | ++argv; | 211 | ++argv; |
215 | --argc; | ||
216 | } | 212 | } |
217 | break; | 213 | break; |
218 | } | 214 | } |
@@ -223,10 +219,9 @@ static int print_formatted(char *format, int argc, char **argv) | |||
223 | if (*f == '*') { | 219 | if (*f == '*') { |
224 | ++f; | 220 | ++f; |
225 | ++direc_length; | 221 | ++direc_length; |
226 | if (argc > 0) { | 222 | if (*argv) { |
227 | field_width = my_xstrtoul(*argv); | 223 | field_width = my_xstrtoul(*argv); |
228 | ++argv; | 224 | ++argv; |
229 | --argc; | ||
230 | } else | 225 | } else |
231 | field_width = 0; | 226 | field_width = 0; |
232 | } else { | 227 | } else { |
@@ -241,10 +236,9 @@ static int print_formatted(char *format, int argc, char **argv) | |||
241 | if (*f == '*') { | 236 | if (*f == '*') { |
242 | ++f; | 237 | ++f; |
243 | ++direc_length; | 238 | ++direc_length; |
244 | if (argc > 0) { | 239 | if (*argv) { |
245 | precision = my_xstrtoul(*argv); | 240 | precision = my_xstrtoul(*argv); |
246 | ++argv; | 241 | ++argv; |
247 | --argc; | ||
248 | } else | 242 | } else |
249 | precision = 0; | 243 | precision = 0; |
250 | } else | 244 | } else |
@@ -262,11 +256,10 @@ static int print_formatted(char *format, int argc, char **argv) | |||
262 | fprintf(stderr, "%%%c: invalid directive", *f); | 256 | fprintf(stderr, "%%%c: invalid directive", *f); |
263 | */ | 257 | */ |
264 | ++direc_length; | 258 | ++direc_length; |
265 | if (argc > 0) { | 259 | if (*argv) { |
266 | print_direc(direc_start, direc_length, field_width, | 260 | print_direc(direc_start, direc_length, field_width, |
267 | precision, *argv); | 261 | precision, *argv); |
268 | ++argv; | 262 | ++argv; |
269 | --argc; | ||
270 | } else | 263 | } else |
271 | print_direc(direc_start, direc_length, field_width, | 264 | print_direc(direc_start, direc_length, field_width, |
272 | precision, ""); | 265 | precision, ""); |
@@ -282,32 +275,35 @@ static int print_formatted(char *format, int argc, char **argv) | |||
282 | } | 275 | } |
283 | } | 276 | } |
284 | 277 | ||
285 | return save_argc - argc; | 278 | return argv; |
286 | } | 279 | } |
287 | 280 | ||
288 | int printf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 281 | int printf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
289 | int printf_main(int argc, char **argv) | 282 | int printf_main(int argc ATTRIBUTE_UNUSED, char **argv) |
290 | { | 283 | { |
291 | char *format; | 284 | char *format; |
292 | int args_used; | 285 | char **argv2; |
293 | 286 | ||
294 | if (argc <= 1 || argv[1][0] == '-') { | 287 | /* bash builtin errors out on "printf '-%s-\n' foo", |
288 | * coreutils-6.9 works. Both work with "printf -- '-%s-\n' foo". | ||
289 | * We will mimic coreutils. */ | ||
290 | if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && argv[1][2] == '\0') | ||
291 | argv++; | ||
292 | if (!argv[1]) | ||
295 | bb_show_usage(); | 293 | bb_show_usage(); |
296 | } | ||
297 | 294 | ||
298 | format = argv[1]; | 295 | format = argv[1]; |
299 | argc -= 2; | 296 | argv2 = argv + 2; |
300 | argv += 2; | ||
301 | 297 | ||
302 | do { | 298 | do { |
303 | args_used = print_formatted(format, argc, argv); | 299 | argv = argv2; |
304 | argc -= args_used; | 300 | argv2 = print_formatted(format, argv); |
305 | argv += args_used; | 301 | } while (argv2 != argv && *argv2); |
306 | } while (args_used > 0 && argc > 0); | ||
307 | 302 | ||
308 | /* if (argc > 0) | 303 | /* coreutils compat (bash doesn't do this): |
304 | if (*argv) | ||
309 | fprintf(stderr, "excess args ignored"); | 305 | fprintf(stderr, "excess args ignored"); |
310 | */ | 306 | */ |
311 | 307 | ||
312 | return EXIT_SUCCESS; | 308 | return EXIT_SUCCESS; |
313 | } | 309 | } |