1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2005 Michel Dagenais
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 consist in AND, OR and NOT nested expressions, forming a tree with
21 simple relations as leaves. The simple relations test is a field
22 in an event is equal, not equal, smaller, smaller or equal, larger, or
23 larger or equal to a specified value.
28 * - should the filter be implemented as a module
29 * - should all the structures and field types be associated with GQuarks
32 #include <lttv/filter.h>
39 simple expr [ op expr ]
41 read_simple_expression
42 read_field_path [ rel value ]
45 read_field_component [. field path]
54 path(component...) -> field
58 * Parse through filtering field hierarchy as specified
59 * by user. This function compares each value to
60 * predetermined quarks
61 * @param fp The field path list
62 * @return success/failure of operation
65 parse_field_path(GList
* fp
) {
67 GString
* f
= g_list_first(fp
)->data
;
69 switch(g_quark_try_string(f
->str
)) {
70 // case LTTV_FILTER_TRACE:
73 // case LTTV_FILTER_TRACEFILE:
76 // case LTTV_FILTER_TRACESET:
79 // case LTTV_FILTER_STATE:
82 // case LTTV_FILTER_EVENT:
85 default: /* Quark value unrecognized or equal to 0 */
86 g_warning("Unrecognized field in filter string");
93 * Add an filtering option to the current tree
94 * @param expression Current expression to parse
95 * @return success/failure of operation
98 parse_simple_expression(GString
* expression
) {
108 * Creates a new lttv_filter
109 * @param expression filtering options string
110 * @param t pointer to the current LttvTrace
111 * @return the current lttv_filter or NULL if error
114 lttv_filter_new(char *expression
, LttvTraceState
*tcs
) {
116 g_print("filter::lttv_filter_new()\n"); /* debug */
120 p
=0, /* parenthesis nesting value */
121 b
=0; /* current breakpoint in expression string */
123 LTTV_FILTER_EVENT
= g_quark_from_string("event");
124 LTTV_FILTER_TRACE
= g_quark_from_string("trace");
125 LTTV_FILTER_TRACESET
= g_quark_from_string("traceset");
126 LTTV_FILTER_STATE
= g_quark_from_string("state");
127 LTTV_FILTER_TRACEFILE
= g_quark_from_string("tracefile");
129 gpointer tree
= NULL
;
131 /* temporary values */
132 GString
*a_field_component
= g_string_new("");
133 GList
*a_field_path
= NULL
;
134 lttv_simple_expression a_simple_expression
;
137 * 1. parse expression
138 * 2. construct binary tree
139 * 3. return corresponding filter
143 * Binary tree memory allocation
144 * - based upon a preliminary block size
146 gulong size
= (strlen(expression
)/AVERAGE_EXPRESSION_LENGTH
)*MAX_FACTOR
;
147 tree
= g_malloc(size
*sizeof(lttv_filter_tree
));
150 * Parse entire expression and construct
151 * the binary tree. There are two steps
152 * in browsing that string
153 * 1. finding boolean ops ( &,|,^,! ) and parenthesis
154 * 2. finding simple expressions
155 * - field path ( separated by dots )
156 * - op ( >, <, =, >=, <=, !=)
157 * - value ( integer, string ... )
158 * To spare computing time, the whole
159 * string is parsed in this loop for a
160 * O(n) complexity order.
162 for(i
=0;i
<strlen(expression
);i
++) {
163 g_print("%s\n",a_field_component
->str
);
164 switch(expression
[i
]) {
171 g_list_append( a_field_path
, a_field_component
);
172 a_field_component
= g_string_new("");
174 case '!': /* not, or not equal (math op) */
175 if(expression
[i
+1] == '=') { /* != */
176 a_simple_expression
.op
= LTTV_FIELD_NE
;
179 g_print("%s\n",a_field_component
);
180 current_option
= g_string_new("");
183 case '(': /* start of parenthesis */
184 p
++; /* incrementing parenthesis nesting value */
186 case ')': /* end of parenthesis */
187 p
--; /* decrementing parenthesis nesting value */
191 * mathematic operators
193 case '<': /* lower, lower or equal */
194 if(expression
[i
+1] == '=') { /* <= */
196 a_simple_expression
.op
= LTTV_FIELD_LE
;
197 } else a_simple_expression
.op
= LTTV_FIELD_LT
;
199 case '>': /* higher, higher or equal */
200 if(expression
[i
+1] == '=') { /* >= */
202 a_simple_expression
.op
= LTTV_FIELD_GE
;
203 } else a_simple_expression
.op
= LTTV_FIELD_GT
;
205 case '=': /* equal */
206 a_simple_expression
.op
= LTTV_FIELD_EQ
;
209 * Field concatening caracter
212 g_list_append( a_field_path
, a_field_component
);
213 a_field_component
= g_string_new("");
215 default: /* concatening current string */
216 g_string_append_c(current_option
,expression
[i
]);
223 g_warning("Wrong filtering options, the string\n\"%s\"\n\
224 is not valid due to parenthesis incorrect use",expression
);
230 * Apply the filter to a specific trace
231 * @param filter the current filter applied
232 * @param tracefile the trace to apply the filter to
233 * @return success/failure of operation
236 lttv_filter_tracefile(lttv_filter
*filter
, LttTracefile
*tracefile
) {
242 char *f_name, *e_name;
252 GString *fe_name = g_string_new("");
254 nb = ltt_trace_eventtype_number(tcs->parent.t);
255 g_print("NB:%i\n",nb);
256 for(i = 0 ; i < nb ; i++) {
257 et = ltt_trace_eventtype_get(tcs->parent.t, i);
258 e_name = ltt_eventtype_name(et);
259 f_name = ltt_facility_name(ltt_eventtype_facility(et));
260 g_string_printf(fe_name, "%s.%s", f_name, e_name);
261 g_print("facility:%s and event:%s\n",f_name,e_name);
267 * Apply the filter to a specific event
268 * @param filter the current filter applied
269 * @param event the event to apply the filter to
270 * @return success/failure of operation
273 lttv_filter_event(lttv_filter
*filter
, LttEvent
*event
) {