1 /*
2 * Copyright (c) 2015 PLUMgrid, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "printer.h"
18 #include "lexer.h"
19 #include "bcc_exception.h"
20
21 namespace ebpf {
22 namespace cc {
23
print_indent()24 void Printer::print_indent() {
25 fprintf(out_, "%*s", indent_, "");
26 }
27
visit_block_stmt_node(BlockStmtNode * n)28 StatusTuple Printer::visit_block_stmt_node(BlockStmtNode* n) {
29 fprintf(out_, "{\n");
30
31 if (!n->stmts_.empty()) {
32 ++indent_;
33 for (auto it = n->stmts_.begin(); it != n->stmts_.end(); ++it) {
34 print_indent();
35 TRY2((*it)->accept(this));
36 fprintf(out_, "\n");
37 }
38 --indent_;
39 }
40 fprintf(out_, "%*s}", indent_, "");
41 return StatusTuple(0);
42 }
43
visit_if_stmt_node(IfStmtNode * n)44 StatusTuple Printer::visit_if_stmt_node(IfStmtNode* n) {
45 fprintf(out_, "if ");
46 TRY2(n->cond_->accept(this));
47 fprintf(out_, " ");
48 TRY2(n->true_block_->accept(this));
49 if (n->false_block_) {
50 fprintf(out_, " else ");
51 TRY2(n->false_block_->accept(this));
52 }
53 return StatusTuple(0);
54 }
55
visit_onvalid_stmt_node(OnValidStmtNode * n)56 StatusTuple Printer::visit_onvalid_stmt_node(OnValidStmtNode* n) {
57 fprintf(out_, "if ");
58 TRY2(n->cond_->accept(this));
59 fprintf(out_, " ");
60 TRY2(n->block_->accept(this));
61 if (n->else_block_) {
62 fprintf(out_, " else ");
63 TRY2(n->else_block_->accept(this));
64 }
65 return StatusTuple(0);
66 }
67
visit_switch_stmt_node(SwitchStmtNode * n)68 StatusTuple Printer::visit_switch_stmt_node(SwitchStmtNode* n) {
69 fprintf(out_, "switch (");
70 TRY2(n->cond_->accept(this));
71 fprintf(out_, ") ");
72 TRY2(n->block_->accept(this));
73 return StatusTuple(0);
74 }
75
visit_case_stmt_node(CaseStmtNode * n)76 StatusTuple Printer::visit_case_stmt_node(CaseStmtNode* n) {
77 if (n->value_) {
78 fprintf(out_, "case ");
79 TRY2(n->value_->accept(this));
80 } else {
81 fprintf(out_, "default");
82 }
83 TRY2(n->block_->accept(this));
84 return StatusTuple(0);
85 }
86
visit_ident_expr_node(IdentExprNode * n)87 StatusTuple Printer::visit_ident_expr_node(IdentExprNode* n) {
88 if (n->scope_name_.size()) {
89 fprintf(out_, "%s::", n->scope_name_.c_str());
90 }
91 fprintf(out_, "%s", n->name_.c_str());
92 if (n->sub_name_.size()) {
93 fprintf(out_, ".%s", n->sub_name_.c_str());
94 }
95 return StatusTuple(0);
96 }
97
visit_assign_expr_node(AssignExprNode * n)98 StatusTuple Printer::visit_assign_expr_node(AssignExprNode* n) {
99 TRY2(n->lhs_->accept(this));
100 fprintf(out_, " = ");
101 TRY2(n->rhs_->accept(this));
102 return StatusTuple(0);
103 }
104
visit_packet_expr_node(PacketExprNode * n)105 StatusTuple Printer::visit_packet_expr_node(PacketExprNode* n) {
106 fprintf(out_, "$");
107 TRY2(n->id_->accept(this));
108 return StatusTuple(0);
109 }
110
visit_integer_expr_node(IntegerExprNode * n)111 StatusTuple Printer::visit_integer_expr_node(IntegerExprNode* n) {
112 fprintf(out_, "%s:%zu", n->val_.c_str(), n->bits_);
113 return StatusTuple(0);
114 }
115
visit_string_expr_node(StringExprNode * n)116 StatusTuple Printer::visit_string_expr_node(StringExprNode *n) {
117 fprintf(out_, "%s", n->val_.c_str());
118 return StatusTuple(0);
119 }
120
visit_binop_expr_node(BinopExprNode * n)121 StatusTuple Printer::visit_binop_expr_node(BinopExprNode* n) {
122 TRY2(n->lhs_->accept(this));
123 fprintf(out_, "%d", n->op_);
124 TRY2(n->rhs_->accept(this));
125 return StatusTuple(0);
126 }
127
visit_unop_expr_node(UnopExprNode * n)128 StatusTuple Printer::visit_unop_expr_node(UnopExprNode* n) {
129 const char* s = "";
130 switch (n->op_) {
131 case Tok::TNOT: s = "!"; break;
132 case Tok::TCMPL: s = "~"; break;
133 case Tok::TMOD: s = "%"; break;
134 default: {}
135 }
136 fprintf(out_, "%s", s);
137 TRY2(n->expr_->accept(this));
138 return StatusTuple(0);
139 }
140
visit_bitop_expr_node(BitopExprNode * n)141 StatusTuple Printer::visit_bitop_expr_node(BitopExprNode* n) {
142
143 return StatusTuple(0);
144 }
145
visit_return_expr_node(ReturnExprNode * n)146 StatusTuple Printer::visit_return_expr_node(ReturnExprNode* n) {
147 fprintf(out_, "return ");
148 TRY2(n->expr_->accept(this));
149 return StatusTuple(0);
150 }
151
visit_goto_expr_node(GotoExprNode * n)152 StatusTuple Printer::visit_goto_expr_node(GotoExprNode* n) {
153 const char* s = n->is_continue_ ? "continue " : "goto ";
154 fprintf(out_, "%s", s);
155 TRY2(n->id_->accept(this));
156 return StatusTuple(0);
157 }
158
visit_method_call_expr_node(MethodCallExprNode * n)159 StatusTuple Printer::visit_method_call_expr_node(MethodCallExprNode* n) {
160 TRY2(n->id_->accept(this));
161 fprintf(out_, "(");
162 for (auto it = n->args_.begin(); it != n->args_.end(); ++it) {
163 TRY2((*it)->accept(this));
164 if (it + 1 != n->args_.end()) {
165 fprintf(out_, ", ");
166 }
167 }
168 fprintf(out_, ")");
169 if (!n->block_->stmts_.empty()) {
170 fprintf(out_, " {\n");
171 ++indent_;
172 for (auto it = n->block_->stmts_.begin(); it != n->block_->stmts_.end(); ++it) {
173 print_indent();
174 TRY2((*it)->accept(this));
175 fprintf(out_, "\n");
176 }
177 --indent_;
178 fprintf(out_, "%*s}", indent_, "");
179 }
180 return StatusTuple(0);
181 }
182
visit_table_index_expr_node(TableIndexExprNode * n)183 StatusTuple Printer::visit_table_index_expr_node(TableIndexExprNode *n) {
184 fprintf(out_, "%s[", n->id_->c_str());
185 TRY2(n->index_->accept(this));
186 fprintf(out_, "]");
187 return StatusTuple(0);
188 }
189
visit_expr_stmt_node(ExprStmtNode * n)190 StatusTuple Printer::visit_expr_stmt_node(ExprStmtNode* n) {
191 TRY2(n->expr_->accept(this));
192 return StatusTuple(0);
193 }
194
visit_struct_variable_decl_stmt_node(StructVariableDeclStmtNode * n)195 StatusTuple Printer::visit_struct_variable_decl_stmt_node(StructVariableDeclStmtNode* n) {
196 fprintf(out_, "var ");
197 TRY2(n->struct_id_->accept(this));
198 fprintf(out_, " ");
199 TRY2(n->id_->accept(this));
200 if (!n->init_.empty()) {
201 fprintf(out_, "{");
202 for (auto it = n->init_.begin(); it != n->init_.end(); ++it) {
203 TRY2((*it)->accept(this));
204 if (it + 1 != n->init_.end()) {
205 fprintf(out_, ", ");
206 }
207 }
208 fprintf(out_, "}");
209 }
210 return StatusTuple(0);
211 }
212
visit_integer_variable_decl_stmt_node(IntegerVariableDeclStmtNode * n)213 StatusTuple Printer::visit_integer_variable_decl_stmt_node(IntegerVariableDeclStmtNode* n) {
214 fprintf(out_, "var ");
215 TRY2(n->id_->accept(this));
216 fprintf(out_, ":%zu", n->bit_width_);
217 if (!n->init_.empty()) {
218 fprintf(out_, "; ");
219 TRY2(n->init_[0]->accept(this));
220 }
221 return StatusTuple(0);
222 }
223
visit_struct_decl_stmt_node(StructDeclStmtNode * n)224 StatusTuple Printer::visit_struct_decl_stmt_node(StructDeclStmtNode* n) {
225 fprintf(out_, "struct ");
226 TRY2(n->id_->accept(this));
227 fprintf(out_, " {\n");
228 ++indent_;
229 for (auto it = n->stmts_.begin(); it != n->stmts_.end(); ++it) {
230 print_indent();
231 TRY2((*it)->accept(this));
232 fprintf(out_, "\n");
233 }
234 --indent_;
235 fprintf(out_, "%*s}", indent_, "");
236 return StatusTuple(0);
237 }
238
visit_state_decl_stmt_node(StateDeclStmtNode * n)239 StatusTuple Printer::visit_state_decl_stmt_node(StateDeclStmtNode* n) {
240 if (!n->id_) {
241 return StatusTuple(0);
242 }
243 fprintf(out_, "state ");
244 TRY2(n->id_->accept(this));
245 //if (!n->id2_) {
246 // fprintf(out_, ", * ");
247 //} else {
248 // fprintf(out_, ", ");
249 // TRY2(n->id2_->accept(this));
250 //}
251 //TRY2(n->block_->accept(this));
252 return StatusTuple(0);
253 }
254
visit_parser_state_stmt_node(ParserStateStmtNode * n)255 StatusTuple Printer::visit_parser_state_stmt_node(ParserStateStmtNode* n) {
256 return StatusTuple(0);
257 }
258
visit_match_decl_stmt_node(MatchDeclStmtNode * n)259 StatusTuple Printer::visit_match_decl_stmt_node(MatchDeclStmtNode* n) {
260 fprintf(out_, "on_match ");
261 TRY2(n->id_->accept(this));
262 fprintf(out_, " (");
263 for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
264 TRY2((*it)->accept(this));
265 if (it + 1 != n->formals_.end()) {
266 fprintf(out_, ", ");
267 }
268 }
269 fprintf(out_, ") ");
270 TRY2(n->block_->accept(this));
271 return StatusTuple(0);
272 }
273
visit_miss_decl_stmt_node(MissDeclStmtNode * n)274 StatusTuple Printer::visit_miss_decl_stmt_node(MissDeclStmtNode* n) {
275 fprintf(out_, "on_miss ");
276 TRY2(n->id_->accept(this));
277 fprintf(out_, " (");
278 for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
279 TRY2((*it)->accept(this));
280 if (it + 1 != n->formals_.end()) {
281 fprintf(out_, ", ");
282 }
283 }
284 fprintf(out_, ") ");
285 TRY2(n->block_->accept(this));
286 return StatusTuple(0);
287 }
288
visit_failure_decl_stmt_node(FailureDeclStmtNode * n)289 StatusTuple Printer::visit_failure_decl_stmt_node(FailureDeclStmtNode* n) {
290 fprintf(out_, "on_failure ");
291 TRY2(n->id_->accept(this));
292 fprintf(out_, " (");
293 for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
294 TRY2((*it)->accept(this));
295 if (it + 1 != n->formals_.end()) {
296 fprintf(out_, ", ");
297 }
298 }
299 fprintf(out_, ") ");
300 TRY2(n->block_->accept(this));
301 return StatusTuple(0);
302 }
303
visit_table_decl_stmt_node(TableDeclStmtNode * n)304 StatusTuple Printer::visit_table_decl_stmt_node(TableDeclStmtNode* n) {
305 TRY2(n->table_type_->accept(this));
306 fprintf(out_, "<");
307 for (auto it = n->templates_.begin(); it != n->templates_.end(); ++it) {
308 TRY2((*it)->accept(this));
309 if (it + 1 != n->templates_.end()) {
310 fprintf(out_, ", ");
311 }
312 }
313 fprintf(out_, "> ");
314 TRY2(n->id_->accept(this));
315 fprintf(out_, "(%zu)", n->size_);
316 return StatusTuple(0);
317 }
318
visit_func_decl_stmt_node(FuncDeclStmtNode * n)319 StatusTuple Printer::visit_func_decl_stmt_node(FuncDeclStmtNode *n) {
320 fprintf(out_, "func ");
321 TRY2(n->id_->accept(this));
322 fprintf(out_, "(");
323 for (auto it = n->formals_.begin(); it != n->formals_.end(); ++it) {
324 TRY2((*it)->accept(this));
325 if (it + 1 != n->formals_.end()) {
326 fprintf(out_, ", ");
327 }
328 }
329 fprintf(out_, ") ");
330 TRY2(n->block_->accept(this));
331 return StatusTuple(0);
332 }
333
334 } // namespace cc
335 } // namespace ebpf
336