template<> void
dwflpp::iterate_over_srcfile_lines<void>(char const * srcfile,
- int linenos[2],
+ const vector<int> linenos,
enum lineno_t lineno_type,
base_func_info_map_t& funcs,
void (* callback) (Dwarf_Addr,
current_funcs, matching_lines);
else if (lineno_type == WILDCARD)
collect_all_lines(srcfile, current_funcs, matching_lines);
- else // RANGE
- for (int lineno = linenos[0]; lineno <= linenos[1]; lineno++)
- collect_lines_for_single_lineno(srcfile, lineno, false, /* is_relative */
+ else if (lineno_type == ENUMERATED)
+ for (vector<int>::const_iterator it = linenos.begin(); it != linenos.end(); it++)
+ collect_lines_for_single_lineno(srcfile, *it, false, /* is_relative */
current_funcs, matching_lines);
// call back with matching lines
dwflpp::iterate_over_labels<void>(Dwarf_Die *begin_die,
const string& sym,
const base_func_info& function,
- int linenos[2],
+ const vector<int> linenos,
enum lineno_t lineno_type,
void *data,
void (* callback)(const base_func_info&,
matches_lineno = dline == linenos[0];
else if (lineno_type == RELATIVE)
matches_lineno = dline == linenos[0] + function.decl_line;
- else if (lineno_type == RANGE)
- matches_lineno = (linenos[0] <= dline && dline <= linenos[1]);
+ else if (lineno_type == ENUMERATED)
+ matches_lineno = (binary_search(linenos.begin(), linenos.end(), dline));
else // WILDCARD
matches_lineno = true;
struct base_query;
struct external_function_query;
-enum lineno_t { ABSOLUTE, RELATIVE, RANGE, WILDCARD };
+enum lineno_t { ABSOLUTE, RELATIVE, WILDCARD, ENUMERATED };
enum info_status { info_unknown, info_present, info_absent };
// module -> cu die[]
template<typename T>
void iterate_over_srcfile_lines (char const * srcfile,
- int linenos[2],
+ const std::vector<int> linenos,
enum lineno_t lineno_type,
base_func_info_map_t& funcs,
void (*callback) (Dwarf_Addr,
void iterate_over_labels (Dwarf_Die *begin_die,
const std::string& sym,
const base_func_info& function,
- int linenos[2],
+ const std::vector<int> linenos,
enum lineno_t lineno_type,
T *data,
void (* callback)(const base_func_info&,
size_t));
template<> void
dwflpp::iterate_over_srcfile_lines<void>(char const * srcfile,
- int linenos[2],
+ const std::vector<int> linenos,
enum lineno_t lineno_type,
base_func_info_map_t& funcs,
void (* callback) (Dwarf_Addr,
dwflpp::iterate_over_labels<void>(Dwarf_Die *begin_die,
const std::string& sym,
const base_func_info& function,
- int linenos[2],
+ const std::vector<int> linenos,
enum lineno_t lineno_type,
void *data,
void (* callback)(const base_func_info&,
string function;
string file;
lineno_t lineno_type;
- int linenos[2];
+ vector<int> linenos;
bool query_done; // Found exact match
// Holds the prologue end of the current function
dwarf_query::parse_function_spec(const string & spec)
{
lineno_type = ABSOLUTE;
- linenos[0] = linenos[1] = 0;
-
- size_t src_pos, line_pos, dash_pos, scope_pos;
+ size_t src_pos, line_pos, scope_pos;
// look for named scopes
scope_pos = spec.rfind("::");
if (lineno_type != WILDCARD)
try
{
- // try to parse either N or N-M
- dash_pos = spec.find('-', line_pos + 1);
- if (dash_pos == string::npos)
- linenos[0] = linenos[1] = lex_cast<int>(spec.substr(line_pos + 1));
+ // try to parse N, N-M, or N,M,O,P, or combination thereof...
+ if (spec.find_first_of(",-", line_pos + 1) != string::npos)
+ {
+ lineno_type = ENUMERATED;
+ vector<string> sub_specs;
+ tokenize(spec.substr(line_pos + 1), sub_specs, ",");
+ vector<string>::const_iterator line_spec;
+ for (line_spec = sub_specs.begin(); line_spec != sub_specs.end(); ++line_spec)
+ {
+ vector<string> ranges;
+ tokenize(*line_spec, ranges, "-");
+ if (ranges.size() > 1)
+ for (int i = lex_cast<int>(ranges.front()); i <= lex_cast<int>(ranges.back()); i++)
+ linenos.push_back(i);
+ else
+ linenos.push_back(lex_cast<int>(ranges.at(0)));
+ }
+ sort(linenos.begin(), linenos.end());
+ }
else
{
- lineno_type = RANGE;
- linenos[0] = lex_cast<int>(spec.substr(line_pos + 1,
- dash_pos - line_pos - 1));
- linenos[1] = lex_cast<int>(spec.substr(dash_pos + 1));
- if (linenos[0] > linenos[1])
- throw runtime_error("bad range");
+ linenos.push_back(lex_cast<int>(spec.substr(line_pos + 1)));
+ linenos.push_back(lex_cast<int>(spec.substr(line_pos + 1)));
}
}
catch (runtime_error & exn)
clog << "+" << linenos[0];
break;
- case RANGE:
- clog << linenos[0] << " - " << linenos[1];
+ case ENUMERATED:
+ {
+ vector<int>::const_iterator linenos_it,range_it;
+ for (linenos_it = linenos.begin(); linenos_it != linenos.end(); ++linenos_it)
+ {
+ vector<int>::const_iterator range_it(linenos_it);
+ while ((range_it+1) != linenos.end() && *range_it + 1 == *(range_it+1))
+ ++range_it;
+ if (linenos_it == range_it)
+ clog << *linenos_it;
+ else
+ clog << *linenos_it << "-" << *range_it;
+ if (range_it + 1 != linenos.end())
+ clog << ",";
+ linenos_it = range_it;
+ }
+ }
break;
case WILDCARD:
# Now we do some consistent probe checking
-# ABSOLUTE and RANGE should give the same results for wild and single func
+# ABSOLUTE, RANGE, and ENUMERATED should give the same results for wild and single func
set subtest "ABSOLUTE - single func"
expect_probes foo 5 1
set subtest "ABSOLUTE - wild func"
expect_probes foo 5-7 3
set subtest "RANGE - wild func"
expect_probes * 5-7 3
-
-# But ABSOLUTE and RANGE shouldn't give any results if the linenos fall outside
+set subtest "ENUMERATED - single func"
+expect_probes foo 5,6,7 3
+set subtest "ENUMERATED and RANGE - single func"
+expect_probes foo 5,6-7 3
+set subtest "ENUMERATED - wild func"
+expect_probes * 5,6,7 3
+set subtest "ENUMERATED and RANGE - wild func"
+expect_probes * 5-6,7 3
+
+# But ABSOLUTE, RANGE, and ENUMERATED shouldn't give any results if the linenos fall outside
# the given func(s)
set subtest "ABSOLUTE - outside single func"
expect_probes bar 5 0
expect_probes bar 5-7 0
set subtest "RANGE - outside wild func"
expect_probes {[bm]*} 5-7 0
+set subtest "ENUMERATED - outside single func"
+expect_probes bar 5-6,7 0
+set subtest "ENUMERATED - outside wild func"
+expect_probes {[bm]*} 5,6-7 0
# RELATIVE and WILDCARD must be applied *per* function
set subtest "RELATIVE - single func"
set subtest "RANGE - out-of-bounds upper"
expect_probes foo 5-999 3
+# ENUMERATED on a function is bound by function linenos
+set subtest "ENUMERATED - out-of-bounds lower"
+expect_probes foo 0,1,2,3,4,5 2
+set subtest "ENUMERATED - out-of-bounds upper"
+expect_probes foo 5,6,7,998,999 3
+
# RANGE overlapping two functions yields intersection of range and filtered
# functions
set subtest "RANGE - single func overlapping"
set subtest "RANGE - wildcard func overlapping"
expect_probes * 5-13 6
+# ENUMERATED overlapping two functions yields intersection of range and filtered
+# functions
+set subtest "ENUMERATED - single func overlapping"
+expect_probes foo 5,6,7,8,9,10,11,12,13 3
+set subtest "ENUMERATED - wildcard func overlapping"
+expect_probes * 5,6,7,8,9,10,11,12,13 6
+
if {[file exists "$test"]} { file delete "$test" }