Implement support for brackets in filter expressions
[lttng-tools.git] / src / lib / lttng-ctl / filter / filter-visitor-set-parent.c
1 /*
2 * filter-visitor-set-parent.c
3 *
4 * LTTng filter set parent 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 static
35 int update_child(struct filter_node *parent,
36 struct filter_node *old_child,
37 struct filter_node *new_child)
38 {
39 if (!parent) {
40 fprintf(stderr, "[error] %s: NULL parent\n", __func__);
41 return -EINVAL;
42 }
43
44 switch (parent->type) {
45 case NODE_UNKNOWN:
46 default:
47 fprintf(stderr, "[error] %s: unknown node type\n", __func__);
48 return -EINVAL;
49 case NODE_ROOT:
50 assert(parent->u.root.child == old_child);
51 parent->u.root.child = new_child;
52 break;
53 case NODE_EXPRESSION:
54 assert(parent->u.expression.type == AST_EXP_NESTED);
55 assert(parent->u.expression.u.child == old_child);
56 parent->u.expression.u.child = new_child;
57 break;
58 case NODE_OP:
59 assert(parent->u.op.lchild == old_child ||
60 parent->u.op.rchild == old_child);
61 if (parent->u.op.lchild == old_child)
62 parent->u.op.lchild = new_child;
63 else
64 parent->u.op.rchild = new_child;
65 break;
66 case NODE_UNARY_OP:
67 assert(parent->u.unary_op.child == old_child);
68 parent->u.unary_op.child = new_child;
69 break;
70 }
71 return 0;
72 }
73
74 static
75 int recursive_visit_set_parent(struct filter_node *node,
76 struct filter_node *parent)
77 {
78 int ret;
79
80 if (!node) {
81 fprintf(stderr, "[error] %s: NULL child\n", __func__);
82 return -EINVAL;
83 }
84 node->parent = parent;
85 switch (node->type) {
86 case NODE_UNKNOWN:
87 default:
88 fprintf(stderr, "[error] %s: unknown node type\n", __func__);
89 return -EINVAL;
90 case NODE_ROOT:
91 assert(parent == NULL);
92 return recursive_visit_set_parent(node->u.root.child, node);
93 case NODE_EXPRESSION:
94 switch (node->u.expression.type) {
95 case AST_EXP_UNKNOWN:
96 default:
97 fprintf(stderr, "[error] %s: unknown expression type\n", __func__);
98 return -EINVAL;
99 case AST_EXP_NESTED:
100 return recursive_visit_set_parent(node->u.expression.u.child, node);
101 case AST_EXP_IDENTIFIER: /* fall-through */
102 case AST_EXP_GLOBAL_IDENTIFIER:
103 {
104 struct filter_node *orig_node = node;
105
106 while (node->u.expression.prev) {
107 struct filter_node *prev;
108
109 prev = node->u.expression.prev;
110 if (prev->type != NODE_EXPRESSION ||
111 (prev->u.expression.type != AST_EXP_IDENTIFIER
112 && prev->u.expression.type != AST_EXP_GLOBAL_IDENTIFIER)) {
113 fprintf(stderr, "[error] %s: expecting identifier before link\n", __func__);
114 return -EINVAL;
115 }
116
117 prev->u.expression.next = node;
118 prev->u.expression.pre_op =
119 node->u.expression.post_op;
120 prev->parent = node->parent;
121 node = prev;
122 }
123 /* Set first child as forward */
124 ret = update_child(parent, orig_node, node);
125 if (ret)
126 return ret;
127 }
128 case AST_EXP_CONSTANT:
129 case AST_EXP_FLOAT_CONSTANT:
130 case AST_EXP_STRING:
131 break;
132 }
133 break;
134 case NODE_OP:
135 ret = recursive_visit_set_parent(node->u.op.lchild, node);
136 if (ret)
137 return ret;
138 return recursive_visit_set_parent(node->u.op.rchild, node);
139 case NODE_UNARY_OP:
140 return recursive_visit_set_parent(node->u.unary_op.child, node);
141 }
142 return 0;
143 }
144
145 LTTNG_HIDDEN
146 int filter_visitor_set_parent(struct filter_parser_ctx *ctx)
147 {
148 return recursive_visit_set_parent(&ctx->ast->root, NULL);
149 }
This page took 0.043488 seconds and 4 git commands to generate.