This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
printf 'I' flag patch
- To: gcc-patches at gcc dot gnu dot org
- Subject: printf 'I' flag patch
- From: "Joseph S. Myers" <jsm28 at cam dot ac dot uk>
- Date: Wed, 23 Aug 2000 01:56:05 +0100 (BST)
This patch adds support for glibc's 'I' printf flag (use locale's
digits for decimal integers), and adds some more tests.
Bootstrapped with no regressions on i686-pc-linux-gnu. With this
patch applied, the tests in it all pass. OK to commit?
gcc/ChangeLog:
2000-08-23 Joseph S. Myers <jsm28@cam.ac.uk>
* c-common.c (print_char_table): Allow 'I' flag with %d, %i and
%u.
(check_format_info): Support printf 'I' flag; warn about it with
-pedantic.
gcc/testsuite/ChangeLog:
2000-08-23 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/c99-printf-2.c, gcc.dg/format-xopen-1.c: Add some more
tests.
* gcc.dg/format-ext-1.c: New test.
--- c-common.c.orig Tue Aug 22 14:04:45 2000
+++ c-common.c Tue Aug 22 21:43:58 2000
@@ -1236,9 +1236,9 @@ typedef struct {
} format_char_info;
static format_char_info print_char_table[] = {
- { "di", 0, T_I, T_I, T_I, T_L, T_LL, T_LL, T_SST, T_PD, T_IM, "-wp0 +'" },
+ { "di", 0, T_I, T_I, T_I, T_L, T_LL, T_LL, T_SST, T_PD, T_IM, "-wp0 +'I" },
{ "oxX", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, T_UPD, T_UIM, "-wp0#" },
- { "u", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, T_UPD, T_UIM, "-wp0'" },
+ { "u", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, T_UPD, T_UIM, "-wp0'I" },
/* A GNU extension. */
{ "m", 0, T_V, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-wp" },
{ "fFgG", 0, T_D, NULL, NULL, T_D, NULL, T_LD, NULL, NULL, NULL, "-wp0 +#'" },
@@ -1916,7 +1916,7 @@ check_format_info (info, params)
has_operand_number = 0;
}
- while (*format_chars != 0 && index (" +#0-'", *format_chars) != 0)
+ while (*format_chars != 0 && index (" +#0-'I", *format_chars) != 0)
{
if (index (flag_chars, *format_chars) != 0)
warning ("repeated `%c' flag in format", *format_chars++);
@@ -1939,6 +1939,8 @@ check_format_info (info, params)
warning ("use of both `0' and `-' flags in format");
if (index (flag_chars, '\'') && pedantic)
warning ("ISO C does not support the `'' format flag");
+ if (index (flag_chars, 'I') && pedantic)
+ warning ("ISO C does not support the `I' format flag");
if (*format_chars == '*')
{
wide = TRUE;
--- c99-printf-2.c.orig Sun Aug 6 18:16:45 2000
+++ c99-printf-2.c Tue Aug 22 21:39:00 2000
@@ -31,4 +31,6 @@
*/
printf ("%'d", i); /* { dg-warning "C" "printf ' flag" } */
printf ("%1$d", i); /* { dg-warning "C" "printf $ format" } */
+ /* The flag character I is a GNU extension. */
+ printf ("%Id", i); /* { dg-warning "C" "printf I flag" } */
}
--- format-xopen-1.c.orig Mon Aug 21 17:53:50 2000
+++ format-xopen-1.c Tue Aug 22 21:39:54 2000
@@ -38,6 +38,7 @@
printf ("% C", lc); /* { dg-warning "flag" "bad % C" } */
printf ("%#C", lc); /* { dg-warning "flag" "bad %#C" } */
printf ("%0C", lc); /* { dg-warning "flag" "bad %0C" } */
+ printf ("%'C", lc); /* { dg-warning "flag" "bad %'C" } */
printf ("%S", ls);
printf ("%3S", ls);
printf ("%.3S", ls);
@@ -54,6 +55,7 @@
printf ("% S", ls); /* { dg-warning "flag" "bad % S" } */
printf ("%#S", ls); /* { dg-warning "flag" "bad %#S" } */
printf ("%0S", ls); /* { dg-warning "flag" "bad %0S" } */
+ printf ("%'S", ls); /* { dg-warning "flag" "bad %'S" } */
scanf ("%C", ls);
scanf ("%S", ls);
scanf ("%*C%*S");
--- /dev/null Fri Sep 11 11:31:59 1998
+++ format-ext-1.c Wed Aug 23 00:47:21 2000
@@ -0,0 +1,120 @@
+/* Test for format extensions beyond the C standard and X/Open standard.
+ Test for printf formats.
+*/
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wformat" } */
+
+/* %q formats want a "quad"; GCC considers this to be a long long. */
+typedef long long int quad_t;
+typedef unsigned long long int u_quad_t;
+
+typedef __WCHAR_TYPE__ wchar_t;
+typedef __WINT_TYPE__ wint_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern int printf (const char *, ...);
+
+void
+foo (quad_t q, u_quad_t uq, quad_t *qn, size_t z, size_t *zn, long long int ll,
+ unsigned long long int ull, int i, unsigned int u, double d,
+ char *s, void *p, wchar_t *ls, wint_t lc, int *n)
+{
+ /* As an extension, GCC allows the BSD length "q" for integer formats.
+ This is largely obsoleted in C99 by %j, %ll and PRId64.
+ */
+ printf ("%qd%qi%qo%qu%qx%qX%qn", q, q, uq, uq, uq, uq, qn);
+ printf ("%qf", d); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qF", d); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qe", d); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qE", d); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qg", d); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qG", d); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qa", d); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qA", d); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qc", i); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qs", s); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qp", p); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qC", lc); /* { dg-warning "length character" "bad use of %q" } */
+ printf ("%qS", ls); /* { dg-warning "length character" "bad use of %q" } */
+ /* With a bad length character GCC wants some argument, any argument,
+ to devour with the format conversion, as a synchronisation heuristic.
+ This may get improved later.
+ */
+ printf ("%qm", i); /* { dg-warning "length character" "bad use of %q" } */
+ /* As an extension, GCC allows the length "Z" as a synonym for "z".
+ This was an extension predating C99 which should now be considered
+ deprecated; use the standard "z" instead.
+ */
+ printf ("%Zd%Zi%Zo%Zu%Zx%ZX", z, z, z, z, z, z);
+ printf ("%Zn", zn);
+ printf ("%Zf", d); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%ZF", d); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%Ze", d); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%ZE", d); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%Zg", d); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%ZG", d); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%Za", d); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%ZA", d); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%Zc", i); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%Zs", s); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%Zp", p); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%ZC", lc); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%ZS", ls); /* { dg-warning "length character" "bad use of %Z" } */
+ printf ("%Zm", i); /* { dg-warning "length character" "bad use of %Z" } */
+ /* As an extension, GCC allows the length "L" on integer formats
+ (but not %n) as a synonym for "ll".
+ This should be considered deprecated.
+ */
+ printf ("%Ld%Li%Lo%Lu%Lx%LX", ll, ll, ull, ull, ull, ull);
+ /* As an extension, derived from syslog, GCC allows the conversion
+ specifier "m" for formatting strerror(errno). This may be used
+ with width, precision and the "-" flag, the same as %s.
+ */
+ printf ("%m%3m%.4m%5.6m");
+ printf ("%*m", i);
+ printf ("%.*m", i);
+ printf ("%*.*m", i, i);
+ printf ("%3.*m", i);
+ printf ("%*.4m", i);
+ printf ("%-m");
+ printf ("%+m"); /* { dg-warning "flag" "bad %+m" } */
+ printf ("% m"); /* { dg-warning "flag" "bad % m" } */
+ printf ("%#m"); /* { dg-warning "flag" "bad %#m" } */
+ printf ("%0m"); /* { dg-warning "flag" "bad %0m" } */
+ printf ("%'m"); /* { dg-warning "flag" "bad %'m" } */
+ printf ("%hm", i); /* { dg-warning "length character" "bad %hm" } */
+ printf ("%hhm", i); /* { dg-warning "length character" "bad %hhm" } */
+ printf ("%lm", i); /* { dg-warning "length character" "bad %lm" } */
+ printf ("%llm", i); /* { dg-warning "length character" "bad %llm" } */
+ printf ("%jm", i); /* { dg-warning "length character" "bad %jm" } */
+ printf ("%zm", i); /* { dg-warning "length character" "bad %zm" } */
+ printf ("%tm", i); /* { dg-warning "length character" "bad %tm" } */
+ printf ("%Lm", i); /* { dg-warning "length character" "bad %Lm" } */
+ printf ("%qm", i); /* { dg-warning "length character" "bad %qm" } */
+ printf ("%Zm", i); /* { dg-warning "length character" "bad %Zm" } */
+ /* As an extension, glibc includes the "I" flag for decimal integer
+ formats, to output using the locale's digits (e.g. in Arabic).
+ In GCC, we require this to be in the standard place for flags, though
+ glibc allows it also after width or precision.
+ */
+ printf ("%Id%Ii%Iu", i, i, u);
+ printf ("%Io", u); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%Ix", u); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%IX", u); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%In", n); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%If", d); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%IF", d); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%Ie", d); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%IE", d); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%Ig", d); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%IG", d); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%Ia", d); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%IA", d); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%Ic", i); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%Is", s); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%Ip", p); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%IC", lc); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%IS", ls); /* { dg-warning "flag" "bad use of I flag" } */
+ printf ("%Im"); /* { dg-warning "flag" "bad use of I flag" } */
+}
--
Joseph S. Myers
jsm28@cam.ac.uk