]> sourceware.org Git - systemtap.git/blame - tapset-mark.cxx
kill interned_string::c_str(), allowing shared substr()
[systemtap.git] / tapset-mark.cxx
CommitLineData
dd0e4fa7 1// tapset for kernel static markers
ef36f781 2// Copyright (C) 2005-2014 Red Hat Inc.
dd0e4fa7 3// Copyright (C) 2005-2007 Intel Corporation.
dd0e4fa7
JS
4//
5// This file is part of systemtap, and is free software. You can
6// redistribute it and/or modify it under the terms of the GNU General
7// Public License (GPL); either version 2, or (at your option) any
8// later version.
9
10#include "session.h"
11#include "tapsets.h"
12#include "translate.h"
13#include "util.h"
14
15#include <cerrno>
16#include <cstdlib>
17#include <cstring>
18#include <string>
19
20extern "C" {
21#include <fnmatch.h>
22}
23
24
25using namespace std;
26using namespace __gnu_cxx;
27
28
4627ed58
JS
29static const string TOK_KERNEL("kernel");
30static const string TOK_MARK("mark");
31static const string TOK_FORMAT("format");
dd0e4fa7
JS
32
33
34// ------------------------------------------------------------------------
35// statically inserted macro-based derived probes
36// ------------------------------------------------------------------------
37
38struct mark_arg
39{
40 bool str;
92dad52b 41 bool isptr;
dd0e4fa7
JS
42 string c_type;
43 exp_type stp_type;
44};
45
46struct mark_derived_probe: public derived_probe
47{
48 mark_derived_probe (systemtap_session &s,
49 const string& probe_name, const string& probe_format,
50 probe* base_probe, probe_point* location);
51
52 systemtap_session& sess;
53 string probe_name, probe_format;
54 vector <struct mark_arg *> mark_args;
55 bool target_symbol_seen;
56
57 void join_group (systemtap_session& s);
58 void print_dupe_stamp (ostream& o);
dd0e4fa7 59 void initialize_probe_context_vars (translator_output* o);
d0bfd2ac 60 void getargs (std::list<std::string> &arg_set) const;
dd0e4fa7
JS
61
62 void parse_probe_format ();
63};
64
65
66struct mark_derived_probe_group: public generic_dpg<mark_derived_probe>
67{
68public:
69 void emit_module_decls (systemtap_session& s);
70 void emit_module_init (systemtap_session& s);
71 void emit_module_exit (systemtap_session& s);
72};
73
74
75struct mark_var_expanding_visitor: public var_expanding_visitor
76{
77 mark_var_expanding_visitor(systemtap_session& s, const string& pn,
78 vector <struct mark_arg *> &mark_args):
79 sess (s), probe_name (pn), mark_args (mark_args),
80 target_symbol_seen (false) {}
81 systemtap_session& sess;
82 string probe_name;
83 vector <struct mark_arg *> &mark_args;
84 bool target_symbol_seen;
85
86 void visit_target_symbol (target_symbol* e);
87 void visit_target_symbol_arg (target_symbol* e);
88 void visit_target_symbol_context (target_symbol* e);
89};
90
91
92void
93mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
94{
47d349b1 95 string argnum_s = (string)e->name.substr(4,e->name.length()-4);
dd0e4fa7
JS
96 int argnum = atoi (argnum_s.c_str());
97
98 if (argnum < 1 || argnum > (int)mark_args.size())
dc09353a 99 throw SEMANTIC_ERROR (_("invalid marker argument number"), e->tok);
dd0e4fa7
JS
100
101 if (is_active_lvalue (e))
dc09353a 102 throw SEMANTIC_ERROR(_("write to marker parameter not permitted"), e->tok);
dd0e4fa7 103
dc5a09fc 104 e->assert_no_components("marker");
dd0e4fa7
JS
105
106 // Remember that we've seen a target variable.
107 target_symbol_seen = true;
108
a45664f4
JS
109 symbol* sym = new symbol;
110 sym->tok = e->tok;
111 sym->name = "__mark_arg" + lex_cast(argnum);
112 provide (sym);
dd0e4fa7
JS
113}
114
115
116void
117mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
118{
47d349b1 119 string sname = e->name;
dd0e4fa7
JS
120
121 if (is_active_lvalue (e))
dc09353a 122 throw SEMANTIC_ERROR(_F("write to marker '%s' not permitted", sname.c_str()), e->tok);
dd0e4fa7 123
dc5a09fc 124 e->assert_no_components("marker");
dd0e4fa7 125
277c21bc 126 if (e->name == "$format" || e->name == "$name") {
bfdaad1e
DS
127 // Synthesize an embedded expression.
128 embedded_expr *expr = new embedded_expr;
129 expr->tok = e->tok;
130
131 if (e->name == "$format")
132 expr->code = string("/* string */ /* pure */ ")
6dceb5c9 133 + string("c->ips.kmark.marker_format ? c->ips.kmark.marker_format : \"\"");
bfdaad1e
DS
134 else
135 expr->code = string("/* string */ /* pure */ ")
6dceb5c9 136 + string("c->ips.kmark.marker_name ? c->ips.kmark.marker_name : \"\"");
bfdaad1e
DS
137
138 provide (expr);
92dad52b 139 }
277c21bc 140 else if (e->name == "$$vars" || e->name == "$$parms")
92dad52b
WH
141 {
142 //copy from tracepoint
1c922ad7 143 print_format* pf = print_format::create(e->tok, "sprintf");
92dad52b
WH
144
145 for (unsigned i = 0; i < mark_args.size(); ++i)
146 {
147 if (i > 0)
148 pf->raw_components += " ";
aca66a36 149 pf->raw_components += "$arg" + lex_cast(i+1);
92dad52b
WH
150 target_symbol *tsym = new target_symbol;
151 tsym->tok = e->tok;
277c21bc 152 tsym->name = "$arg" + lex_cast(i+1);
92dad52b
WH
153
154 tsym->saved_conversion_error = 0;
155 expression *texp = require (tsym); //same treatment as tracepoint
156 assert (!tsym->saved_conversion_error);
157 switch (mark_args[i]->stp_type)
158 {
159 case pe_long:
160 pf->raw_components += mark_args[i]->isptr ? "=%p" : "=%#x";
161 break;
162 case pe_string:
163 pf->raw_components += "=%s";
164 break;
165 default:
166 pf->raw_components += "=%#x";
167 break;
168 }
169 pf->args.push_back(texp);
170 }
171 pf->components = print_format::string_to_components(pf->raw_components);
172 provide (pf);
dd0e4fa7 173 }
dd0e4fa7
JS
174}
175
176void
177mark_var_expanding_visitor::visit_target_symbol (target_symbol* e)
178{
277c21bc 179 assert(e->name.size() > 0 && e->name[0] == '$');
dd0e4fa7 180
c69a87e0
FCE
181 try
182 {
183 if (e->addressof)
dc09353a 184 throw SEMANTIC_ERROR(_("cannot take address of marker variable"), e->tok);
277c21bc 185
47d349b1 186 if (startswith(e->name, "$arg"))
c69a87e0 187 visit_target_symbol_arg (e);
277c21bc
JS
188 else if (e->name == "$format" || e->name == "$name"
189 || e->name == "$$parms" || e->name == "$$vars")
c69a87e0
FCE
190 visit_target_symbol_context (e);
191 else
dc09353a 192 throw SEMANTIC_ERROR (_("invalid target symbol for marker, $argN, $name, $format, $$parms or $$vars expected"),
c69a87e0
FCE
193 e->tok);
194 }
195 catch (const semantic_error &er)
196 {
1af1e62d 197 e->chain (er);
c69a87e0
FCE
198 provide (e);
199 }
dd0e4fa7
JS
200}
201
202
dd0e4fa7
JS
203mark_derived_probe::mark_derived_probe (systemtap_session &s,
204 const string& p_n,
205 const string& p_f,
206 probe* base, probe_point* loc):
4c5d1300 207 derived_probe (base, loc, true /* .components soon rewritten */),
dd0e4fa7
JS
208 sess (s), probe_name (p_n), probe_format (p_f),
209 target_symbol_seen (false)
210{
211 // create synthetic probe point name; preserve condition
212 vector<probe_point::component*> comps;
213 comps.push_back (new probe_point::component (TOK_KERNEL));
214 comps.push_back (new probe_point::component (TOK_MARK, new literal_string (probe_name)));
215 comps.push_back (new probe_point::component (TOK_FORMAT, new literal_string (probe_format)));
216 this->sole_location()->components = comps;
217
218 // expand the marker format
219 parse_probe_format();
220
221 // Now expand the local variables in the probe body
222 mark_var_expanding_visitor v (sess, name, mark_args);
8b095b45 223 v.replace (this->body);
dd0e4fa7 224 target_symbol_seen = v.target_symbol_seen;
a45664f4
JS
225 if (target_symbol_seen)
226 for (unsigned i = 0; i < mark_args.size(); ++i)
227 {
228 vardecl* v = new vardecl;
229 v->name = "__mark_arg" + lex_cast(i+1);
230 v->tok = this->tok;
58701b78 231 v->set_arity(0, this->tok);
a45664f4 232 v->type = mark_args[i]->stp_type;
69aa668e 233 v->synthetic = true;
a45664f4
JS
234 this->locals.push_back (v);
235 }
dd0e4fa7
JS
236
237 if (sess.verbose > 2)
ce0f6648
LB
238 clog << "marker-based " << name << " mark=" << probe_name << " fmt='" << probe_format
239 << "'" << endl;
dd0e4fa7
JS
240}
241
242
243static int
244skip_atoi(const char **s)
245{
246 int i = 0;
247 while (isdigit(**s))
248 i = i * 10 + *((*s)++) - '0';
249 return i;
250}
251
252
253void
254mark_derived_probe::parse_probe_format()
255{
256 const char *fmt = probe_format.c_str();
257 int qualifier; // 'h', 'l', or 'L' for integer fields
258 mark_arg *arg;
259
260 for (; *fmt ; ++fmt)
261 {
262 if (*fmt != '%')
263 {
264 /* Skip text */
265 continue;
266 }
267
268repeat:
269 ++fmt;
270
271 // skip conversion flags (if present)
272 switch (*fmt)
273 {
274 case '-':
275 case '+':
276 case ' ':
277 case '#':
278 case '0':
279 goto repeat;
280 }
281
282 // skip minimum field witdh (if present)
283 if (isdigit(*fmt))
284 skip_atoi(&fmt);
285
286 // skip precision (if present)
287 if (*fmt == '.')
288 {
289 ++fmt;
290 if (isdigit(*fmt))
291 skip_atoi(&fmt);
292 }
293
294 // get the conversion qualifier (if present)
295 qualifier = -1;
296 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
297 {
298 qualifier = *fmt;
299 ++fmt;
300 if (qualifier == 'l' && *fmt == 'l')
301 {
302 qualifier = 'L';
303 ++fmt;
304 }
305 }
306
307 // get the conversion type
308 switch (*fmt)
309 {
310 case 'c':
311 arg = new mark_arg;
312 arg->str = false;
92dad52b 313 arg->isptr = false;
dd0e4fa7
JS
314 arg->c_type = "int";
315 arg->stp_type = pe_long;
316 mark_args.push_back(arg);
317 continue;
318
319 case 's':
320 arg = new mark_arg;
321 arg->str = true;
92dad52b 322 arg->isptr = false;
dd0e4fa7
JS
323 arg->c_type = "char *";
324 arg->stp_type = pe_string;
325 mark_args.push_back(arg);
326 continue;
327
328 case 'p':
329 arg = new mark_arg;
330 arg->str = false;
92dad52b 331 arg->isptr = true;
dd0e4fa7
JS
332 // This should really be 'void *'. But, then we'll get a
333 // compile error when we assign the void pointer to an
334 // integer without a cast. So, we use 'long' instead, since
335 // it should have the same size as 'void *'.
336 arg->c_type = "long";
337 arg->stp_type = pe_long;
338 mark_args.push_back(arg);
339 continue;
340
341 case '%':
342 continue;
343
344 case 'o':
345 case 'X':
346 case 'x':
347 case 'd':
348 case 'i':
349 case 'u':
350 // fall through...
351 break;
352
353 default:
354 if (!*fmt)
355 --fmt;
356 continue;
357 }
358
359 arg = new mark_arg;
360 arg->str = false;
92dad52b 361 arg->isptr = false;
dd0e4fa7
JS
362 arg->stp_type = pe_long;
363 switch (qualifier)
364 {
365 case 'L':
366 arg->c_type = "long long";
367 break;
368
369 case 'l':
370 arg->c_type = "long";
371 break;
372
373 case 'h':
374 arg->c_type = "short";
375 break;
376
377 default:
378 arg->c_type = "int";
379 break;
380 }
381 mark_args.push_back(arg);
382 }
383}
384
385
386void
387mark_derived_probe::join_group (systemtap_session& s)
388{
389 if (! s.mark_derived_probes)
390 {
391 s.mark_derived_probes = new mark_derived_probe_group ();
392
393 // Make sure <linux/marker.h> is included early.
394 embeddedcode *ec = new embeddedcode;
395 ec->tok = NULL;
396 ec->code = string("#if ! defined(CONFIG_MARKERS)\n")
397 + string("#error \"Need CONFIG_MARKERS!\"\n")
398 + string("#endif\n")
399 + string("#include <linux/marker.h>\n");
400
401 s.embeds.push_back(ec);
402 }
403 s.mark_derived_probes->enroll (this);
ca6d3b0f 404 this->group = s.mark_derived_probes;
dd0e4fa7
JS
405}
406
407
408void
409mark_derived_probe::print_dupe_stamp (ostream& o)
410{
411 if (target_symbol_seen)
412 for (unsigned i = 0; i < mark_args.size(); i++)
413 o << mark_args[i]->c_type << " __mark_arg" << (i+1) << endl;
414}
415
416
dd0e4fa7
JS
417void
418mark_derived_probe::initialize_probe_context_vars (translator_output* o)
419{
420 // If we haven't seen a target symbol for this probe, quit.
421 if (! target_symbol_seen)
422 return;
423
424 bool deref_fault_needed = false;
425 for (unsigned i = 0; i < mark_args.size(); i++)
426 {
3acf16ff
JS
427 string localname = "l->" +
428 sess.up->c_localname("__mark_arg" + lex_cast(i+1));
dd0e4fa7
JS
429 switch (mark_args[i]->stp_type)
430 {
431 case pe_long:
6dceb5c9 432 o->newline() << localname << " = va_arg(*c->ips.kmark.mark_va_list, "
dd0e4fa7
JS
433 << mark_args[i]->c_type << ");";
434 break;
435
436 case pe_string:
437 // We're assuming that this is a kernel string (this code is
438 // basically the guts of kernel_string), not a user string.
439 o->newline() << "{ " << mark_args[i]->c_type
6dceb5c9 440 << " tmp_str = va_arg(*c->ips.kmark.mark_va_list, "
dd0e4fa7 441 << mark_args[i]->c_type << ");";
f1e8e7e0 442 o->newline() << "kderef_string (" << localname
dd0e4fa7
JS
443 << ", tmp_str, MAXSTRINGLEN); }";
444 deref_fault_needed = true;
445 break;
446
447 default:
dc09353a 448 throw SEMANTIC_ERROR (_("cannot expand unknown type"));
dd0e4fa7
JS
449 break;
450 }
451 }
452 if (deref_fault_needed)
453 // Need to report errors?
454 o->newline() << "deref_fault: ;";
455}
456
457void
d0bfd2ac 458mark_derived_probe::getargs(std::list<std::string> &arg_set) const
dd0e4fa7 459{
b2017fdd
WH
460 //PR11761: hard-coded the basic variables
461 arg_set.push_back("$name:string");
462 arg_set.push_back("$format:string");
dd0e4fa7
JS
463 for (unsigned i = 0; i < mark_args.size(); i++)
464 {
aca66a36 465 string localname = "$arg" + lex_cast(i+1);
dd0e4fa7
JS
466 switch (mark_args[i]->stp_type)
467 {
468 case pe_long:
d0bfd2ac 469 arg_set.push_back(localname+":long");
dd0e4fa7
JS
470 break;
471 case pe_string:
d0bfd2ac 472 arg_set.push_back(localname+":string");
dd0e4fa7
JS
473 break;
474 default:
d0bfd2ac 475 arg_set.push_back(localname+":unknown");
dd0e4fa7
JS
476 break;
477 }
478 }
479}
480
481
482void
483mark_derived_probe_group::emit_module_decls (systemtap_session& s)
484{
485 if (probes.empty())
486 return;
487
488 s.op->newline() << "/* ---- marker probes ---- */";
489
490 s.op->newline() << "static struct stap_marker_probe {";
491 s.op->newline(1) << "const char * const name;";
492 s.op->newline() << "const char * const format;";
7c3e97f4 493 s.op->newline() << "const struct stap_probe * const probe;";
dd0e4fa7
JS
494 s.op->newline(-1) << "} stap_marker_probes [" << probes.size() << "] = {";
495 s.op->indent(1);
496 for (unsigned i=0; i < probes.size(); i++)
497 {
498 s.op->newline () << "{";
faea5e16
JS
499 s.op->line() << " .name=" << lex_cast_qstring(probes[i]->probe_name) << ",";
500 s.op->line() << " .format=" << lex_cast_qstring(probes[i]->probe_format) << ",";
501 s.op->line() << " .probe=" << common_probe_init (probes[i]) << ",";
dd0e4fa7
JS
502 s.op->line() << " },";
503 }
504 s.op->newline(-1) << "};";
505 s.op->newline();
506
507
508 // Emit the marker callback function
509 s.op->newline();
510 s.op->newline() << "static void enter_marker_probe (void *probe_data, void *call_data, const char *fmt, va_list *args) {";
511 s.op->newline(1) << "struct stap_marker_probe *smp = (struct stap_marker_probe *)probe_data;";
71db462b 512 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "smp->probe",
cda141c2 513 "stp_probe_type_marker");
6dceb5c9
MW
514 s.op->newline() << "c->ips.kmark.marker_name = smp->name;";
515 s.op->newline() << "c->ips.kmark.marker_format = smp->format;";
516 s.op->newline() << "c->ips.kmark.mark_va_list = args;";
26e63673 517 s.op->newline() << "(*smp->probe->ph) (c);";
6dceb5c9 518 s.op->newline() << "c->ips.kmark.mark_va_list = NULL;";
dd0e4fa7 519
ef1337ee 520 common_probe_entryfn_epilogue (s, true, otf_safe_context(s));
dd0e4fa7
JS
521 s.op->newline(-1) << "}";
522
523 return;
524}
525
526
527void
528mark_derived_probe_group::emit_module_init (systemtap_session &s)
529{
530 if (probes.size () == 0)
531 return;
532
533 s.op->newline() << "/* init marker probes */";
534 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
535 s.op->newline(1) << "struct stap_marker_probe *smp = &stap_marker_probes[i];";
26e63673 536 s.op->newline() << "probe_point = smp->probe->pp;";
dd0e4fa7
JS
537 s.op->newline() << "rc = marker_probe_register(smp->name, smp->format, enter_marker_probe, smp);";
538 s.op->newline() << "if (rc) {";
539 s.op->newline(1) << "for (j=i-1; j>=0; j--) {"; // partial rollback
540 s.op->newline(1) << "struct stap_marker_probe *smp2 = &stap_marker_probes[j];";
541 s.op->newline() << "marker_probe_unregister(smp2->name, enter_marker_probe, smp2);";
542 s.op->newline(-1) << "}";
543 s.op->newline() << "break;"; // don't attempt to register any more probes
544 s.op->newline(-1) << "}";
545 s.op->newline(-1) << "}"; // for loop
546}
547
548
549void
550mark_derived_probe_group::emit_module_exit (systemtap_session& s)
551{
552 if (probes.empty())
553 return;
554
555 s.op->newline() << "/* deregister marker probes */";
556 s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
557 s.op->newline(1) << "struct stap_marker_probe *smp = &stap_marker_probes[i];";
558 s.op->newline() << "marker_probe_unregister(smp->name, enter_marker_probe, smp);";
559 s.op->newline(-1) << "}"; // for loop
560}
561
562
563struct mark_builder: public derived_probe_builder
564{
565private:
566 bool cache_initialized;
567 typedef multimap<string, string> mark_cache_t;
568 typedef multimap<string, string>::const_iterator mark_cache_const_iterator_t;
569 typedef pair<mark_cache_const_iterator_t, mark_cache_const_iterator_t>
570 mark_cache_const_iterator_pair_t;
571 mark_cache_t mark_cache;
572
e3718b64
JL
573 string suggest_marks(systemtap_session& sess,
574 const string& mark);
575
dd0e4fa7
JS
576public:
577 mark_builder(): cache_initialized(false) {}
578
579 void build_no_more (systemtap_session &s)
580 {
581 if (! mark_cache.empty())
582 {
583 if (s.verbose > 3)
efee9a98 584 clog << _("mark_builder releasing cache") << endl;
dd0e4fa7
JS
585 mark_cache.clear();
586 }
587 }
588
589 void build(systemtap_session & sess,
590 probe * base,
591 probe_point * location,
592 literal_map_t const & parameters,
593 vector<derived_probe *> & finished_results);
594};
595
596
e3718b64
JL
597string
598mark_builder::suggest_marks(systemtap_session& sess,
599 const string& mark)
600{
601 if (mark.empty() || mark_cache.empty())
602 return "";
603
604 set<string> marks;
605
606 // Collect all markers from cache
607 for (mark_cache_const_iterator_t it = mark_cache.begin();
608 it != mark_cache.end(); it++)
609 marks.insert(it->first);
610
611 if (sess.verbose > 2)
612 clog << "suggesting from " << marks.size()
613 << " kernel marks" << endl;
614
615 if (marks.empty())
616 return "";
617
618 return levenshtein_suggest(mark, marks, 5); // print top 5 marks only
619}
620
dd0e4fa7
JS
621void
622mark_builder::build(systemtap_session & sess,
623 probe * base,
624 probe_point *loc,
625 literal_map_t const & parameters,
626 vector<derived_probe *> & finished_results)
627{
45a63356 628 interned_string mark_str_val;
dd0e4fa7 629 bool has_mark_str = get_param (parameters, TOK_MARK, mark_str_val);
45a63356 630 interned_string mark_format_val;
dd0e4fa7
JS
631 bool has_mark_format = get_param (parameters, TOK_FORMAT, mark_format_val);
632 assert (has_mark_str);
633 (void) has_mark_str;
634
635 if (! cache_initialized)
636 {
637 cache_initialized = true;
638 string module_markers_path = sess.kernel_build_tree + "/Module.markers";
639
640 ifstream module_markers;
641 module_markers.open(module_markers_path.c_str(), ifstream::in);
642 if (! module_markers)
643 {
644 if (sess.verbose>3)
efee9a98
LB
645 //TRANSLATORS: specific path cannot be opened
646 clog << module_markers_path << _(" cannot be opened: ")
dd0e4fa7
JS
647 << strerror(errno) << endl;
648 return;
649 }
650
651 string name, module, format;
652 do
653 {
654 module_markers >> name >> module;
655 getline(module_markers, format);
656
657 // trim leading whitespace
658 string::size_type notwhite = format.find_first_not_of(" \t");
659 format.erase(0, notwhite);
660
661 // If the format is empty, make sure we add back a space
662 // character, which is what MARK_NOARGS expands to.
663 if (format.length() == 0)
664 format = " ";
665
666 if (sess.verbose>3)
667 clog << "'" << name << "' '" << module << "' '" << format
668 << "'" << endl;
669
670 if (mark_cache.count(name) > 0)
671 {
672 // If we have 2 markers with the same we've got 2 cases:
673 // different format strings or duplicate format strings.
674 // If an existing marker in the cache doesn't have the
675 // same format string, add this marker.
676 mark_cache_const_iterator_pair_t ret;
677 mark_cache_const_iterator_t it;
678 bool matching_format_string = false;
679
680 ret = mark_cache.equal_range(name);
681 for (it = ret.first; it != ret.second; ++it)
682 {
683 if (format == it->second)
684 {
685 matching_format_string = true;
686 break;
687 }
688 }
689
690 if (! matching_format_string)
691 mark_cache.insert(pair<string,string>(name, format));
692 }
693 else
694 mark_cache.insert(pair<string,string>(name, format));
695 }
696 while (! module_markers.eof());
697 module_markers.close();
698 }
699
e3718b64
JL
700 unsigned results_pre = finished_results.size();
701
dd0e4fa7 702 // Search marker list for matching markers
7371cd19
JS
703 const string& str_val = mark_str_val;
704 const string& format_val = mark_format_val;
dd0e4fa7
JS
705 for (mark_cache_const_iterator_t it = mark_cache.begin();
706 it != mark_cache.end(); it++)
707 {
708 // Below, "rc" has negative polarity: zero iff matching.
7371cd19 709 int rc = fnmatch(str_val.c_str(), it->first.c_str(), 0);
dd0e4fa7
JS
710 if (! rc)
711 {
712 bool add_result = true;
713
714 // Match format strings (if the user specified one)
7371cd19 715 if (has_mark_format && fnmatch(format_val.c_str(),
dd0e4fa7
JS
716 it->second.c_str(), 0))
717 add_result = false;
718
719 if (add_result)
720 {
721 derived_probe *dp
722 = new mark_derived_probe (sess,
723 it->first, it->second,
724 base, loc);
725 finished_results.push_back (dp);
726 }
727 }
728 }
e3718b64 729
d2eaa03b
JL
730 if (results_pre == finished_results.size()
731 && !loc->from_globby_comp(TOK_MARK))
e3718b64
JL
732 {
733 string sugs = suggest_marks(sess, mark_str_val);
734 if (!sugs.empty())
735 throw SEMANTIC_ERROR (_NF("no match (similar mark: %s)",
736 "no match (similar marks: %s)",
737 sugs.find(',') == string::npos,
738 sugs.c_str()));
739 }
dd0e4fa7
JS
740}
741
742
743
744void
745register_tapset_mark(systemtap_session& s)
746{
747 match_node* root = s.pattern_root;
748 derived_probe_builder *builder = new mark_builder();
749
750 root = root->bind(TOK_KERNEL);
751 root = root->bind_str(TOK_MARK);
752
753 root->bind(builder);
754 root->bind_str(TOK_FORMAT)->bind(builder);
755}
756
757/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.219608 seconds and 5 git commands to generate.