aboutsummaryrefslogtreecommitdiff
path: root/devel/freebsd-gcc6/files/patch-freebsd-format-extensions
blob: ed211f8e2070a655a377dee8f36742a1e2c26b8d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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, "<base><arg>*");
+     which produces:	reg=3<BITTWO,BITONE>
+     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