summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--NEWS29
-rw-r--r--elaborate.cxx57
-rw-r--r--elaborate.h1
-rw-r--r--staptree.cxx54
-rw-r--r--staptree.h25
6 files changed, 161 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 3c183d73..4326326c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2008-02-21 Dave Brolley <brolley@redhat.com>
+
+ PR5189
+ * staptree.h (print_format::conv_memory): New enumerator.
+ (print_format::width_type): New enumeration.
+ (print_format::precision_type): New enumeration.
+ (format_component::widthtype): New member.
+ (format_component::prectype): New member.
+ (format_component::is_empty): Test widthtype and prectype.
+ (format_component::clear): Clear widthtype and prectype.
+ * staptree.cxx (print_format::components_to_string): Handle dynamic width and precision.
+ Handle conv_memory.
+ (print_format::string_to_components): Parse dynamic width and precision specifiers.
+ Set widthtype and prectype. Parse %m format specifier.
+ * elaborate.h (typeresolution_info::check_arg_type): New method.
+ * elaborate.cxx (typeresolution_info::visit_print_format): Account for dynamic width
+ and precision when computing the expected number of arguments. Check the types of
+ arguments for dynamic width and precision. Use check_arg_type to check the types of
+ all arguments. Handle print_format::conv_memory.
+ (typeresolution_info::check_arg_type): New method.
+ * NEWS: Describe the enhancements above.
+
2008-02-27 David Smith <dsmith@redhat.com>
PR5729
diff --git a/NEWS b/NEWS
index df7e27b4..cd9c72db 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,34 @@
* What's new in version 0.6 / 0.6.1
+- There is a new format specifier, %m, for the printf family of
+ functions. It functions like %s, except that it does not stop when
+ a nul ('\0') byte is encountered. The number of bytes output is
+ determined by the precision specifier. The default precision is 1.
+ For example:
+
+ printf ("%m", "My String") // prints one character: M
+ printf ("%.5", myString) // prints 5 bytes beginning at the start
+ // of myString
+
+- The %b format specifier for the printf family of functions has been enhanced
+ as follows:
+
+ 1) When the width and precision are both unspecified, the default is %8.8b.
+ 2) When only one of the width or precision is specified, the other defaults
+ to the same value. For example, %4b == %.4b == %4.4b
+ 3) Nul ('\0') bytes are used for field width padding. For example,
+
+ printf ("%b", 0x1111deadbeef2222) // prints all eight bytes
+ printf ("%4.2b", 0xdeadbeef) // prints \0\0\xbe\xef
+
+- Dynamic width and precision are now supported for all printf family format
+ specifiers. For example:
+
+ four = 4
+ two = 2
+ printf ("%*.*b", four, two, 0xdeadbbeef) // prints \0\0\xbe\xef
+ printf ("%*d", four, two) // prints <space><space><space>2
+
- Preprocessor conditional expressions can now include wildcard style
matches on kernel versions.
%( kernel_vr != "*xen" %? foo %: bar %)
diff --git a/elaborate.cxx b/elaborate.cxx
index bc0d1489..7f4ccf35 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -2854,6 +2854,7 @@ typeresolution_info::visit_print_format (print_format* e)
// First we extract the subsequence of formatting components
// which are conversions (not just literal string components)
+ unsigned expected_num_args = 0;
std::vector<print_format::format_component> components;
for (size_t i = 0; i < e->components.size(); ++i)
{
@@ -2864,19 +2865,39 @@ typeresolution_info::visit_print_format (print_format* e)
|| e->components[i].type == print_format::conv_size)
continue;
components.push_back(e->components[i]);
+ ++expected_num_args;
+ if (e->components[i].widthtype == print_format::width_dynamic)
+ ++expected_num_args;
+ if (e->components[i].prectype == print_format::prec_dynamic)
+ ++expected_num_args;
}
// Then we check that the number of conversions and the number
// of args agree.
- if (components.size() != e->args.size())
+ if (expected_num_args != e->args.size())
throw semantic_error ("Wrong number of args to formatted print operator",
e->tok);
// Then we check that the types of the conversions match the types
// of the args.
+ unsigned argno = 0;
for (size_t i = 0; i < components.size(); ++i)
{
+ // Check the dynamic width, if specified
+ if (components[i].widthtype == print_format::width_dynamic)
+ {
+ check_arg_type (pe_long, e->args[argno]);
+ ++argno;
+ }
+
+ // Check the dynamic precision, if specified
+ if (components[i].prectype == print_format::prec_dynamic)
+ {
+ check_arg_type (pe_long, e->args[argno]);
+ ++argno;
+ }
+
exp_type wanted = pe_unknown;
switch (components[i].type)
@@ -2898,24 +2919,14 @@ typeresolution_info::visit_print_format (print_format* e)
break;
case print_format::conv_string:
+ case print_format::conv_memory:
wanted = pe_string;
break;
}
assert (wanted != pe_unknown);
-
- t = wanted;
- e->args[i]->visit (this);
-
- if (e->args[i]->type == pe_unknown)
- {
- e->args[i]->type = wanted;
- resolved (e->args[i]->tok, wanted);
- }
- else if (e->args[i]->type != wanted)
- {
- mismatch (e->args[i]->tok, e->args[i]->type, wanted);
- }
+ check_arg_type (wanted, e->args[argno]);
+ ++argno;
}
}
else
@@ -2976,6 +2987,24 @@ typeresolution_info::visit_hist_op (hist_op* e)
void
+typeresolution_info::check_arg_type (exp_type wanted, expression* arg)
+{
+ t = wanted;
+ arg->visit (this);
+
+ if (arg->type == pe_unknown)
+ {
+ arg->type = wanted;
+ resolved (arg->tok, wanted);
+ }
+ else if (arg->type != wanted)
+ {
+ mismatch (arg->tok, arg->type, wanted);
+ }
+}
+
+
+void
typeresolution_info::unresolved (const token* tok)
{
num_still_unresolved ++;
diff --git a/elaborate.h b/elaborate.h
index 607f8689..fc8fbbcb 100644
--- a/elaborate.h
+++ b/elaborate.h
@@ -54,6 +54,7 @@ struct typeresolution_info: public visitor
functiondecl* current_function;
derived_probe* current_probe;
+ void check_arg_type (exp_type wanted, expression* arg);
void mismatch (const token* tok, exp_type t1, exp_type t2);
void unresolved (const token* tok);
void resolved (const token* tok, exp_type t);
diff --git a/staptree.cxx b/staptree.cxx
index 36ef04f5..63c1fcf7 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -442,10 +442,14 @@ print_format::components_to_string(vector<format_component> const & components)
if (i->flags & static_cast<unsigned long>(fmt_flag_special))
oss << '#';
- if (i->width > 0)
+ if (i->widthtype == width_dynamic)
+ oss << '*';
+ else if (i->widthtype != width_unspecified && i->width > 0)
oss << i->width;
- if (i->precision > 0)
+ if (i->prectype == prec_dynamic)
+ oss << ".*";
+ else if (i->prectype != prec_unspecified && i->precision > 0)
oss << '.' << i->precision;
switch (i->type)
@@ -482,6 +486,10 @@ print_format::components_to_string(vector<format_component> const & components)
oss << 's';
break;
+ case conv_memory:
+ oss << 'm';
+ break;
+
case conv_size:
oss << 'n';
break;
@@ -574,14 +582,27 @@ print_format::string_to_components(string const & str)
break;
}
+ if (i == str.end())
+ break;
+
// Parse optional width
-
- while (i != str.end() && isdigit(*i))
+ if (*i == '*')
{
- curr.width *= 10;
- curr.width += (*i - '0');
+ curr.widthtype = width_dynamic;
++i;
}
+ else if (isdigit(*i))
+ {
+ curr.widthtype = width_static;
+ curr.width = 0;
+ do
+ {
+ curr.width *= 10;
+ curr.width += (*i - '0');
+ ++i;
+ }
+ while (i != str.end() && isdigit(*i));
+ }
if (i == str.end())
break;
@@ -592,12 +613,23 @@ print_format::string_to_components(string const & str)
++i;
if (i == str.end())
break;
- while (i != str.end() && isdigit(*i))
+ if (*i == '*')
{
- curr.precision *= 10;
- curr.precision += (*i - '0');
+ curr.prectype = prec_dynamic;
++i;
}
+ else if (isdigit(*i))
+ {
+ curr.prectype = prec_static;
+ curr.precision = 0;
+ do
+ {
+ curr.precision *= 10;
+ curr.precision += (*i - '0');
+ ++i;
+ }
+ while (i != str.end() && isdigit(*i));
+ }
}
if (i == str.end())
@@ -615,6 +647,10 @@ print_format::string_to_components(string const & str)
curr.type = conv_string;
break;
+ case 'm':
+ curr.type = conv_memory;
+ break;
+
case 'd':
case 'i':
curr.type = conv_signed_decimal;
diff --git a/staptree.h b/staptree.h
index 8235a535..acb56719 100644
--- a/staptree.h
+++ b/staptree.h
@@ -287,31 +287,48 @@ struct print_format: public expression
conv_unsigned_uppercase_hex,
conv_unsigned_lowercase_hex,
conv_string,
+ conv_memory,
conv_literal,
conv_binary,
conv_size
};
+ enum width_type
+ {
+ width_unspecified,
+ width_static,
+ width_dynamic
+ };
+
+ enum precision_type
+ {
+ prec_unspecified,
+ prec_static,
+ prec_dynamic
+ };
+
struct format_component
{
unsigned long flags;
unsigned width;
unsigned precision;
+ width_type widthtype;
+ precision_type prectype;
conversion_type type;
std::string literal_string;
bool is_empty() const
{
return flags == 0
- && width == 0
- && precision == 0
+ && widthtype == width_unspecified
+ && prectype == prec_unspecified
&& type == conv_unspecified
&& literal_string.empty();
}
void clear()
{
flags = 0;
- width = 0;
- precision = 0;
+ widthtype = width_unspecified;
+ prectype = prec_unspecified;
type = conv_unspecified;
literal_string.clear();
}