]> sourceware.org Git - systemtap.git/blob - stapregex.cxx
Define __NR_epoll_wait if not defined (PR17462)
[systemtap.git] / stapregex.cxx
1 // -*- C++ -*-
2 // Copyright (C) 2012-2013 Red Hat Inc.
3 //
4 // This file is part of systemtap, and is free software. You can
5 // redistribute it and/or modify it under the terms of the GNU General
6 // Public License (GPL); either version 2, or (at your option) any
7 // later version.
8 //
9 // ---
10 //
11 // This file incorporates code from the re2c project; please see
12 // the file README.stapregex for details.
13
14 #include "util.h"
15 #include "translator-output.h"
16
17 #include "session.h"
18 #include "staptree.h" // needed to use semantic_error
19
20 #include <iostream>
21 #include <cstdlib>
22 #include <string>
23 #include <algorithm>
24
25 using namespace std;
26
27 #include "stapregex-parse.h"
28 #include "stapregex-tree.h"
29 #include "stapregex-dfa.h"
30 #include "stapregex.h"
31
32 using namespace stapregex;
33
34 // ------------------------------------------------------------------------
35
36 stapdfa *
37 regex_to_stapdfa (systemtap_session *s, const string& input, const token *tok)
38 {
39 // Tags are disabled when not used, for the extra bit of efficiency.
40 bool do_tag = s->need_tagged_dfa;
41
42 if (s->dfas.find(input) != s->dfas.end())
43 return s->dfas[input];
44
45 stapdfa *dfa = new stapdfa ("__stp_dfa" + lex_cast(s->dfa_counter++), input, tok, true, do_tag);
46
47 // Update required size of subexpression-tracking data structure:
48 s->dfa_maxstate = max(s->dfa_maxstate, dfa->num_states());
49 s->dfa_maxtag = max(s->dfa_maxtag, dfa->num_tags());
50
51 s->dfas[input] = dfa;
52 return dfa;
53 }
54
55 // ------------------------------------------------------------------------
56
57 stapdfa::stapdfa (const string& func_name, const string& re,
58 const token *tok, bool do_unescape, bool do_tag)
59 : func_name(func_name), orig_input(re), tok(tok), do_tag(do_tag)
60 {
61 try
62 {
63 regex_parser p(re, do_unescape);
64 ast = p.parse (do_tag);
65 content = stapregex_compile (ast, "goto match_success;", "goto match_fail;");
66 }
67 catch (const regex_error &e)
68 {
69 if (e.pos >= 0)
70 throw SEMANTIC_ERROR(_F("regex compilation error (at position %d): %s",
71 e.pos, e.what()), tok);
72 else
73 throw SEMANTIC_ERROR(_F("regex compilation error: %s", e.what()), tok);
74 }
75 }
76
77 stapdfa::~stapdfa ()
78 {
79 delete content;
80 delete ast;
81 }
82
83 unsigned
84 stapdfa::num_states () const
85 {
86 return content->nstates;
87 }
88
89 unsigned
90 stapdfa::num_tags () const
91 {
92 return content->ntags;
93 }
94
95 void
96 stapdfa::emit_declaration (translator_output *o) const
97 {
98 o->newline() << "// DFA for \"" << orig_input << "\"";
99 o->newline() << "int " << func_name << " (struct context * __restrict__ c, const char *str) {";
100 o->indent(1);
101
102 // Emit a SystemTap function body (as if an embedded-C snippet) that
103 // invokes the DFA on the argument named 'str', saves a boolean
104 // value (0 or 1) in the return value, and updates the probe
105 // context's match object with subexpression contents as
106 // appropriate.
107
108 o->newline() << "const char *cur = str;";
109 o->newline() << "const char *mar;";
110
111 if (do_tag)
112 o->newline() << "#define YYTAG(t,s,n) {c->last_match.tag_states[(t)][(s)] = (n);}";
113 o->newline() << "#define YYCTYPE char";
114 o->newline() << "#define YYCURSOR cur";
115 o->newline() << "#define YYLIMIT cur";
116 o->newline() << "#define YYMARKER mar";
117 // XXX: YYFILL is disabled as it doesn't play well with ^
118 o->newline();
119
120 try
121 {
122 content->emit(o);
123 }
124 catch (const regex_error &e)
125 {
126 if (e.pos >= 0)
127 throw SEMANTIC_ERROR(_F("regex compilation error (at position %d): %s",
128 e.pos, e.what()), tok);
129 else
130 throw SEMANTIC_ERROR(_F("regex compilation error: %s", e.what()), tok);
131 }
132
133 o->newline() << "#undef YYCTYPE";
134 o->newline() << "#undef YYCURSOR";
135 o->newline() << "#undef YYLIMIT";
136 o->newline() << "#undef YYMARKER";
137
138 o->newline() << "match_success:";
139 if (do_tag)
140 {
141 o->newline() << "strlcpy (c->last_match.matched_str, str, MAXSTRINGLEN);";
142 o->newline() << "c->last_match.result = 1";
143 content->emit_tagsave(o, "c->last_match.tag_states", "c->last_match.tag_vals", "c->last_match.num_final_tags");
144 }
145 o->newline() << "return 1;";
146
147 o->newline() << "match_fail:";
148 if (do_tag)
149 {
150 o->newline() << "strlcpy (c->last_match.matched_str, str, MAXSTRINGLEN);";
151 o->newline() << "c->last_match.result = 0;";
152 }
153 o->newline() << "return 0;";
154
155 o->newline(-1) << "}";
156 }
157
158 void
159 stapdfa::emit_matchop_start (translator_output *o) const
160 {
161 o->line() << "(" << func_name << "(c, ("; // XXX: assumes context is available
162 }
163
164 void
165 stapdfa::emit_matchop_end (translator_output *o) const
166 {
167 o->line() << ")))";
168 }
169
170 void
171 stapdfa::print (std::ostream& o) const
172 {
173 translator_output to(o); print(&to);
174 }
175
176 void
177 stapdfa::print (translator_output *o) const
178 {
179 o->line() << "STAPDFA (" << func_name << ", \"" << orig_input << "\") {";
180 content->print(o);
181 o->newline(-1) << "}";
182 }
183
184 std::ostream&
185 operator << (std::ostream &o, const stapdfa& d)
186 {
187 d.print (o);
188 return o;
189 }
190
191 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.044442 seconds and 5 git commands to generate.