-//FIXME: actually, the same happens with bare "%d":
-//it printfs an int, but we pass long!
-//What saves us is that on most arches stack slot
-//is pointer-sized -> long-sized -> ints are promoted to longs
-// for variadic functions -> printf("%d", int_v) is in reality
-// indistinqushable from printf("%d", long_v) ->
-// since printf("%d", int_v) works, printf("%d", long_v) has to work.
-//But "clean" solution would be to add "l" to d,i,o,x,X.
-//Probably makes sense to go all the way to "ll" then.
-//Coreutils support long long-sized arguments.
-
- /* needed - try "printf %" without it */
- if (!strchr("diouxXfeEgGcs", *f)) {
- bb_error_msg("%s: invalid format", direc_start);
- /* causes main() to exit with error */
- return saved_argv - 1;
- }
- ++direc_length;
- if (*argv) {
- print_direc(direc_start, direc_length, field_width,
- precision, *argv);
- ++argv;
- } else {
- print_direc(direc_start, direc_length, field_width,
- precision, "");
+ /* Add "ll" if integer modifier, then print */
+ {
+ static const char format_chars[] ALIGN1 = "diouxXfeEgGcs";
+ char *p = strchr(format_chars, *f);
+ /* needed - try "printf %" without it */
+ if (p == NULL) {
+ bb_error_msg("%s: invalid format", direc_start);
+ /* causes main() to exit with error */
+ return saved_argv - 1;
+ }
+ ++direc_length;
+ if (p - format_chars <= 5) {
+ /* it is one of "diouxX" */
+ p = xmalloc(direc_length + 3);
+ memcpy(p, direc_start, direc_length);
+ p[direc_length + 1] = p[direc_length - 1];
+ p[direc_length - 1] = 'l';
+ p[direc_length] = 'l';
+ //bb_error_msg("<%s>", p);
+ direc_length += 2;
+ direc_start = p;
+ } else {
+ p = NULL;
+ }
+ if (*argv) {
+ print_direc(direc_start, direc_length, field_width,
+ precision, *argv++);
+ } else {
+ print_direc(direc_start, direc_length, field_width,
+ precision, "");
+ }
+ *conv_err |= errno;
+ free(p);