printf: fix printf -%s- foo, printf -- -%s- foo (bug 3354)

function                                             old     new   delta
printf_main                                          577     548     -29
This commit is contained in:
Denis Vlasenko 2008-05-18 14:28:40 +00:00
parent 29eb3599e4
commit b6c4855f1d

View File

@ -185,13 +185,10 @@ static void print_direc(char *start, size_t length, int field_width, int precisi
free(p); free(p);
} }
/* Print the text in FORMAT, using ARGV (with ARGC elements) for /* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
arguments to any '%' directives. Return advanced ARGV. */
Return the number of elements of ARGV used. */ static char **print_formatted(char *format, char **argv)
static int print_formatted(char *format, int argc, char **argv)
{ {
int save_argc = argc; /* Preserve original value. */
char *f; /* Pointer into 'format'. */ char *f; /* Pointer into 'format'. */
char *direc_start; /* Start of % directive. */ char *direc_start; /* Start of % directive. */
size_t direc_length; /* Length of % directive. */ size_t direc_length; /* Length of % directive. */
@ -209,10 +206,9 @@ static int print_formatted(char *format, int argc, char **argv)
break; break;
} }
if (*f == 'b') { if (*f == 'b') {
if (argc > 0) { if (*argv) {
print_esc_string(*argv); print_esc_string(*argv);
++argv; ++argv;
--argc;
} }
break; break;
} }
@ -223,10 +219,9 @@ static int print_formatted(char *format, int argc, char **argv)
if (*f == '*') { if (*f == '*') {
++f; ++f;
++direc_length; ++direc_length;
if (argc > 0) { if (*argv) {
field_width = my_xstrtoul(*argv); field_width = my_xstrtoul(*argv);
++argv; ++argv;
--argc;
} else } else
field_width = 0; field_width = 0;
} else { } else {
@ -241,10 +236,9 @@ static int print_formatted(char *format, int argc, char **argv)
if (*f == '*') { if (*f == '*') {
++f; ++f;
++direc_length; ++direc_length;
if (argc > 0) { if (*argv) {
precision = my_xstrtoul(*argv); precision = my_xstrtoul(*argv);
++argv; ++argv;
--argc;
} else } else
precision = 0; precision = 0;
} else } else
@ -262,11 +256,10 @@ static int print_formatted(char *format, int argc, char **argv)
fprintf(stderr, "%%%c: invalid directive", *f); fprintf(stderr, "%%%c: invalid directive", *f);
*/ */
++direc_length; ++direc_length;
if (argc > 0) { if (*argv) {
print_direc(direc_start, direc_length, field_width, print_direc(direc_start, direc_length, field_width,
precision, *argv); precision, *argv);
++argv; ++argv;
--argc;
} else } else
print_direc(direc_start, direc_length, field_width, print_direc(direc_start, direc_length, field_width,
precision, ""); precision, "");
@ -282,30 +275,33 @@ static int print_formatted(char *format, int argc, char **argv)
} }
} }
return save_argc - argc; return argv;
} }
int printf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int printf_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int printf_main(int argc, char **argv) int printf_main(int argc ATTRIBUTE_UNUSED, char **argv)
{ {
char *format; char *format;
int args_used; char **argv2;
if (argc <= 1 || argv[1][0] == '-') { /* bash builtin errors out on "printf '-%s-\n' foo",
* coreutils-6.9 works. Both work with "printf -- '-%s-\n' foo".
* We will mimic coreutils. */
if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && argv[1][2] == '\0')
argv++;
if (!argv[1])
bb_show_usage(); bb_show_usage();
}
format = argv[1]; format = argv[1];
argc -= 2; argv2 = argv + 2;
argv += 2;
do { do {
args_used = print_formatted(format, argc, argv); argv = argv2;
argc -= args_used; argv2 = print_formatted(format, argv);
argv += args_used; } while (argv2 != argv && *argv2);
} while (args_used > 0 && argc > 0);
/* if (argc > 0) /* coreutils compat (bash doesn't do this):
if (*argv)
fprintf(stderr, "excess args ignored"); fprintf(stderr, "excess args ignored");
*/ */