On Sun, 14 Apr 2013, Theo de Raadt wrote:
Since the kernel's printf does not support %td for ptrdiff_t, I have
used %ld instead. %zd would also work. Is there a preferred way?

Or try to add %td support to kernel printf?

The patch below seems to do the trick for gcc 4.2.

I can't see that we would add an arch where sizeof(ptrdiff_t) != sizeof(size_t). Therefore I don't see any benefit in adding code that deals with this case and which would probably be just slightly to complicated for the compiler to optimize away on sane archs.

Checking sizeof(ptrdiff_t) == sizeof(size_t) there would be a good use for a compile time assert macro (like _Static_assert in C11). Do we have that and I didn't find it? Or do we want to add one?

Adding ptrdiff_t to stdint.h is not strictly necessary, but I see no reason not to do it.


--- a/gnu/gcc/gcc/c-format.c
+++ b/gnu/gcc/gcc/c-format.c
@@ -325,6 +325,7 @@ static const format_length_info kprintf_length_specs[] =
   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
   { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 },
   { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 },
+  { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 },
   { NULL, 0, 0, NULL, 0, 0 }
 };

@@ -552,9 +553,9 @@ static const format_char_info asm_fprintf_char_table[] =
 static const format_char_info kprint_char_table[] =
 {
/* C89 conversion specifiers. */ - { "di", 0, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +'I", "i", NULL }, - { "oxX", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, BADLEN, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL }, - { "u", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, BADLEN, T99_ST, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0'I", "i", NULL }, + { "di", 0, STD_C89, { T89_I, BADLEN, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +'I", "i", NULL }, + { "oxX", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, BADLEN, T99_ST, T99_UPD, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL }, + { "u", 0, STD_C89, { T89_UI, BADLEN, T89_US, T89_UL, T9L_ULL, BADLEN, T99_ST, T99_UPD, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0'I", "i", NULL },
   { "c",   0, STD_C89, { T89_I,   BADLEN, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  
BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",       "", NULL },
   { "s",   1, STD_C89, { T89_C,   BADLEN, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  
BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",      "cR", NULL },
{ "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, T89_UL, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0", "c", NULL }, --- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -834,6 +834,9 @@ reswitch:   switch (ch) {
                case 'q':
                        flags |= QUADINT;
                        goto rflag;
+               case 't':
+                       /* for us, ptrdiff_t (C) is equal to ssize_t (POSIX) */
+                       /* FALLTHROUGH */
                case 'z':
                        flags |= SIZEINT;
                        goto rflag;
--- a/sys/sys/stdint.h
+++ b/sys/sys/stdint.h
@@ -95,6 +95,9 @@ typedef       __uintptr_t             uintptr_t;
 typedef        __intmax_t              intmax_t;
 typedef        __uintmax_t             uintmax_t;

+/* Integer type of the result of substracting two pointers */
+typedef        __ptrdiff_t             ptrdiff_t;
+
 #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
 /*
  * 7.18.2 Limits of specified-width integer types.




For older gcc, it seems more difficult to add support for %t. At least, the code is quite different. Maybe this patch does the trick but it is untested. And it again assumes that sizeof(size_t) == sizeof(ptrdiff_t). IMHO simply keeping -Wno-format on architectures that use old gcc versions should be ok, too.

--- a/gnu/egcs/gcc/c-common.c
+++ b/gnu/egcs/gcc/c-common.c
@@ -2497,7 +2497,7 @@ check_format_info (info, params)
              if (pedantic)
                warning ("ANSI C does not support the `Z' length modifier");
            }
-         else if (*format_chars == 'z')
+         else if (*format_chars == 'z' || *format_chars == 't')
            {
              length_char = 'Z', format_chars++;
              /* FIXME: Is allowed in ISO C 9x.  */

Reply via email to