Fix: Possible memory leaks when creating filter IR root node
[lttng-tools.git] / src / lib / lttng-ctl / filter / filter-visitor-xml.c
1 /*
2 * filter-visitor-xml.c
3 *
4 * LTTng filter XML pretty printer visitor
5 *
6 * Copyright 2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License, version 2.1 only,
10 * as published by the Free Software Foundation.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <assert.h>
27 #include <errno.h>
28 #include <inttypes.h>
29 #include "filter-ast.h"
30 #include "filter-parser.h"
31
32 #define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args)
33
34 static
35 int recursive_visit_print(struct filter_node *node, FILE *stream, int indent);
36
37 static
38 void print_tabs(FILE *fd, int depth)
39 {
40 int i;
41
42 for (i = 0; i < depth; i++)
43 fprintf(fd, "\t");
44 }
45
46 static
47 int recursive_visit_print_expression(struct filter_node *node,
48 FILE *stream, int indent)
49 {
50 if (!node) {
51 fprintf(stderr, "[error] %s: NULL child\n", __func__);
52 return -EINVAL;
53 }
54 switch (node->u.expression.type) {
55 case AST_EXP_UNKNOWN:
56 default:
57 fprintf(stderr, "[error] %s: unknown expression\n", __func__);
58 return -EINVAL;
59 case AST_EXP_STRING:
60 print_tabs(stream, indent);
61 fprintf(stream, "<string value=\"%s\"/>\n",
62 node->u.expression.u.string);
63 break;
64 case AST_EXP_CONSTANT:
65 print_tabs(stream, indent);
66 fprintf(stream, "<constant value=\"%" PRIu64 "\"/>\n",
67 node->u.expression.u.constant);
68 break;
69 case AST_EXP_FLOAT_CONSTANT:
70 print_tabs(stream, indent);
71 fprintf(stream, "<float_constant value=\"%lg\"/>\n",
72 node->u.expression.u.float_constant);
73 break;
74 case AST_EXP_IDENTIFIER:
75 print_tabs(stream, indent);
76 fprintf(stream, "<identifier value=\"%s\"/>\n",
77 node->u.expression.u.identifier);
78 while (node->u.expression.next) {
79 print_tabs(stream, indent);
80 fprintf(stream, "<link type=\"");
81 switch (node->u.expression.pre_op) {
82 case AST_LINK_UNKNOWN:
83 default:
84 fprintf(stderr, "[error] %s: unknown link\n", __func__);
85 return -EINVAL;
86 case AST_LINK_DOT:
87 fprintf(stream, ".");
88 break;
89 case AST_LINK_RARROW:
90 fprintf(stream, "->");
91 break;
92 }
93 fprintf(stream, "\"/>\n");
94
95 node = node->u.expression.next;
96 if (node->type != NODE_EXPRESSION ||
97 node->u.expression.type != AST_EXP_IDENTIFIER) {
98 fprintf(stderr, "[error] %s: expecting identifier before link\n", __func__);
99 return -EINVAL;
100 }
101
102 print_tabs(stream, indent);
103 fprintf(stream, "<identifier value=\"%s\"/>\n",
104 node->u.expression.u.identifier);
105 }
106 break;
107 case AST_EXP_NESTED:
108 return recursive_visit_print(node->u.expression.u.child,
109 stream, indent + 1);
110 }
111 return 0;
112 }
113
114
115 static
116 int recursive_visit_print(struct filter_node *node, FILE *stream, int indent)
117 {
118 int ret;
119
120 if (!node) {
121 fprintf(stderr, "[error] %s: NULL child\n", __func__);
122 return -EINVAL;
123 }
124 switch (node->type) {
125 case NODE_UNKNOWN:
126 default:
127 fprintf(stderr, "[error] %s: unknown node type\n", __func__);
128 return -EINVAL;
129 case NODE_ROOT:
130 print_tabs(stream, indent);
131 fprintf(stream, "<root>\n");
132 ret = recursive_visit_print(node->u.root.child, stream,
133 indent + 1);
134 print_tabs(stream, indent);
135 fprintf(stream, "</root>\n");
136 return ret;
137 case NODE_EXPRESSION:
138 print_tabs(stream, indent);
139 fprintf(stream, "<expression>\n");
140 ret = recursive_visit_print_expression(node, stream,
141 indent + 1);
142 print_tabs(stream, indent);
143 fprintf(stream, "</expression>\n");
144 return ret;
145 case NODE_OP:
146 print_tabs(stream, indent);
147 fprintf(stream, "<op type=");
148 switch (node->u.op.type) {
149 case AST_OP_UNKNOWN:
150 default:
151 fprintf(stderr, "[error] %s: unknown op\n", __func__);
152 return -EINVAL;
153 case AST_OP_MUL:
154 fprintf(stream, "\"*\"");
155 break;
156 case AST_OP_DIV:
157 fprintf(stream, "\"/\"");
158 break;
159 case AST_OP_MOD:
160 fprintf(stream, "\"%%\"");
161 break;
162 case AST_OP_PLUS:
163 fprintf(stream, "\"+\"");
164 break;
165 case AST_OP_MINUS:
166 fprintf(stream, "\"-\"");
167 break;
168 case AST_OP_RSHIFT:
169 fprintf(stream, "\">>\"");
170 break;
171 case AST_OP_LSHIFT:
172 fprintf(stream, "\"<<\"");
173 break;
174 case AST_OP_AND:
175 fprintf(stream, "\"&&\"");
176 break;
177 case AST_OP_OR:
178 fprintf(stream, "\"||\"");
179 break;
180 case AST_OP_BIN_AND:
181 fprintf(stream, "\"&\"");
182 break;
183 case AST_OP_BIN_OR:
184 fprintf(stream, "\"|\"");
185 break;
186 case AST_OP_BIN_XOR:
187 fprintf(stream, "\"^\"");
188 break;
189
190 case AST_OP_EQ:
191 fprintf(stream, "\"==\"");
192 break;
193 case AST_OP_NE:
194 fprintf(stream, "\"!=\"");
195 break;
196 case AST_OP_GT:
197 fprintf(stream, "\">\"");
198 break;
199 case AST_OP_LT:
200 fprintf(stream, "\"<\"");
201 break;
202 case AST_OP_GE:
203 fprintf(stream, "\">=\"");
204 break;
205 case AST_OP_LE:
206 fprintf(stream, "\"<=\"");
207 break;
208 }
209 fprintf(stream, ">\n");
210 ret = recursive_visit_print(node->u.op.lchild,
211 stream, indent + 1);
212 if (ret)
213 return ret;
214 ret = recursive_visit_print(node->u.op.rchild,
215 stream, indent + 1);
216 if (ret)
217 return ret;
218 print_tabs(stream, indent);
219 fprintf(stream, "</op>\n");
220 return ret;
221 case NODE_UNARY_OP:
222 print_tabs(stream, indent);
223 fprintf(stream, "<unary_op type=");
224 switch (node->u.unary_op.type) {
225 case AST_UNARY_UNKNOWN:
226 default:
227 fprintf(stderr, "[error] %s: unknown unary_op\n", __func__);
228 return -EINVAL;
229 case AST_UNARY_PLUS:
230 fprintf(stream, "\"+\"");
231 break;
232 case AST_UNARY_MINUS:
233 fprintf(stream, "\"-\"");
234 break;
235 case AST_UNARY_NOT:
236 fprintf(stream, "\"!\"");
237 break;
238 }
239 fprintf(stream, ">\n");
240 ret = recursive_visit_print(node->u.unary_op.child,
241 stream, indent + 1);
242 print_tabs(stream, indent);
243 fprintf(stream, "</unary_op>\n");
244 return ret;
245 }
246 return 0;
247 }
248
249 __attribute__((visibility("hidden")))
250 int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream,
251 int indent)
252 {
253 return recursive_visit_print(&ctx->ast->root, stream, indent);
254 }
This page took 0.033888 seconds and 4 git commands to generate.