summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-05-18 14:28:40 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-05-18 14:28:40 +0000
commitb6c4855f1db16af926a0616cf91e0f65b0e2a3c6 (patch)
treee12e90f661576ae93f54a02b47f7e538c3b10927
parent29eb3599e4014c225365f2c5539cf8a3ef46136e (diff)
downloadbusybox-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.c52
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. */ 190static char **print_formatted(char *format, char **argv)
191
192static 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
288int printf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 281int printf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
289int printf_main(int argc, char **argv) 282int 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}