Implement support for brackets in filter expressions
[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 #include <common/macros.h>
33
34 #define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ## args)
35
36 static
37 int recursive_visit_print(struct filter_node *node, FILE *stream, int indent);
38
39 static
40 void print_tabs(FILE *fd, int depth)
41 {
42 int i;
43
44 for (i = 0; i < depth; i++)
45 fprintf(fd, "\t");
46 }
47
48 static
49 int recursive_visit_print_expression(struct filter_node *node,
50 FILE *stream, int indent)
51 {
52 struct filter_node *iter_node;
53
54 if (!node) {
55 fprintf(stderr, "[error] %s: NULL child\n", __func__);
56 return -EINVAL;
57 }
58 switch (node->u.expression.type) {
59 case AST_EXP_UNKNOWN:
60 default:
61 fprintf(stderr, "[error] %s: unknown expression\n", __func__);
62 return -EINVAL;
63 case AST_EXP_STRING:
64 print_tabs(stream, indent);
65 fprintf(stream, "<string value=\"%s\"/>\n",
66 node->u.expression.u.string);
67 break;
68 case AST_EXP_CONSTANT:
69 print_tabs(stream, indent);
70 fprintf(stream, "<constant value=\"%" PRIu64 "\"/>\n",
71 node->u.expression.u.constant);
72 break;
73 case AST_EXP_FLOAT_CONSTANT:
74 print_tabs(stream, indent);
75 fprintf(stream, "<float_constant value=\"%lg\"/>\n",
76 node->u.expression.u.float_constant);
77 break;
78 case AST_EXP_IDENTIFIER: /* fall-through */
79 case AST_EXP_GLOBAL_IDENTIFIER:
80 print_tabs(stream, indent);
81 fprintf(stream, "<%s value=\"%s\"/>\n",
82 node->u.expression.type == AST_EXP_IDENTIFIER ?
83 "identifier" : "global_identifier",
84 node->u.expression.u.identifier);
85 iter_node = node->u.expression.next;
86 while (iter_node) {
87 print_tabs(stream, indent);
88 fprintf(stream, "<bracket>\n");
89 if (recursive_visit_print_expression(iter_node,
90 stream, indent + 1)) {
91 return -EINVAL;
92 }
93 print_tabs(stream, indent);
94 fprintf(stream, "</bracket>\n");
95 iter_node = iter_node->u.expression.next;
96
97 }
98 break;
99 case AST_EXP_NESTED:
100 return recursive_visit_print(node->u.expression.u.child,
101 stream, indent + 1);
102 }
103 return 0;
104 }
105
106
107 static
108 int recursive_visit_print(struct filter_node *node, FILE *stream, int indent)
109 {
110 int ret;
111
112 if (!node) {
113 fprintf(stderr, "[error] %s: NULL child\n", __func__);
114 return -EINVAL;
115 }
116 switch (node->type) {
117 case NODE_UNKNOWN:
118 default:
119 fprintf(stderr, "[error] %s: unknown node type\n", __func__);
120 return -EINVAL;
121 case NODE_ROOT:
122 print_tabs(stream, indent);
123 fprintf(stream, "<root>\n");
124 ret = recursive_visit_print(node->u.root.child, stream,
125 indent + 1);
126 print_tabs(stream, indent);
127 fprintf(stream, "</root>\n");
128 return ret;
129 case NODE_EXPRESSION:
130 print_tabs(stream, indent);
131 fprintf(stream, "<expression>\n");
132 ret = recursive_visit_print_expression(node, stream,
133 indent + 1);
134 print_tabs(stream, indent);
135 fprintf(stream, "</expression>\n");
136 return ret;
137 case NODE_OP:
138 print_tabs(stream, indent);
139 fprintf(stream, "<op type=");
140 switch (node->u.op.type) {
141 case AST_OP_UNKNOWN:
142 default:
143 fprintf(stderr, "[error] %s: unknown op\n", __func__);
144 return -EINVAL;
145 case AST_OP_MUL:
146 fprintf(stream, "\"*\"");
147 break;
148 case AST_OP_DIV:
149 fprintf(stream, "\"/\"");
150 break;
151 case AST_OP_MOD:
152 fprintf(stream, "\"%%\"");
153 break;
154 case AST_OP_PLUS:
155 fprintf(stream, "\"+\"");
156 break;
157 case AST_OP_MINUS:
158 fprintf(stream, "\"-\"");
159 break;
160 case AST_OP_RSHIFT:
161 fprintf(stream, "\">>\"");
162 break;
163 case AST_OP_LSHIFT:
164 fprintf(stream, "\"<<\"");
165 break;
166 case AST_OP_AND:
167 fprintf(stream, "\"&&\"");
168 break;
169 case AST_OP_OR:
170 fprintf(stream, "\"||\"");
171 break;
172 case AST_OP_BIN_AND:
173 fprintf(stream, "\"&\"");
174 break;
175 case AST_OP_BIN_OR:
176 fprintf(stream, "\"|\"");
177 break;
178 case AST_OP_BIN_XOR:
179 fprintf(stream, "\"^\"");
180 break;
181
182 case AST_OP_EQ:
183 fprintf(stream, "\"==\"");
184 break;
185 case AST_OP_NE:
186 fprintf(stream, "\"!=\"");
187 break;
188 case AST_OP_GT:
189 fprintf(stream, "\">\"");
190 break;
191 case AST_OP_LT:
192 fprintf(stream, "\"<\"");
193 break;
194 case AST_OP_GE:
195 fprintf(stream, "\">=\"");
196 break;
197 case AST_OP_LE:
198 fprintf(stream, "\"<=\"");
199 break;
200 }
201 fprintf(stream, ">\n");
202 ret = recursive_visit_print(node->u.op.lchild,
203 stream, indent + 1);
204 if (ret)
205 return ret;
206 ret = recursive_visit_print(node->u.op.rchild,
207 stream, indent + 1);
208 if (ret)
209 return ret;
210 print_tabs(stream, indent);
211 fprintf(stream, "</op>\n");
212 return ret;
213 case NODE_UNARY_OP:
214 print_tabs(stream, indent);
215 fprintf(stream, "<unary_op type=");
216 switch (node->u.unary_op.type) {
217 case AST_UNARY_UNKNOWN:
218 default:
219 fprintf(stderr, "[error] %s: unknown unary_op\n", __func__);
220 return -EINVAL;
221 case AST_UNARY_PLUS:
222 fprintf(stream, "\"+\"");
223 break;
224 case AST_UNARY_MINUS:
225 fprintf(stream, "\"-\"");
226 break;
227 case AST_UNARY_NOT:
228 fprintf(stream, "\"!\"");
229 break;
230 case AST_UNARY_BIN_NOT:
231 fprintf(stream, "\"~\"");
232 break;
233 }
234 fprintf(stream, ">\n");
235 ret = recursive_visit_print(node->u.unary_op.child,
236 stream, indent + 1);
237 print_tabs(stream, indent);
238 fprintf(stream, "</unary_op>\n");
239 return ret;
240 }
241 return 0;
242 }
243
244 LTTNG_HIDDEN
245 int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream,
246 int indent)
247 {
248 return recursive_visit_print(&ctx->ast->root, stream, indent);
249 }
This page took 0.050781 seconds and 4 git commands to generate.