filter core:
[lttv.git] / ltt / branches / poly / lttv / lttv / filter.c
CommitLineData
9c312311 1/* This file is part of the Linux Trace Toolkit viewer
0769c82f 2 * Copyright (C) 2003-2005 Michel Dagenais
9c312311 3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
31452f49 19/*
a4c292d4 20 read_token
48f6f3c2 21
a4c292d4 22 read_expression
23 ( read expr )
24 simple expr [ op expr ]
48f6f3c2 25
a4c292d4 26 read_simple_expression
27 read_field_path [ rel value ]
48f6f3c2 28
a4c292d4 29 read_field_path
30 read_field_component [. field path]
48f6f3c2 31
a4c292d4 32 read_field_component
33 name [ \[ value \] ]
48f6f3c2 34
a4c292d4 35 data struct:
36 and/or(left/right)
37 not(child)
38 op(left/right)
39 path(component...) -> field
150f0d33 40
41 consist in AND, OR and NOT nested expressions, forming a tree with
42 simple relations as leaves. The simple relations test is a field
43 in an event is equal, not equal, smaller, smaller or equal, larger, or
44 larger or equal to a specified value.
31452f49 45*/
46
150f0d33 47/*
48 * YET TO BE ANSWERED
49 * - none yet
50 */
51
52/*
53 * TODO
54 * - refine switch of expression in multiple uses functions
55 * - remove the idle expressions in the tree ****
56 * - add the current simple expression to the tree
389ba50e 57 * * clear the field_path array after use
150f0d33 58 */
59
60#include <lttv/filter.h>
61
62/*
1a7fa682 63GQuark
64 LTTV_FILTER_TRACE,
65 LTTV_FILTER_TRACESET,
66 LTTV_FILTER_TRACEFILE,
67 LTTV_FILTER_STATE,
91ad3f0a 68 LTTV_FILTER_EVENT,
69 LTTV_FILTER_NAME,
70 LTTV_FILTER_CATEGORY,
71 LTTV_FILTER_TIME,
72 LTTV_FILTER_TSC,
73 LTTV_FILTER_PID,
74 LTTV_FILTER_PPID,
75 LTTV_FILTER_C_TIME,
76 LTTV_FILTER_I_TIME,
77 LTTV_FILTER_P_NAME,
78 LTTV_FILTER_EX_MODE,
79 LTTV_FILTER_EX_SUBMODE,
80 LTTV_FILTER_P_STATUS,
81 LTTV_FILTER_CPU;
150f0d33 82*/
0cdc2470 83
389ba50e 84/**
85 * Constructor for LttvSimpleExpression
86 * @return pointer to new LttvSimpleExpression
87 */
2ea36caf 88LttvSimpleExpression*
0cdc2470 89lttv_simple_expression_new() {
90
389ba50e 91 LttvSimpleExpression* se = g_new(LttvSimpleExpression,1);
92
93 se->field = LTTV_FILTER_UNDEFINED;
bb87caa7 94 se->op = NULL;
389ba50e 95 se->offset = 0;
96 se->value = NULL;
97
98 return se;
0cdc2470 99}
f4e9dd16 100/**
150f0d33 101 * add a node to the current tree
bb87caa7 102 * FIXME: Might be used to lower coding in lttv_filter_new switch expression
150f0d33 103 * @param stack the tree stack
104 * @param subtree the subtree if available (pointer or NULL)
105 * @param op the logical operator that will form the node
f4e9dd16 106 */
0cdc2470 107void
5b729fcf 108lttv_filter_tree_add_node(GPtrArray* stack, LttvFilterTree* subtree, LttvLogicalOp op) {
0cdc2470 109
5b729fcf 110 LttvFilterTree* t1 = NULL;
111 LttvFilterTree* t2 = NULL;
0cdc2470 112
5b729fcf 113 t1 = (LttvFilterTree*)g_ptr_array_index(stack,stack->len-1);
0cdc2470 114 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
115 t2 = lttv_filter_tree_new();
116 t2->node = op;
117 if(subtree != NULL) {
118 t2->left = LTTV_TREE_NODE;
119 t2->l_child.t = subtree;
120 subtree = NULL;
121 t1->right = LTTV_TREE_NODE;
122 t1->r_child.t = t2;
123 } else {
124// a_simple_expression->value = a_field_component->str;
125// a_field_component = g_string_new("");
126 t2->left = LTTV_TREE_LEAF;
127// t2->l_child.leaf = a_simple_expression;
128// a_simple_expression = g_new(lttv_simple_expression,1);
129 t1->right = LTTV_TREE_NODE;
130 t1->r_child.t = t2;
131 }
132
133}
134
0769c82f 135/**
136 * Parse through filtering field hierarchy as specified
137 * by user. This function compares each value to
138 * predetermined quarks
139 * @param fp The field path list
bb87caa7 140 * @param se current simple expression
0769c82f 141 * @return success/failure of operation
142 */
143gboolean
47aa6e58 144parse_field_path(GPtrArray* fp, LttvSimpleExpression* se) {
0769c82f 145
f4e9dd16 146 GString* f = NULL;
2b99ec10 147 if(fp->len < 2) return FALSE;
f4e9dd16 148 g_assert(f=g_ptr_array_index(fp,0)); //list_first(fp)->data;
47aa6e58 149
150 /*
151 * Parse through the specified
152 * hardcoded fields.
153 *
154 * Take note however that the
155 * 'event' subfields might change
156 * depending on values specified
157 * in core.xml file. Hence, if
158 * none of the subfields in the
159 * array match the hardcoded
160 * subfields, it will be considered
161 * as a dynamic field
162 */
163 if(g_strcasecmp(f->str,"trace") ) {
164 /*
165 * Possible values:
166 * trace.name
167 */
168 f=g_ptr_array_index(fp,1);
389ba50e 169 if(g_strcasecmp(f->str,"name")) {
170 se->field = LTTV_FILTER_TRACE_NAME;
171 }
47aa6e58 172 else return FALSE;
173 } else if(g_strcasecmp(f->str,"traceset") ) {
174 /*
175 * FIXME: not yet implemented !
176 */
177 } else if(g_strcasecmp(f->str,"tracefile") ) {
178 /*
179 * Possible values:
180 * tracefile.name
181 */
182 f=g_ptr_array_index(fp,1);
389ba50e 183 if(g_strcasecmp(f->str,"name")) {
184 se->field = LTTV_FILTER_TRACEFILE_NAME;
185 }
47aa6e58 186 else return FALSE;
187 } else if(g_strcasecmp(f->str,"state") ) {
188 /*
189 * Possible values:
190 * state.pid
191 * state.ppid
192 * state.creation_time
193 * state.insertion_time
194 * state.process_name
195 * state.execution_mode
196 * state.execution_submode
197 * state.process_status
198 * state.cpu
199 */
200 f=g_ptr_array_index(fp,1);
389ba50e 201 if(g_strcasecmp(f->str,"pid") ) {
202 se->field = LTTV_FILTER_STATE_PID;
203 }
204 else if(g_strcasecmp(f->str,"ppid") ) {
205 se->field = LTTV_FILTER_STATE_PPID;
206 }
207 else if(g_strcasecmp(f->str,"creation_time") ) {
208 se->field = LTTV_FILTER_STATE_CT;
209 }
210 else if(g_strcasecmp(f->str,"insertion_time") ) {
211 se->field = LTTV_FILTER_STATE_IT;
212 }
213 else if(g_strcasecmp(f->str,"process_name") ) {
214 se->field = LTTV_FILTER_STATE_P_NAME;
215 }
216 else if(g_strcasecmp(f->str,"execution_mode") ) {
217 se->field = LTTV_FILTER_STATE_EX_MODE;
218 }
219 else if(g_strcasecmp(f->str,"execution_submode") ) {
220 se->field = LTTV_FILTER_STATE_EX_SUBMODE;
221 }
222 else if(g_strcasecmp(f->str,"process_status") ) {
223 se->field = LTTV_FILTER_STATE_P_STATUS;
224 }
225 else if(g_strcasecmp(f->str,"cpu") ) {
226 se->field = LTTV_FILTER_STATE_CPU;
227 }
47aa6e58 228 else return FALSE;
229 } else if(g_strcasecmp(f->str,"event") ) {
389ba50e 230 /*
231 * Possible values:
232 * event.name
233 * event.category
234 * event.time
235 * event.tsc
236 */
2b99ec10 237 f=g_ptr_array_index(fp,1);
389ba50e 238 if(g_strcasecmp(f->str,"name") ) {
239 se->field = LTTV_FILTER_EVENT_NAME;
240 }
241 else if(g_strcasecmp(f->str,"category") ) {
242 /*
243 * FIXME: Category not yet functional in lttv
244 */
245 se->field = LTTV_FILTER_EVENT_CATEGORY;
246 }
47aa6e58 247 else if(g_strcasecmp(f->str,"time") ) {
389ba50e 248 se->field = LTTV_FILTER_EVENT_TIME;
2b99ec10 249 // offset = &((LttEvent*)NULL)->event_time);
250 }
47aa6e58 251 else if(g_strcasecmp(f->str,"tsc") ) {
389ba50e 252 se->field = LTTV_FILTER_EVENT_TSC;
2b99ec10 253 // offset = &((LttEvent*)NULL)->event_cycle_count);
254 }
255 else { /* core.xml specified options */
389ba50e 256 se->field = LTTV_FILTER_EVENT_FIELD;
257 //se->offset = (...);
2b99ec10 258 }
91ad3f0a 259 } else {
260 g_warning("Unrecognized field in filter string");
261 return FALSE;
0769c82f 262 }
47aa6e58 263
bb87caa7 264 /* free the pointer array */
265 g_ptr_array_free(fp,FALSE);
266
91ad3f0a 267 return TRUE;
0769c82f 268}
269
bb87caa7 270/**
271 * Sets the function pointer for the current
272 * Simple Expression
273 * @param se current simple expression
274 * @return success/failure of operation
275 */
276gboolean assign_operator(LttvSimpleExpression* se, LttvExpressionOp op) {
277
278 switch(se->field) {
279 /* char */
280 case LTTV_FILTER_TRACE_NAME:
281 case LTTV_FILTER_TRACEFILE_NAME:
282 case LTTV_FILTER_STATE_P_NAME:
283 case LTTV_FILTER_EVENT_NAME:
284 switch(op) {
285 case LTTV_FIELD_EQ:
286 se->op = lttv_apply_op_eq_string;
287 break;
288 case LTTV_FIELD_NE:
289 se->op = lttv_apply_op_eq_string;
290 break;
291 default:
292 g_warning("Error encountered in operator assignment");
293 return FALSE;
294 }
295 break;
296 case LTTV_FILTER_STATE_PID:
297 case LTTV_FILTER_STATE_PPID:
298 case LTTV_FILTER_STATE_EX_MODE:
299 case LTTV_FILTER_STATE_EX_SUBMODE:
300 case LTTV_FILTER_STATE_P_STATUS:
301 switch(op) {
302 case LTTV_FIELD_EQ:
303 se->op = lttv_apply_op_eq_uint64;
304 break;
305 case LTTV_FIELD_NE:
306 se->op = lttv_apply_op_ne_uint64;
307 break;
308 case LTTV_FIELD_LT:
309 se->op = lttv_apply_op_lt_uint64;
310 break;
311 case LTTV_FIELD_LE:
312 se->op = lttv_apply_op_le_uint64;
313 break;
314 case LTTV_FIELD_GT:
315 se->op = lttv_apply_op_gt_uint64;
316 break;
317 case LTTV_FIELD_GE:
318 se->op = lttv_apply_op_ge_uint64;
319 break;
320 default:
321 g_warning("Error encountered in operator assignment");
322 return FALSE;
323 }
324 break;
325 case LTTV_FILTER_STATE_CT:
326 case LTTV_FILTER_STATE_IT:
327 case LTTV_FILTER_EVENT_TIME:
328 case LTTV_FILTER_EVENT_TSC:
329 switch(op) {
330 case LTTV_FIELD_EQ:
331 se->op = lttv_apply_op_eq_double;
332 break;
333 case LTTV_FIELD_NE:
334 se->op = lttv_apply_op_ne_double;
335 break;
336 case LTTV_FIELD_LT:
337 se->op = lttv_apply_op_lt_double;
338 break;
339 case LTTV_FIELD_LE:
340 se->op = lttv_apply_op_le_double;
341 break;
342 case LTTV_FIELD_GT:
343 se->op = lttv_apply_op_gt_double;
344 break;
345 case LTTV_FIELD_GE:
346 se->op = lttv_apply_op_ge_double;
347 break;
348 default:
349 g_warning("Error encountered in operator assignment");
350 return FALSE;
351 }
352 break;
353 default:
354 g_warning("Error encountered in operator assignment");
355 return FALSE;
356 }
357
358}
359
31452f49 360/**
84a333d6 361 * Add an filtering option to the current tree
362 * @param expression Current expression to parse
363 * @return success/failure of operation
364 */
365gboolean
366parse_simple_expression(GString* expression) {
367
368 unsigned i;
369
a4c292d4 370
0769c82f 371
a4c292d4 372
84a333d6 373}
374
150f0d33 375/**
376 * Applies the 'equal' operator to the
47aa6e58 377 * specified structure and value
378 * @param v1 left member of comparison
379 * @param v2 right member of comparison
150f0d33 380 * @return success/failure of operation
381 */
bb87caa7 382gboolean lttv_apply_op_eq_uint64(gpointer v1, char* v2) {}
150f0d33 383
5b729fcf 384/**
385 * Applies the 'equal' operator to the
47aa6e58 386 * specified structure and value
387 * @param v1 left member of comparison
388 * @param v2 right member of comparison
5b729fcf 389 * @return success/failure of operation
390 */
bb87caa7 391gboolean lttv_apply_op_eq_uint32(gpointer v1, char* v2) {}
5b729fcf 392
393/**
394 * Applies the 'equal' operator to the
47aa6e58 395 * specified structure and value
396 * @param v1 left member of comparison
397 * @param v2 right member of comparison
5b729fcf 398 * @return success/failure of operation
399 */
bb87caa7 400gboolean lttv_apply_op_eq_uint16(gpointer v1, char* v2) {}
5b729fcf 401
402/**
403 * Applies the 'equal' operator to the
47aa6e58 404 * specified structure and value
405 * @param v1 left member of comparison
406 * @param v2 right member of comparison
5b729fcf 407 * @return success/failure of operation
408 */
bb87caa7 409gboolean lttv_apply_op_eq_double(gpointer v1, char* v2) {}
5b729fcf 410
411/**
412 * Applies the 'equal' operator to the
47aa6e58 413 * specified structure and value
414 * @param v1 left member of comparison
415 * @param v2 right member of comparison
5b729fcf 416 * @return success/failure of operation
417 */
bb87caa7 418gboolean lttv_apply_op_eq_string(gpointer v1, char* v2) {}
150f0d33 419
420/**
421 * Applies the 'not equal' operator to the
47aa6e58 422 * specified structure and value
423 * @param v1 left member of comparison
424 * @param v2 right member of comparison
150f0d33 425 * @return success/failure of operation
426 */
bb87caa7 427gboolean lttv_apply_op_ne_uint64(gpointer v1, char* v2) {}
150f0d33 428
5b729fcf 429/**
430 * Applies the 'not equal' operator to the
47aa6e58 431 * specified structure and value
432 * @param v1 left member of comparison
433 * @param v2 right member of comparison
5b729fcf 434 * @return success/failure of operation
435 */
bb87caa7 436gboolean lttv_apply_op_ne_uint32(gpointer v1, char* v2) {}
5b729fcf 437
438/**
439 * Applies the 'not equal' operator to the
47aa6e58 440 * specified structure and value
441 * @param v1 left member of comparison
442 * @param v2 right member of comparison
5b729fcf 443 * @return success/failure of operation
444 */
bb87caa7 445gboolean lttv_apply_op_ne_uint16(gpointer v1, char* v2) {}
5b729fcf 446
447/**
448 * Applies the 'not equal' operator to the
47aa6e58 449 * specified structure and value
450 * @param v1 left member of comparison
451 * @param v2 right member of comparison
5b729fcf 452 * @return success/failure of operation
453 */
bb87caa7 454gboolean lttv_apply_op_ne_double(gpointer v1, char* v2) {}
5b729fcf 455
456/**
457 * Applies the 'not equal' operator to the
47aa6e58 458 * specified structure and value
459 * @param v1 left member of comparison
460 * @param v2 right member of comparison
5b729fcf 461 * @return success/failure of operation
462 */
bb87caa7 463gboolean lttv_apply_op_ne_string(gpointer v1, char* v2) {}
150f0d33 464
465/**
466 * Applies the 'lower than' operator to the
47aa6e58 467 * specified structure and value
468 * @param v1 left member of comparison
469 * @param v2 right member of comparison
150f0d33 470 * @return success/failure of operation
471 */
bb87caa7 472gboolean lttv_apply_op_lt_uint64(gpointer v1, char* v2) {}
150f0d33 473
5b729fcf 474/**
475 * Applies the 'lower than' operator to the
47aa6e58 476 * specified structure and value
477 * @param v1 left member of comparison
478 * @param v2 right member of comparison
5b729fcf 479 * @return success/failure of operation
480 */
bb87caa7 481gboolean lttv_apply_op_lt_uint32(gpointer v1, char* v2) {}
5b729fcf 482
483/**
484 * Applies the 'lower than' operator to the
47aa6e58 485 * specified structure and value
486 * @param v1 left member of comparison
487 * @param v2 right member of comparison
5b729fcf 488 * @return success/failure of operation
489 */
bb87caa7 490gboolean lttv_apply_op_lt_uint16(gpointer v1, char* v2) {}
5b729fcf 491
492/**
493 * Applies the 'lower than' operator to the
47aa6e58 494 * specified structure and value
495 * @param v1 left member of comparison
496 * @param v2 right member of comparison
5b729fcf 497 * @return success/failure of operation
498 */
bb87caa7 499gboolean lttv_apply_op_lt_double(gpointer v1, char* v2) {}
5b729fcf 500
501/**
502 * Applies the 'lower than' operator to the
47aa6e58 503 * specified structure and value
504 * @param v1 left member of comparison
505 * @param v2 right member of comparison
5b729fcf 506 * @return success/failure of operation
507 */
bb87caa7 508gboolean lttv_apply_op_le_uint64(gpointer v1, char* v2) {}
150f0d33 509
510/**
511 * Applies the 'lower or equal' operator to the
47aa6e58 512 * specified structure and value
513 * @param v1 left member of comparison
514 * @param v2 right member of comparison
150f0d33 515 * @return success/failure of operation
516 */
bb87caa7 517gboolean lttv_apply_op_le_uint32(gpointer v1, char* v2) {}
150f0d33 518
5b729fcf 519/**
520 * Applies the 'lower or equal' operator to the
47aa6e58 521 * specified structure and value
522 * @param v1 left member of comparison
523 * @param v2 right member of comparison
5b729fcf 524 * @return success/failure of operation
525 */
bb87caa7 526gboolean lttv_apply_op_le_uint16(gpointer v1, char* v2) {}
5b729fcf 527
528/**
529 * Applies the 'lower or equal' operator to the
47aa6e58 530 * specified structure and value
531 * @param v1 left member of comparison
532 * @param v2 right member of comparison
5b729fcf 533 * @return success/failure of operation
534 */
bb87caa7 535gboolean lttv_apply_op_le_double(gpointer v1, char* v2) {}
5b729fcf 536
537/**
538 * Applies the 'lower or equal' operator to the
47aa6e58 539 * specified structure and value
540 * @param v1 left member of comparison
541 * @param v2 right member of comparison
5b729fcf 542 * @return success/failure of operation
543 */
bb87caa7 544gboolean lttv_apply_op_gt_uint64(gpointer v1, char* v2) {}
150f0d33 545
546/**
547 * Applies the 'greater than' operator to the
47aa6e58 548 * specified structure and value
549 * @param v1 left member of comparison
550 * @param v2 right member of comparison
150f0d33 551 * @return success/failure of operation
552 */
bb87caa7 553gboolean lttv_apply_op_gt_uint32(gpointer v1, char* v2) {}
150f0d33 554
5b729fcf 555/**
556 * Applies the 'greater than' operator to the
47aa6e58 557 * specified structure and value
558 * @param v1 left member of comparison
559 * @param v2 right member of comparison
5b729fcf 560 * @return success/failure of operation
561 */
bb87caa7 562gboolean lttv_apply_op_gt_uint16(gpointer v1, char* v2) {}
5b729fcf 563
564/**
565 * Applies the 'greater than' operator to the
47aa6e58 566 * specified structure and value
567 * @param v1 left member of comparison
568 * @param v2 right member of comparison
5b729fcf 569 * @return success/failure of operation
570 */
bb87caa7 571gboolean lttv_apply_op_gt_double(gpointer v1, char* v2) {}
5b729fcf 572
573/**
574 * Applies the 'greater than' operator to the
47aa6e58 575 * specified structure and value
576 * @param v1 left member of comparison
577 * @param v2 right member of comparison
5b729fcf 578 * @return success/failure of operation
579 */
bb87caa7 580gboolean lttv_apply_op_ge_uint64(gpointer v1, char* v2) {}
150f0d33 581
582/**
583 * Applies the 'greater or equal' operator to the
47aa6e58 584 * specified structure and value
585 * @param v1 left member of comparison
586 * @param v2 right member of comparison
150f0d33 587 * @return success/failure of operation
588 */
bb87caa7 589gboolean lttv_apply_op_ge_uint32(gpointer v1, char* v2) {}
150f0d33 590
5b729fcf 591/**
592 * Applies the 'greater or equal' operator to the
47aa6e58 593 * specified structure and value
594 * @param v1 left member of comparison
595 * @param v2 right member of comparison
5b729fcf 596 * @return success/failure of operation
597 */
bb87caa7 598gboolean lttv_apply_op_ge_uint16(gpointer v1, char* v2) {}
150f0d33 599
5b729fcf 600/**
601 * Applies the 'greater or equal' operator to the
47aa6e58 602 * specified structure and value
603 * @param v1 left member of comparison
604 * @param v2 right member of comparison
5b729fcf 605 * @return success/failure of operation
606 */
bb87caa7 607gboolean lttv_apply_op_ge_double(gpointer v1, char* v2) {}
150f0d33 608
609
610/**
611 * Makes a copy of the current filter tree
612 * @param tree pointer to the current tree
613 * @return new copy of the filter tree
614 */
615LttvFilterTree*
616lttv_filter_tree_clone(LttvFilterTree* tree) {
617
618
619
620}
621
622/**
623 * Makes a copy of the current filter
624 * @param filter pointer to the current filter
625 * @return new copy of the filter
626 */
627LttvFilter*
628lttv_filter_clone(LttvFilter* filter) {
629
630
631 LttvFilter* newfilter = g_new(LttvFilter,1);
632
633 // newfilter->expression = g_new(char,1)
634 strcpy(newfilter->expression,filter->expression);
635
636 newfilter->head = lttv_filter_tree_clone(filter->head);
637
638 return newfilter;
639
640}
641
642
84a333d6 643/**
644 * Creates a new lttv_filter
31452f49 645 * @param expression filtering options string
646 * @param t pointer to the current LttvTrace
84a333d6 647 * @return the current lttv_filter or NULL if error
31452f49 648 */
2ea36caf 649LttvFilter*
0769c82f 650lttv_filter_new(char *expression, LttvTraceState *tcs) {
a4c292d4 651
0769c82f 652 g_print("filter::lttv_filter_new()\n"); /* debug */
a4c292d4 653
a4c292d4 654 unsigned
655 i,
91ad3f0a 656 p_nesting=0, /* parenthesis nesting value */
a4c292d4 657 b=0; /* current breakpoint in expression string */
1601b365 658
659 /* trees */
5b729fcf 660 LttvFilterTree
1601b365 661 *tree = lttv_filter_tree_new(), /* main tree */
662 *subtree = NULL, /* buffer for subtrees */
663 *t1, /* buffer #1 */
664 *t2; /* buffer #2 */
665
666 /*
667 * Tree Stack
f4e9dd16 668 * each element of the list
669 * is a sub tree created
670 * by the use of parenthesis in the
671 * global expression. The final tree
1601b365 672 * will be the one left at the root of
f4e9dd16 673 * the list
674 */
18d1226f 675 GPtrArray *tree_stack = g_ptr_array_new();
676 g_ptr_array_add( tree_stack,(gpointer) tree );
f4e9dd16 677
a4c292d4 678 /* temporary values */
0769c82f 679 GString *a_field_component = g_string_new("");
f4e9dd16 680 GPtrArray *a_field_path = NULL;
681
389ba50e 682 LttvSimpleExpression* a_simple_expression = lttv_simple_expression_new();
0769c82f 683
a4c292d4 684 /*
685 * Parse entire expression and construct
686 * the binary tree. There are two steps
687 * in browsing that string
f4e9dd16 688 * 1. finding boolean ops " &,|,^,! " and parenthesis " {,(,[,],),} "
a4c292d4 689 * 2. finding simple expressions
0769c82f 690 * - field path ( separated by dots )
a4c292d4 691 * - op ( >, <, =, >=, <=, !=)
0769c82f 692 * - value ( integer, string ... )
693 * To spare computing time, the whole
694 * string is parsed in this loop for a
695 * O(n) complexity order.
1601b365 696 *
18d1226f 697 * When encountering logical op &,|,^
698 * 1. parse the last value if any
699 * 2. create a new tree
700 * 3. add the expression (simple exp, or exp (subtree)) to the tree
701 * 4. concatenate this tree with the current tree on top of the stack
702 * When encountering math ops >,>=,<,<=,=,!=
703 * 1. add to op to the simple expression
704 * 2. concatenate last field component to field path
705 * When encountering concatening ops .
706 * 1. concatenate last field component to field path
707 * When encountering opening parenthesis (,{,[
708 * 1. create a new subtree on top of tree stack
709 * When encountering closing parenthesis ),},]
710 * 1. add the expression on right child of the current tree
711 * 2. the subtree is completed, allocate a new subtree
712 * 3. pop the tree value from the tree stack
713 */
714
f4e9dd16 715 a_field_path = g_ptr_array_new();
716 g_ptr_array_set_size(a_field_path,2); /* by default, recording 2 field expressions */
717
18d1226f 718
a4c292d4 719 for(i=0;i<strlen(expression);i++) {
18d1226f 720// g_print("%s\n",a_field_component->str);
410c83da 721 g_print("%c ",expression[i]);
1601b365 722// g_print("switch:%c -->subtree:%p\n",expression[i],subtree);
a4c292d4 723 switch(expression[i]) {
724 /*
725 * logical operators
726 */
727 case '&': /* and */
5b729fcf 728 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 729 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
18d1226f 730 t2 = lttv_filter_tree_new();
0cdc2470 731 t2->node = LTTV_LOGICAL_AND;
bb87caa7 732 if(subtree != NULL) { /* append subtree to current tree */
18d1226f 733 t2->left = LTTV_TREE_NODE;
734 t2->l_child.t = subtree;
f4e9dd16 735 subtree = NULL;
18d1226f 736 t1->right = LTTV_TREE_NODE;
410c83da 737 t1->r_child.t = t2;
bb87caa7 738 } else { /* append a simple expression */
0cdc2470 739 a_simple_expression->value = a_field_component->str;
18d1226f 740 a_field_component = g_string_new("");
741 t2->left = LTTV_TREE_LEAF;
0cdc2470 742 t2->l_child.leaf = a_simple_expression;
389ba50e 743 a_simple_expression = lttv_simple_expression_new();
18d1226f 744 t1->right = LTTV_TREE_NODE;
410c83da 745 t1->r_child.t = t2;
f4e9dd16 746 }
747
748 break;
a4c292d4 749 case '|': /* or */
2ea36caf 750 t1 = (LttvFilter*)g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 751 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
1601b365 752 t2 = lttv_filter_tree_new();
0cdc2470 753 t2->node = LTTV_LOGICAL_OR;
bb87caa7 754 if(subtree != NULL) { /* append subtree to current tree */
1601b365 755 t2->left = LTTV_TREE_NODE;
756 t2->l_child.t = subtree;
757 subtree = NULL;
758 t1->right = LTTV_TREE_NODE;
759 t1->r_child.t = t2;
bb87caa7 760 } else { /* append a simple expression */
0cdc2470 761 a_simple_expression->value = a_field_component->str;
1601b365 762 a_field_component = g_string_new("");
763 t2->left = LTTV_TREE_LEAF;
0cdc2470 764 t2->l_child.leaf = a_simple_expression;
389ba50e 765 a_simple_expression = lttv_simple_expression_new();
1601b365 766 t1->right = LTTV_TREE_NODE;
767 t1->r_child.t = t2;
768 }
f4e9dd16 769 break;
a4c292d4 770 case '^': /* xor */
2ea36caf 771 t1 = (LttvFilter*)g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 772 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
1601b365 773 t2 = lttv_filter_tree_new();
0cdc2470 774 t2->node = LTTV_LOGICAL_XOR;
bb87caa7 775 if(subtree != NULL) { /* append subtree to current tree */
1601b365 776 t2->left = LTTV_TREE_NODE;
777 t2->l_child.t = subtree;
778 subtree = NULL;
779 t1->right = LTTV_TREE_NODE;
780 t1->r_child.t = t2;
bb87caa7 781 } else { /* append a simple expression */
0cdc2470 782 a_simple_expression->value = a_field_component->str;
1601b365 783 a_field_component = g_string_new("");
784 t2->left = LTTV_TREE_LEAF;
0cdc2470 785 t2->l_child.leaf = a_simple_expression;
389ba50e 786 a_simple_expression = lttv_simple_expression_new();
1601b365 787 t1->right = LTTV_TREE_NODE;
788 t1->r_child.t = t2;
789 }
a4c292d4 790 break;
791 case '!': /* not, or not equal (math op) */
792 if(expression[i+1] == '=') { /* != */
bb87caa7 793 assign_operator(a_simple_expression,LTTV_FIELD_NE);
a4c292d4 794 i++;
0cdc2470 795 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
389ba50e 796 parse_field_path(a_field_path,a_simple_expression);
0cdc2470 797 a_field_component = g_string_new("");
a4c292d4 798 } else { /* ! */
1601b365 799 // g_print("%s\n",a_field_component);
800 // a_field_component = g_string_new("");
2ea36caf 801 t1 = (LttvFilter*)g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 802 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
1601b365 803 t2 = lttv_filter_tree_new();
0cdc2470 804 t2->node = LTTV_LOGICAL_NOT;
1601b365 805 t1->right = LTTV_TREE_NODE;
806 t1->r_child.t = t2;
a4c292d4 807 }
808 break;
809 case '(': /* start of parenthesis */
91ad3f0a 810 case '[':
811 case '{':
812 p_nesting++; /* incrementing parenthesis nesting value */
1601b365 813 t1 = lttv_filter_tree_new();
814 g_ptr_array_add( tree_stack,(gpointer) t1 );
a4c292d4 815 break;
816 case ')': /* end of parenthesis */
91ad3f0a 817 case ']':
818 case '}':
819 p_nesting--; /* decrementing parenthesis nesting value */
18d1226f 820 if(p_nesting<0 || tree_stack->len<2) {
f4e9dd16 821 g_warning("Wrong filtering options, the string\n\"%s\"\n\
822 is not valid due to parenthesis incorrect use",expression);
823 return NULL;
824 }
18d1226f 825
826 g_assert(tree_stack->len>0);
bb87caa7 827 if(subtree != NULL) { /* append subtree to current tree */
18d1226f 828 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 829 while(t1->right != LTTV_TREE_IDLE && t1->right != LTTV_TREE_LEAF) {
18d1226f 830 g_assert(t1!=NULL && t1->r_child.t != NULL);
831 t1 = t1->r_child.t;
832 }
833 t1->right = LTTV_TREE_NODE;
834 t1->r_child.t = subtree;
835 subtree = g_ptr_array_index(tree_stack,tree_stack->len-1);
836 g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
bb87caa7 837 } else { /* assign subtree as current tree */
0cdc2470 838 a_simple_expression->value = a_field_component->str;
18d1226f 839 a_field_component = g_string_new("");
840 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 841 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
18d1226f 842 t1->right = LTTV_TREE_LEAF;
0cdc2470 843 t1->r_child.leaf = a_simple_expression;
389ba50e 844 a_simple_expression = lttv_simple_expression_new();
18d1226f 845 subtree = g_ptr_array_index(tree_stack,tree_stack->len-1);
1601b365 846 g_assert(subtree != NULL);
18d1226f 847 g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
848 }
a4c292d4 849 break;
850
851 /*
852 * mathematic operators
853 */
854 case '<': /* lower, lower or equal */
855 if(expression[i+1] == '=') { /* <= */
856 i++;
bb87caa7 857 assign_operator(a_simple_expression,LTTV_FIELD_LE);
858 } else assign_operator(a_simple_expression,LTTV_FIELD_LT);
f4e9dd16 859 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
389ba50e 860 parse_field_path(a_field_path,a_simple_expression);
f4e9dd16 861 a_field_component = g_string_new("");
a4c292d4 862 break;
863 case '>': /* higher, higher or equal */
864 if(expression[i+1] == '=') { /* >= */
865 i++;
bb87caa7 866 assign_operator(a_simple_expression,LTTV_FIELD_GE);
867 } else assign_operator(a_simple_expression,LTTV_FIELD_GT);
389ba50e 868 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
869 parse_field_path(a_field_path,a_simple_expression);
f4e9dd16 870 a_field_component = g_string_new("");
a4c292d4 871 break;
872 case '=': /* equal */
bb87caa7 873 assign_operator(a_simple_expression,LTTV_FIELD_EQ);
f4e9dd16 874 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
389ba50e 875 parse_field_path(a_field_path,a_simple_expression);
f4e9dd16 876 a_field_component = g_string_new("");
a4c292d4 877 break;
0769c82f 878 /*
879 * Field concatening caracter
880 */
881 case '.': /* dot */
bb87caa7 882 /*
883 * divide field expression into elements
884 * in a_field_path array.
885 */
886 if(a_simple_expression->op != NULL) {
887 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
888 a_field_component = g_string_new("");
889 }
0769c82f 890 break;
a4c292d4 891 default: /* concatening current string */
1a7fa682 892 g_string_append_c(a_field_component,expression[i]);
a4c292d4 893 }
894 }
1601b365 895
896 g_print("subtree:%p, tree:%p, t1:%p, t2:%p\n",subtree,tree,t1,t2);
0cdc2470 897 g_print("stack size: %i\n",tree_stack->len);
898
899 /*
900 * Preliminary check to see
901 * if tree was constructed correctly
902 */
903 if( p_nesting>0 ) {
904 g_warning("Wrong filtering options, the string\n\"%s\"\n\
905 is not valid due to parenthesis incorrect use",expression);
906 return NULL;
907 }
908
909 if(tree_stack->len != 1) /* only root tree should remain */
910 return NULL;
1601b365 911
410c83da 912 /* processing last element of expression */
410c83da 913 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 914 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
410c83da 915 if(subtree != NULL) { /* add the subtree */
916 t1->right = LTTV_TREE_NODE;
0cdc2470 917 t1->r_child.t = subtree;
410c83da 918 subtree = NULL;
919 } else { /* add a leaf */
0cdc2470 920 a_simple_expression->value = a_field_component->str;
410c83da 921 a_field_component = g_string_new("");
922 t1->right = LTTV_TREE_LEAF;
0cdc2470 923 t1->r_child.leaf = a_simple_expression;
2ea36caf 924 /*
925 * FIXME: is it really necessary to reallocate
926 * LttvSimpleExpression at this point ??
927 */
389ba50e 928 a_simple_expression = lttv_simple_expression_new();
410c83da 929 }
930
931 g_assert(tree != NULL);
932 g_assert(subtree == NULL);
a4c292d4 933
1601b365 934 lttv_filter_tracefile(tree,NULL);
935
410c83da 936 return tree;
937
31452f49 938}
939
1da1525d 940void
2ea36caf 941lttv_filter_destroy(LttvFilter* filter) {
1da1525d 942
943}
944
150f0d33 945/**
946 * Assign a new tree for the current expression
947 * or sub expression
948 * @return pointer of LttvFilterTree
949 */
950LttvFilterTree* lttv_filter_tree_new() {
951 LttvFilterTree* tree;
952
953 tree = g_new(LttvFilter,1);
954 tree->node = 0; //g_new(lttv_expression,1);
955// tree->node->type = LTTV_UNDEFINED_EXPRESSION;
956 tree->left = LTTV_TREE_IDLE;
957 tree->right = LTTV_TREE_IDLE;
958
959 return tree;
960}
961
962/**
963 * Destroys the tree and his sub-trees
964 * @param tree Tree which must be destroyed
965 */
966void lttv_filter_tree_destroy(LttvFilterTree* tree) {
967
968 if(tree == NULL) return;
969
970 if(tree->left == LTTV_TREE_LEAF) g_free(tree->l_child.leaf);
971 else if(tree->left == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->l_child.t);
972
973 if(tree->right == LTTV_TREE_LEAF) g_free(tree->r_child.leaf);
974 else if(tree->right == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->r_child.t);
975
976 g_free(tree->node);
977 g_free(tree);
978}
979
980
84a333d6 981/**
982 * Apply the filter to a specific trace
983 * @param filter the current filter applied
984 * @param tracefile the trace to apply the filter to
985 * @return success/failure of operation
986 */
31452f49 987gboolean
2ea36caf 988lttv_filter_tracefile(LttvFilter *filter, LttTracefile *tracefile) {
0769c82f 989
5b729fcf 990 LttvFilterTree* t = filter->head;
991
1601b365 992 /*
993 * Each tree is parsed in inorder.
994 * This way, it's possible to apply the left filter of the
995 * tree, then decide whether or not the right branch should
996 * be parsed depending on the linking logical operator
997 *
998 * As for the filtering structure, since we are trying
999 * to remove elements from the trace, it might be better
1000 * managing an array of all items to be removed ..
1001 */
0769c82f 1002
5b729fcf 1003 g_print("node:%p lchild:%p rchild:%p\n",t,t->l_child.t,t->r_child.t);
1004 g_print("node type%i\n",t->node);
1005 if(t->left == LTTV_TREE_NODE) lttv_filter_tracefile(t->l_child.t,NULL);
1006 else if(t->left == LTTV_TREE_LEAF) {
1007 g_assert(t->l_child.leaf->value != NULL);
1008 g_print("%p: left is qqch %i %s\n",t,t->l_child.leaf->op,t->l_child.leaf->value);
0cdc2470 1009 }
5b729fcf 1010 if(t->right == LTTV_TREE_NODE) lttv_filter_tracefile(t->r_child.t,NULL);
1011 else if(t->right == LTTV_TREE_LEAF) {
1012 g_assert(t->r_child.leaf->value != NULL);
1013 g_print("%p: right is qqch %i %s\n",t,t->r_child.leaf->op,t->r_child.leaf->value);
0cdc2470 1014 }
0769c82f 1015
1016 /* test */
1017/* int i, nb;
1018 char *f_name, *e_name;
31452f49 1019
0769c82f 1020 char* field = "cpu";
1021
1022 LttvTraceHook h;
1023
1024 LttEventType *et;
1025
1026 LttType *t;
1027
1028 GString *fe_name = g_string_new("");
1029
1030 nb = ltt_trace_eventtype_number(tcs->parent.t);
1031 g_print("NB:%i\n",nb);
1032 for(i = 0 ; i < nb ; i++) {
1033 et = ltt_trace_eventtype_get(tcs->parent.t, i);
1034 e_name = ltt_eventtype_name(et);
1035 f_name = ltt_facility_name(ltt_eventtype_facility(et));
1036 g_string_printf(fe_name, "%s.%s", f_name, e_name);
1037 g_print("facility:%s and event:%s\n",f_name,e_name);
1038 }
1039 */
31452f49 1040}
1041
1a7fa682 1042gboolean
2ea36caf 1043lttv_filter_tracestate(LttvFilter *filter, LttvTraceState *tracestate) {
341aa948 1044
1045}
1a7fa682 1046
84a333d6 1047/**
1048 * Apply the filter to a specific event
1049 * @param filter the current filter applied
1050 * @param event the event to apply the filter to
1051 * @return success/failure of operation
1052 */
31452f49 1053gboolean
2ea36caf 1054lttv_filter_event(LttvFilter *filter, LttEvent *event) {
31452f49 1055
1056}
1a7fa682 1057
91ad3f0a 1058/**
1059 * Initializes the filter module and specific values
1060 */
1a7fa682 1061static void module_init()
1062{
91ad3f0a 1063
1064 /*
1065 * Quarks initialization
1066 * for hardcoded filtering options
1067 *
1068 * TODO: traceset has no yet been defined
1069 */
1070
1071 /* top fields */
5b729fcf 1072// LTTV_FILTER_EVENT = g_quark_from_string("event");
1073// LTTV_FILTER_TRACE = g_quark_from_string("trace");
1074// LTTV_FILTER_TRACESET = g_quark_from_string("traceset");
1075// LTTV_FILTER_STATE = g_quark_from_string("state");
1076// LTTV_FILTER_TRACEFILE = g_quark_from_string("tracefile");
1a7fa682 1077
91ad3f0a 1078 /* event.name, tracefile.name, trace.name */
5b729fcf 1079// LTTV_FILTER_NAME = g_quark_from_string("name");
91ad3f0a 1080
1081 /* event sub fields */
5b729fcf 1082// LTTV_FILTER_CATEGORY = g_quark_from_string("category");
1083// LTTV_FILTER_TIME = g_quark_from_string("time");
1084// LTTV_FILTER_TSC = g_quark_from_string("tsc");
91ad3f0a 1085
1086 /* state sub fields */
5b729fcf 1087// LTTV_FILTER_PID = g_quark_from_string("pid");
1088// LTTV_FILTER_PPID = g_quark_from_string("ppid");
1089// LTTV_FILTER_C_TIME = g_quark_from_string("creation_time");
1090// LTTV_FILTER_I_TIME = g_quark_from_string("insertion_time");
1091// LTTV_FILTER_P_NAME = g_quark_from_string("process_name");
1092// LTTV_FILTER_EX_MODE = g_quark_from_string("execution_mode");
1093// LTTV_FILTER_EX_SUBMODE = g_quark_from_string("execution_submode");
1094// LTTV_FILTER_P_STATUS = g_quark_from_string("process_status");
1095// LTTV_FILTER_CPU = g_quark_from_string("cpu");
91ad3f0a 1096
1a7fa682 1097}
1098
91ad3f0a 1099/**
1100 * Destroys the filter module and specific values
1101 */
1a7fa682 1102static void module_destroy()
1103{
1104}
1105
1106
91ad3f0a 1107LTTV_MODULE("filter", "Filters traceset and events", \
1108 "Filters traceset and events specifically to user input", \
1a7fa682 1109 module_init, module_destroy)
1110
1111
1112
This page took 0.080577 seconds and 4 git commands to generate.