summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/printf.c24
-rwxr-xr-xtestsuite/printf.tests3
2 files changed, 12 insertions, 15 deletions
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 2beea71..5b326c6 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -53,10 +53,7 @@
* (but negative numbers are not "bad").
* Both accept negative numbers for %u specifier.
*
- * We try to be compatible. We are not compatible here:
- * - we do not accept -NUM for %u
- * - exit code is 0 even if "invalid number" was seen (FIXME)
- * See "if (errno)" checks in the code below.
+ * We try to be compatible.
*/
typedef void FAST_FUNC (*converter)(const char *arg, void *result);
@@ -163,7 +160,6 @@ static void print_direc(char *format, unsigned fmt_length,
case 'i':
llv = my_xstrtoll(argument);
print_long:
- /* if (errno) return; - see comment at the top */
if (!have_width) {
if (!have_prec)
printf(format, llv);
@@ -210,7 +206,6 @@ static void print_direc(char *format, unsigned fmt_length,
case 'g':
case 'G':
dv = my_xstrtod(argument);
- /* if (errno) return; */
if (!have_width) {
if (!have_prec)
printf(format, dv);
@@ -241,7 +236,7 @@ static int get_width_prec(const char *str)
/* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
Return advanced ARGV. */
-static char **print_formatted(char *f, char **argv)
+static char **print_formatted(char *f, char **argv, int *conv_err)
{
char *direc_start; /* Start of % directive. */
unsigned direc_length; /* Length of % directive. */
@@ -299,8 +294,8 @@ static char **print_formatted(char *f, char **argv)
/* Remove "lLhz" size modifiers, repeatedly.
* bash does not like "%lld", but coreutils
- * would happily take even "%Llllhhzhhzd"!
- * We will be permissive like coreutils */
+ * happily takes even "%Llllhhzhhzd"!
+ * We are permissive like coreutils */
while ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
overlapping_strcpy(f, f + 1);
}
@@ -330,12 +325,12 @@ static char **print_formatted(char *f, char **argv)
}
if (*argv) {
print_direc(direc_start, direc_length, field_width,
- precision, *argv);
- ++argv;
+ precision, *argv++);
} else {
print_direc(direc_start, direc_length, field_width,
precision, "");
}
+ *conv_err |= errno;
free(p);
}
break;
@@ -356,6 +351,7 @@ static char **print_formatted(char *f, char **argv)
int printf_main(int argc UNUSED_PARAM, char **argv)
{
+ int conv_err;
char *format;
char **argv2;
@@ -392,9 +388,10 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
format = argv[1];
argv2 = argv + 2;
+ conv_err = 0;
do {
argv = argv2;
- argv2 = print_formatted(format, argv);
+ argv2 = print_formatted(format, argv, &conv_err);
} while (argv2 > argv && *argv2);
/* coreutils compat (bash doesn't do this):
@@ -402,5 +399,6 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
fprintf(stderr, "excess args ignored");
*/
- return (argv2 < argv); /* if true, print_formatted errored out */
+ return (argv2 < argv) /* if true, print_formatted errored out */
+ || conv_err; /* print_formatted saw invalid number */
}
diff --git a/testsuite/printf.tests b/testsuite/printf.tests
index 558ecb1..0a63f0f 100755
--- a/testsuite/printf.tests
+++ b/testsuite/printf.tests
@@ -87,13 +87,12 @@ testing "printf understands %Ld" \
# "1\n""printf: -2: invalid number\n""0\n""3\n""0\n" \
# "" ""
-# Actually, we are wrong here: exit code should be 1
testing "printf handles %d bad_input" \
"${bb}printf '%d\n' 1 - 2 bad 3 123bad 4 2>&1; echo \$?" \
"1\n""printf: -: invalid number\n""0\n"\
"2\n""printf: bad: invalid number\n""0\n"\
"3\n""printf: 123bad: invalid number\n""0\n"\
-"4\n""0\n" \
+"4\n""1\n" \
"" ""
testing "printf aborts on bare %" \