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. */