summaryrefslogtreecommitdiffstats
path: root/staptree.cxx
diff options
context:
space:
mode:
authorgraydon <graydon>2005-11-24 05:55:52 +0000
committergraydon <graydon>2005-11-24 05:55:52 +0000
commit07c17d677a8080492b4a67b664f4cc9557f5dda3 (patch)
treeddff61760db8a9d3067f3e559ce36eca9e642811 /staptree.cxx
parent5bb3c2a0266268e63d373de4df3fed2bb7d3be67 (diff)
downloadsystemtap-steved-07c17d677a8080492b4a67b664f4cc9557f5dda3.tar.gz
systemtap-steved-07c17d677a8080492b4a67b664f4cc9557f5dda3.tar.xz
systemtap-steved-07c17d677a8080492b4a67b664f4cc9557f5dda3.zip
2005-11-23 Graydon Hoare <graydon@redhat.com>
* elaborate.h (get_symbol_within_expression): Make visible. * elaborate.cxx (get_symbol_within_expression): Make non-static. (stat_decl_collector): New struct. (semantic_pass_stats): New semantic pass. (semantic_pass): Call it. (semantic_pass_symbols): Remove collection of statistic_decls from files. (visit_stat_op): Only fail if inferred type is not pe_long. * parse.cxx (parser::parse): Don't pass per-file statistic_decl into parse_global. (parser::parse_global): Don't parse global statistic_decls, they're obsolete. * parse.hh (parser::parse_global): Adjust signature to match. * session.h (statistic_decl::operator==): New method. * staptree.h (print_format::is_empty): New method. (stapfile::stat_decls): Remove field. * staptree.cxx (string_to_components): Fix bugs in format-string parser. * translate.cxx (var): Make private fields protected. (var::init): Support HIST_NONE stats. (aggvar): New struct. (mapvar::is_parallel): New method. (mapvar::call_prefix): Use it. (mapvar::calculate_aggregate): New method. (mapvar::fetch_existing_aggregate): New method. (mapvar::get): Support pe_stats. (mapvar::init): Use is_parallel(), and support HIST_NONE. (itervar::itervar): Only fault on pe_unknown. (itervar::start): Use mapvar::is_parallel and mapvar::fetch_existing_aggregate. (emit_map_type_instantiations): Include alloc.c before pmap-gen.c. Include pmap-gen.c for pe_stats maps. (c_unparser::gensym_aggregate): New method. (c_unparser::visit_foreach_loop): Handle mapvar::is_parallel case. (arrayindex_downcaster): New struct. (expression_is_arrayindex): New function. (c_tmpcounter::visit_stat_op): New method. (c_unparser::visit_stat_op): Implement. (c_unparser::visit_hist_op): Add commentary, still not implemented. * testsuite/buildok/stat_{insert,extract}.stp: New tests. * testsuite/semok/ten.stp: Correct for changes to global declarations. * testsuite/semko/*.stp: Likewise.
Diffstat (limited to 'staptree.cxx')
-rw-r--r--staptree.cxx304
1 files changed, 128 insertions, 176 deletions
diff --git a/staptree.cxx b/staptree.cxx
index 6ea1fc70..6f75e09b 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -404,206 +404,158 @@ print_format::string_to_components(string const & str)
format_component curr;
vector<format_component> res;
- enum
- {
- parsing_plain_data,
- parsing_flags,
- parsing_width,
- parsing_precision,
- parsing_conversion_specifier
- }
- state = parsing_plain_data;
-
curr.clear();
string::const_iterator i = str.begin();
-
+
while (i != str.end())
{
- switch (state)
+ if (*i != '%')
{
- case parsing_plain_data:
-
- if (*i != '%')
- {
- assert (curr.type == conv_unspecified || curr.type == conv_literal);
- curr.type = conv_literal;
- curr.literal_string += *i;
- }
- else if (i+1 == str.end() || *(i+1) == '%')
- {
- assert(*i == '%');
- // *i == '%' and *(i+1) == '%'; append only one '%' to the literal string
- assert (curr.type == conv_unspecified || curr.type == conv_literal);
- curr.type = conv_literal;
- curr.literal_string += '%';
- }
- else
- {
- assert(*i == '%');
- state = parsing_flags;
- if (curr.type != conv_unspecified)
- {
- assert (curr.type == conv_literal);
- res.push_back(curr);
- curr.clear();
- }
- }
+ assert (curr.type == conv_unspecified || curr.type == conv_literal);
+ curr.type = conv_literal;
+ curr.literal_string += *i;
++i;
- break;
-
- case parsing_flags:
- switch (*i)
+ continue;
+ }
+ else if (i+1 == str.end() || *(i+1) == '%')
+ {
+ assert(*i == '%');
+ // *i == '%' and *(i+1) == '%'; append only one '%' to the literal string
+ assert (curr.type == conv_unspecified || curr.type == conv_literal);
+ curr.type = conv_literal;
+ curr.literal_string += '%';
+ ++i;
+ continue;
+ }
+ else
+ {
+ assert(*i == '%');
+ if (curr.type != conv_unspecified)
{
- case '0':
- curr.flags |= static_cast<unsigned long>(fmt_flag_zeropad);
- ++i;
- break;
-
- case '+':
- curr.flags |= static_cast<unsigned long>(fmt_flag_plus);
- ++i;
- break;
-
- case '-':
- curr.flags |= static_cast<unsigned long>(fmt_flag_left);
- ++i;
- break;
-
- case ' ':
- curr.flags |= static_cast<unsigned long>(fmt_flag_space);
- ++i;
- break;
+ // Flush any component we were previously accumulating
+ assert (curr.type == conv_literal);
+ res.push_back(curr);
+ curr.clear();
+ }
+ }
+ ++i;
+
+ if (i == str.end())
+ break;
- case '#':
- curr.flags |= static_cast<unsigned long>(fmt_flag_special);
- ++i;
- break;
+ // Now we are definitely parsing a conversion.
+ // Begin by parsing flags (whicih are optional).
- default:
- state = parsing_width;
- break;
- }
+ switch (*i)
+ {
+ case '0':
+ curr.flags |= static_cast<unsigned long>(fmt_flag_zeropad);
+ ++i;
break;
-
- case parsing_width:
- while (isdigit(*i))
- {
- curr.width *= 10;
- curr.width += (*i - '0');
- ++i;
- }
- state = parsing_precision;
+
+ case '+':
+ curr.flags |= static_cast<unsigned long>(fmt_flag_plus);
+ ++i;
break;
- case parsing_precision:
- if (*i == '.')
- {
- ++i;
- while (isdigit(*i))
- {
- curr.precision *= 10;
- curr.precision += (*i - '0');
- ++i;
- }
- }
- state = parsing_conversion_specifier;
+ case '-':
+ curr.flags |= static_cast<unsigned long>(fmt_flag_left);
+ ++i;
break;
+
+ case ' ':
+ curr.flags |= static_cast<unsigned long>(fmt_flag_space);
+ ++i;
+ break;
+
+ case '#':
+ curr.flags |= static_cast<unsigned long>(fmt_flag_special);
+ ++i;
+ break;
+
+ default:
+ break;
+ }
- case parsing_conversion_specifier:
- switch (*i)
- {
-
- default:
- if (curr.type == conv_unspecified)
- throw semantic_error("no conversion specifier provided");
-
- res.push_back(curr);
- curr.clear();
- state = parsing_plain_data;
- break;
-
- // Valid conversion types
- case 's':
- if (curr.type != conv_unspecified)
- throw semantic_error("multiple conversion types supplied");
- curr.type = conv_string;
- ++i;
- break;
-
- case 'd':
- case 'i':
- if (curr.type != conv_unspecified)
- throw semantic_error("multiple conversion types supplied");
- curr.type = conv_signed_decimal;
- ++i;
- break;
-
- case 'o':
- if (curr.type != conv_unspecified)
- throw semantic_error("multiple conversion types supplied");
- curr.type = conv_unsigned_octal;
- ++i;
- break;
+ // Parse optional width
+
+ while (i != str.end() && isdigit(*i))
+ {
+ curr.width *= 10;
+ curr.width += (*i - '0');
+ ++i;
+ }
- case 'u':
- if (curr.type != conv_unspecified)
- throw semantic_error("multiple conversion types supplied");
- curr.type = conv_unsigned_decimal;
- ++i;
- break;
+ if (i == str.end())
+ break;
- case 'X':
- if (curr.type != conv_unspecified)
- throw semantic_error("multiple conversion types supplied");
- curr.type = conv_unsigned_uppercase_hex;
+ // Parse optional precision
+ if (*i == '.')
+ {
+ ++i;
+ if (i == str.end())
+ break;
+ while (i != str.end() && isdigit(*i))
+ {
+ curr.precision *= 10;
+ curr.precision += (*i - '0');
++i;
+ }
+ }
- case 'x':
- if (curr.type != conv_unspecified)
- throw semantic_error("multiple conversion types supplied");
- curr.type = conv_unsigned_lowercase_hex;
- ++i;
- break;
+ if (i == str.end())
+ break;
- // We prohibit users passing any funny stuff through which might
- // make linux's printf function do naughty things.
- case 'p':
- case 'n':
- case 'c':
- case 'q':
- case 'j':
- case 't':
-
- case ',':
- case '.':
- case '*':
-
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- case 'h':
- case 'H':
- case 'I':
- case 'l':
- case 'L':
- case 'z':
- case 'Z':
- string err("prohibited conversion character '");
- err += *i;
- err += '"';
- throw parse_error(err);
- }
+ // Parse the actual conversion specifier (sdiouxX)
+ switch (*i)
+ {
+ // Valid conversion types
+ case 's':
+ curr.type = conv_string;
+ break;
+
+ case 'd':
+ case 'i':
+ curr.type = conv_signed_decimal;
+ break;
+
+ case 'o':
+ curr.type = conv_unsigned_octal;
+ break;
+
+ case 'u':
+ curr.type = conv_unsigned_decimal;
+ break;
+
+ case 'X':
+ curr.type = conv_unsigned_uppercase_hex;
+ break;
+
+ case 'x':
+ curr.type = conv_unsigned_lowercase_hex;
+ break;
+
+ default:
break;
}
+
+ if (curr.type == conv_unspecified)
+ throw semantic_error("invalid or missing conversion specifier");
+
+ ++i;
+ res.push_back(curr);
+ curr.clear();
}
- // Flush final component
- if (curr.type != conv_unspecified)
- res.push_back(curr);
+ // If there's a remaining partly-composed conversion, fail.
+ if (!curr.is_empty())
+ {
+ if (curr.type == conv_literal)
+ res.push_back(curr);
+ else
+ throw semantic_error("trailing incomplete print format conversion");
+ }
return res;
}