* gettext-tools/src/format-invalid.h (INVALID_FLAG_FOR): New macro.
* gettext-tools/src/format-java-printf.c (INVALID_FLAG_FOR): Remove macro.
* gettext-tools/src/format-sh-printf.c (format_parse): Reject format strings
with invalid flag+specifier combinations.
* gettext-tools/tests/format-sh-printf-1: Add more test cases.
* gettext-tools/doc/gettext.texi (sh-format): Mention the ' flag.
Extensions by the GNU coreutils @samp{printf} command
(@url{https://www.gnu.org/software/coreutils/manual/html_node/printf-invocation.html})
are not supported:
+use of the @samp{'} flag in the
+@code{%i}, @code{%d}, @code{%u}, @code{%f}, @code{%F}, @code{%g}, @code{%G}
+directives;
use of @samp{*} or @samp{*@var{m}$} as width or precision;
use of size specifiers @code{h}, @code{l}, @code{j}, @code{z}, @code{t} (ignored);
and the escape sequences @code{\c},
? xasprintf (_("In the directive number %u, the character '%c' is not a valid conversion specifier."), directive_number, conv_char) \
: xasprintf (_("The character that terminates the directive number %u is not a valid conversion specifier."), directive_number))
+#define INVALID_FLAG_FOR(directive_number,flag_char,conv_char) \
+ xasprintf (_("In the directive number %u, the flag '%c' is invalid for the conversion '%c'."), directive_number, flag_char, conv_char)
+
#define INVALID_INCOMPATIBLE_ARG_TYPES(arg_number) \
xasprintf (_("The string refers to argument number %u in incompatible ways."), arg_number)
#define INVALID_LAST_ARG(directive_number) \
xasprintf (_("In the directive number %u, the reference to the argument of the previous directive is invalid."), directive_number)
-#define INVALID_FLAG_FOR(directive_number,flag_char,conv_char) \
- xasprintf (_("In the directive number %u, the flag '%c' is invalid for the conversion '%c'."), directive_number, flag_char, conv_char)
-
#define INVALID_WIDTH_FOR(directive_number,conv_char) \
xasprintf (_("In the directive number %u, a width is invalid for the conversion '%c'."), directive_number, conv_char)
- 'u', 'o', 'x', 'X', that need an unsigned integer argument,
- [optional in POSIX, but supported here:] 'e', 'E', 'f', 'F', 'g', 'G',
'a', 'A', that need a floating-point argument.
+ Some flag+specifier combinations are invalid:
+ - The '#' flag with the specifiers 'c', 's', 'i', 'd', 'u'.
+ - The '0' flag with the specifiers 'c', 's'.
Additionally there is the directive '%%', which takes no argument.
Numbered ('%m$' or '*m$') and unnumbered argument specifications cannot
be used in the same string.
}
/* Parse flags. */
+ bool have_hash_flag = false;
+ bool have_zero_flag = false;
while (*format == ' ' || *format == '+' || *format == '-'
|| *format == '#' || *format == '0')
{
if (*format == ' ')
likely_intentional = false;
+ if (*format == '#')
+ have_hash_flag = true;
+ if (*format == '0')
+ have_zero_flag = true;
format++;
}
goto bad_format;
}
+ if (have_hash_flag
+ && (*format == 'c' || *format == 's'
+ || *format == 'i' || *format == 'd' || *format == 'u'))
+ {
+ *invalid_reason =
+ INVALID_FLAG_FOR (spec.directives, '#', *format);
+ FDI_SET (format, FMTDIR_ERROR);
+ goto bad_format;
+ }
+ if (have_zero_flag && (*format == 'c' || *format == 's'))
+ {
+ *invalid_reason =
+ INVALID_FLAG_FOR (spec.directives, '0', *format);
+ FDI_SET (format, FMTDIR_ERROR);
+ goto bad_format;
+ }
+
if (number)
{
/* Numbered argument. */
"abc%3$*2$.*1$g"
# Invalid: zero
"abc%2$*0$.*1$g"
+# Invalid: flag not valid
+"abc%'d"
+# Invalid: flag not valid
+"abc%'u"
+# Invalid: flag not valid
+"abc%'f"
+# Invalid: flag not valid
+"abc%'g"
+# Invalid: flag not valid for specifier
+"abc%#c"
+# Invalid: flag not valid for specifier
+"abc%#s"
+# Invalid: flag not valid for specifier
+"abc%#i"
+# Invalid: flag not valid for specifier
+"abc%#d"
+# Invalid: flag not valid for specifier
+"abc%#u"
+# Invalid: flag not valid for specifier
+"abc%0c"
+# Invalid: flag not valid for specifier
+"abc%0s"
# Valid: escape sequence
"abc%%def\\"
# Valid: escape sequence