Commit | Line | Data |
---|---|---|
953192ba MD |
1 | /* |
2 | * filter-visitor-xml.c | |
3 | * | |
4 | * LTTng filter XML pretty printer visitor | |
5 | * | |
ab5be9fa | 6 | * Copyright 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
953192ba | 7 | * |
ab5be9fa | 8 | * SPDX-License-Identifier: LGPL-2.1-only |
953192ba | 9 | * |
953192ba MD |
10 | */ |
11 | ||
c9e313bc | 12 | #include "filter-ast.hpp" |
348ddc5c | 13 | #include "filter-parser.hpp" |
953192ba | 14 | |
c9e313bc SM |
15 | #include <common/compat/errno.hpp> |
16 | #include <common/macros.hpp> | |
a187da1a | 17 | |
28ab034a JG |
18 | #include <inttypes.h> |
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <unistd.h> | |
953192ba | 23 | |
28ab034a | 24 | #define fprintf_dbg(fd, fmt, args...) fprintf(fd, "%s: " fmt, __func__, ##args) |
953192ba | 25 | |
28ab034a JG |
26 | static int recursive_visit_print(struct filter_node *node, FILE *stream, int indent); |
27 | ||
28 | static void print_tabs(FILE *fd, int depth) | |
953192ba MD |
29 | { |
30 | int i; | |
31 | ||
32 | for (i = 0; i < depth; i++) | |
33 | fprintf(fd, "\t"); | |
34 | } | |
35 | ||
28ab034a | 36 | static int recursive_visit_print_expression(struct filter_node *node, FILE *stream, int indent) |
953192ba | 37 | { |
661dfdd1 MD |
38 | struct filter_node *iter_node; |
39 | ||
953192ba MD |
40 | if (!node) { |
41 | fprintf(stderr, "[error] %s: NULL child\n", __func__); | |
42 | return -EINVAL; | |
43 | } | |
44 | switch (node->u.expression.type) { | |
45 | case AST_EXP_UNKNOWN: | |
46 | default: | |
47 | fprintf(stderr, "[error] %s: unknown expression\n", __func__); | |
48 | return -EINVAL; | |
49 | case AST_EXP_STRING: | |
50 | print_tabs(stream, indent); | |
28ab034a | 51 | fprintf(stream, "<string value=\"%s\"/>\n", node->u.expression.u.string); |
953192ba MD |
52 | break; |
53 | case AST_EXP_CONSTANT: | |
54 | print_tabs(stream, indent); | |
28ab034a JG |
55 | fprintf(stream, |
56 | "<constant value=\"%" PRIu64 "\"/>\n", | |
953192ba MD |
57 | node->u.expression.u.constant); |
58 | break; | |
e90d8561 MD |
59 | case AST_EXP_FLOAT_CONSTANT: |
60 | print_tabs(stream, indent); | |
28ab034a JG |
61 | fprintf(stream, |
62 | "<float_constant value=\"%lg\"/>\n", | |
e90d8561 MD |
63 | node->u.expression.u.float_constant); |
64 | break; | |
28ab034a | 65 | case AST_EXP_IDENTIFIER: /* fall-through */ |
586dc72f | 66 | case AST_EXP_GLOBAL_IDENTIFIER: |
953192ba | 67 | print_tabs(stream, indent); |
28ab034a JG |
68 | fprintf(stream, |
69 | "<%s value=\"%s\"/>\n", | |
70 | node->u.expression.type == AST_EXP_IDENTIFIER ? "identifier" : | |
71 | "global_identifier", | |
953192ba | 72 | node->u.expression.u.identifier); |
661dfdd1 MD |
73 | iter_node = node->u.expression.next; |
74 | while (iter_node) { | |
953192ba | 75 | print_tabs(stream, indent); |
661dfdd1 | 76 | fprintf(stream, "<bracket>\n"); |
28ab034a | 77 | if (recursive_visit_print_expression(iter_node, stream, indent + 1)) { |
953192ba MD |
78 | return -EINVAL; |
79 | } | |
953192ba | 80 | print_tabs(stream, indent); |
661dfdd1 MD |
81 | fprintf(stream, "</bracket>\n"); |
82 | iter_node = iter_node->u.expression.next; | |
953192ba MD |
83 | } |
84 | break; | |
85 | case AST_EXP_NESTED: | |
28ab034a | 86 | return recursive_visit_print(node->u.expression.u.child, stream, indent + 1); |
953192ba MD |
87 | } |
88 | return 0; | |
89 | } | |
90 | ||
28ab034a | 91 | static int recursive_visit_print(struct filter_node *node, FILE *stream, int indent) |
953192ba MD |
92 | { |
93 | int ret; | |
94 | ||
95 | if (!node) { | |
96 | fprintf(stderr, "[error] %s: NULL child\n", __func__); | |
97 | return -EINVAL; | |
98 | } | |
99 | switch (node->type) { | |
100 | case NODE_UNKNOWN: | |
101 | default: | |
102 | fprintf(stderr, "[error] %s: unknown node type\n", __func__); | |
103 | return -EINVAL; | |
104 | case NODE_ROOT: | |
105 | print_tabs(stream, indent); | |
106 | fprintf(stream, "<root>\n"); | |
28ab034a | 107 | ret = recursive_visit_print(node->u.root.child, stream, indent + 1); |
953192ba MD |
108 | print_tabs(stream, indent); |
109 | fprintf(stream, "</root>\n"); | |
110 | return ret; | |
111 | case NODE_EXPRESSION: | |
112 | print_tabs(stream, indent); | |
113 | fprintf(stream, "<expression>\n"); | |
28ab034a | 114 | ret = recursive_visit_print_expression(node, stream, indent + 1); |
953192ba MD |
115 | print_tabs(stream, indent); |
116 | fprintf(stream, "</expression>\n"); | |
117 | return ret; | |
118 | case NODE_OP: | |
119 | print_tabs(stream, indent); | |
120 | fprintf(stream, "<op type="); | |
121 | switch (node->u.op.type) { | |
122 | case AST_OP_UNKNOWN: | |
123 | default: | |
124 | fprintf(stderr, "[error] %s: unknown op\n", __func__); | |
125 | return -EINVAL; | |
126 | case AST_OP_MUL: | |
127 | fprintf(stream, "\"*\""); | |
128 | break; | |
129 | case AST_OP_DIV: | |
130 | fprintf(stream, "\"/\""); | |
131 | break; | |
132 | case AST_OP_MOD: | |
133 | fprintf(stream, "\"%%\""); | |
134 | break; | |
135 | case AST_OP_PLUS: | |
136 | fprintf(stream, "\"+\""); | |
137 | break; | |
138 | case AST_OP_MINUS: | |
139 | fprintf(stream, "\"-\""); | |
140 | break; | |
116d3c01 | 141 | case AST_OP_BIT_RSHIFT: |
953192ba MD |
142 | fprintf(stream, "\">>\""); |
143 | break; | |
116d3c01 | 144 | case AST_OP_BIT_LSHIFT: |
953192ba MD |
145 | fprintf(stream, "\"<<\""); |
146 | break; | |
147 | case AST_OP_AND: | |
148 | fprintf(stream, "\"&&\""); | |
149 | break; | |
150 | case AST_OP_OR: | |
151 | fprintf(stream, "\"||\""); | |
152 | break; | |
bff988fa | 153 | case AST_OP_BIT_AND: |
953192ba MD |
154 | fprintf(stream, "\"&\""); |
155 | break; | |
bff988fa | 156 | case AST_OP_BIT_OR: |
953192ba MD |
157 | fprintf(stream, "\"|\""); |
158 | break; | |
bff988fa | 159 | case AST_OP_BIT_XOR: |
953192ba MD |
160 | fprintf(stream, "\"^\""); |
161 | break; | |
162 | ||
163 | case AST_OP_EQ: | |
164 | fprintf(stream, "\"==\""); | |
165 | break; | |
166 | case AST_OP_NE: | |
167 | fprintf(stream, "\"!=\""); | |
168 | break; | |
169 | case AST_OP_GT: | |
170 | fprintf(stream, "\">\""); | |
171 | break; | |
172 | case AST_OP_LT: | |
173 | fprintf(stream, "\"<\""); | |
174 | break; | |
175 | case AST_OP_GE: | |
176 | fprintf(stream, "\">=\""); | |
177 | break; | |
178 | case AST_OP_LE: | |
179 | fprintf(stream, "\"<=\""); | |
180 | break; | |
181 | } | |
182 | fprintf(stream, ">\n"); | |
28ab034a | 183 | ret = recursive_visit_print(node->u.op.lchild, stream, indent + 1); |
953192ba MD |
184 | if (ret) |
185 | return ret; | |
28ab034a | 186 | ret = recursive_visit_print(node->u.op.rchild, stream, indent + 1); |
953192ba MD |
187 | if (ret) |
188 | return ret; | |
189 | print_tabs(stream, indent); | |
190 | fprintf(stream, "</op>\n"); | |
191 | return ret; | |
192 | case NODE_UNARY_OP: | |
193 | print_tabs(stream, indent); | |
194 | fprintf(stream, "<unary_op type="); | |
195 | switch (node->u.unary_op.type) { | |
196 | case AST_UNARY_UNKNOWN: | |
197 | default: | |
198 | fprintf(stderr, "[error] %s: unknown unary_op\n", __func__); | |
199 | return -EINVAL; | |
200 | case AST_UNARY_PLUS: | |
201 | fprintf(stream, "\"+\""); | |
202 | break; | |
203 | case AST_UNARY_MINUS: | |
204 | fprintf(stream, "\"-\""); | |
205 | break; | |
206 | case AST_UNARY_NOT: | |
207 | fprintf(stream, "\"!\""); | |
208 | break; | |
bff988fa | 209 | case AST_UNARY_BIT_NOT: |
d804b36b CB |
210 | fprintf(stream, "\"~\""); |
211 | break; | |
953192ba MD |
212 | } |
213 | fprintf(stream, ">\n"); | |
28ab034a | 214 | ret = recursive_visit_print(node->u.unary_op.child, stream, indent + 1); |
953192ba MD |
215 | print_tabs(stream, indent); |
216 | fprintf(stream, "</unary_op>\n"); | |
217 | return ret; | |
218 | } | |
219 | return 0; | |
220 | } | |
221 | ||
28ab034a | 222 | int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream, int indent) |
953192ba MD |
223 | { |
224 | return recursive_visit_print(&ctx->ast->root, stream, indent); | |
225 | } |