Index: gcc/c-family/c-format.c =================================================================== --- gcc/c-family/c-format.c (revision 216017) +++ gcc/c-family/c-format.c (working copy) @@ -622,6 +622,26 @@ { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } }; +static const format_char_info fbsd_ext_char_info = +{ NULL, 1, STD_EXT, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL }; + +static const format_char_info fbsd_print_char_table[] = +{ + /* BSD conversion specifiers. */ + /* FreeBSD kernel extensions (src/sys/kern/subr_prf.c). + The format %b is supported to decode error registers. + Its usage is: printf("reg=%b\n", regval, "*"); + which produces: reg=3 + The format %D provides a hexdump given a pointer and separator string: + ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX + ("%*D", len, ptr, " ") -> XX XX XX XX ... + */ + { "D", 1, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", &fbsd_ext_char_info }, + { "b", 0, STD_EXT, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "", &fbsd_ext_char_info }, + { "ry", 0, STD_EXT, { T89_I, BADLEN, BADLEN, T89_L, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "i", NULL }, + { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } +}; + static const format_char_info asm_fprintf_char_table[] = { /* C89 conversion specifiers. */ @@ -872,6 +892,12 @@ strfmon_flag_specs, strfmon_flag_pairs, FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L', 0, NULL, NULL + }, + { "printf0", printf_length_specs, print_char_table, " +#0-'I", NULL, + printf_flag_specs, printf_flag_pairs, + FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK|FMT_FLAG_NULL_FORMAT_OK, + 'w', 0, 'p', 0, 'L', 0, + &integer_type_node, &integer_type_node } }; @@ -1426,6 +1452,9 @@ if (integer_zerop (format_tree)) { + if (!(format_types[info->format_type].flags & FMT_FLAG_NULL_FORMAT_OK)) + warning (OPT_Wformat_, "null format string"); + /* Skip to first argument to check, so we can see if this format has any arguments (it shouldn't). */ while (arg_num + 1 < info->first_arg_num) @@ -1926,6 +1955,14 @@ while (fli->name != 0 && strncmp (fli->name, format_chars, strlen (fli->name))) fli++; + /* + * Make sure FreeBSD's D format char takes preference + * over new DD length specifier if FreeBSD format + * extensions are requested. + */ + if (fli->index == FMT_LEN_D && flag_format_extensions + && fki->conversion_specs == print_char_table) + while (fli->name != 0) fli++; if (fli->name != 0) { format_chars += strlen (fli->name); @@ -1993,6 +2030,14 @@ while (fci->format_chars != 0 && strchr (fci->format_chars, format_char) == 0) ++fci; + if (fci->format_chars == 0 && flag_format_extensions + && fki->conversion_specs == print_char_table) + { + fci = fbsd_print_char_table; + while (fci->format_chars != 0 + && strchr (fci->format_chars, format_char) == 0) + ++fci; + } if (fci->format_chars == 0) { if (ISGRAPH (format_char)) Index: gcc/c-family/c-format.h =================================================================== --- gcc/c-family/c-format.h (revision 216017) +++ gcc/c-family/c-format.h (working copy) @@ -75,11 +75,12 @@ FMT_FLAG_DOLLAR_GAP_POINTER_OK = 128, /* The format arg is an opaque object that will be parsed by an external facility. */ - FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL = 256 + FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL = 256, /* Not included here: details of whether width or precision may occur (controlled by width_char and precision_char); details of whether '*' can be used for these (width_type and precision_type); details of whether length modifiers can occur (length_char_specs). */ + FMT_FLAG_NULL_FORMAT_OK = 512 }; /* Structure describing a length modifier supported in format checking, and Index: gcc/config/freebsd.opt =================================================================== --- gcc/config/freebsd.opt (revision 216017) +++ gcc/config/freebsd.opt (working copy) @@ -34,6 +34,10 @@ defsym= Driver JoinedOrMissing +fformat-extensions +Common Report Var(flag_format_extensions) Init(0) +Allow FreeBSD kernel-specific printf format specifiers. + posix Driver