Massive debugging in lttv 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
f4e9dd16 84/**
150f0d33 85 * add a node to the current tree
bb87caa7 86 * FIXME: Might be used to lower coding in lttv_filter_new switch expression
150f0d33 87 * @param stack the tree stack
88 * @param subtree the subtree if available (pointer or NULL)
89 * @param op the logical operator that will form the node
f4e9dd16 90 */
0cdc2470 91void
5b729fcf 92lttv_filter_tree_add_node(GPtrArray* stack, LttvFilterTree* subtree, LttvLogicalOp op) {
0cdc2470 93
5b729fcf 94 LttvFilterTree* t1 = NULL;
95 LttvFilterTree* t2 = NULL;
0cdc2470 96
5b729fcf 97 t1 = (LttvFilterTree*)g_ptr_array_index(stack,stack->len-1);
0cdc2470 98 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
99 t2 = lttv_filter_tree_new();
100 t2->node = op;
101 if(subtree != NULL) {
102 t2->left = LTTV_TREE_NODE;
103 t2->l_child.t = subtree;
104 subtree = NULL;
105 t1->right = LTTV_TREE_NODE;
106 t1->r_child.t = t2;
107 } else {
108// a_simple_expression->value = a_field_component->str;
109// a_field_component = g_string_new("");
110 t2->left = LTTV_TREE_LEAF;
111// t2->l_child.leaf = a_simple_expression;
112// a_simple_expression = g_new(lttv_simple_expression,1);
113 t1->right = LTTV_TREE_NODE;
114 t1->r_child.t = t2;
115 }
116
117}
118
80f9611a 119
120/**
121 * Constructor for LttvSimpleExpression
122 * @return pointer to new LttvSimpleExpression
123 */
124LttvSimpleExpression*
125lttv_simple_expression_new() {
126
127 LttvSimpleExpression* se = g_new(LttvSimpleExpression,1);
128
129 se->field = LTTV_FILTER_UNDEFINED;
130 se->op = NULL;
131 se->offset = 0;
132 se->value = NULL;
133
134 return se;
135}
136
0769c82f 137/**
138 * Parse through filtering field hierarchy as specified
139 * by user. This function compares each value to
140 * predetermined quarks
141 * @param fp The field path list
bb87caa7 142 * @param se current simple expression
0769c82f 143 * @return success/failure of operation
144 */
145gboolean
47aa6e58 146parse_field_path(GPtrArray* fp, LttvSimpleExpression* se) {
0769c82f 147
f4e9dd16 148 GString* f = NULL;
cec3d7b0 149// g_print("fp->len:%i\n",fp->len);
150// int i;
151// for(i=0;i<fp->len;i++) {
152// GString* f2 = g_ptr_array_index(fp,i);
153// g_print("%i=%s",i,f2->str);
154// }
73050a5f 155
2b99ec10 156 if(fp->len < 2) return FALSE;
73050a5f 157 g_assert(f=g_ptr_array_remove_index(fp,0)); //list_first(fp)->data;
158
47aa6e58 159 /*
160 * Parse through the specified
161 * hardcoded fields.
162 *
163 * Take note however that the
164 * 'event' subfields might change
165 * depending on values specified
166 * in core.xml file. Hence, if
167 * none of the subfields in the
168 * array match the hardcoded
169 * subfields, it will be considered
170 * as a dynamic field
171 */
80f9611a 172 if(!g_strcasecmp(f->str,"trace") ) {
47aa6e58 173 /*
174 * Possible values:
175 * trace.name
176 */
73050a5f 177 g_string_free(f,TRUE);
178 f=g_ptr_array_remove_index(fp,0);
80f9611a 179 if(!g_strcasecmp(f->str,"name")) {
389ba50e 180 se->field = LTTV_FILTER_TRACE_NAME;
181 }
73050a5f 182// else return FALSE;
80f9611a 183 } else if(!g_strcasecmp(f->str,"traceset") ) {
47aa6e58 184 /*
185 * FIXME: not yet implemented !
186 */
80f9611a 187 } else if(!g_strcasecmp(f->str,"tracefile") ) {
47aa6e58 188 /*
189 * Possible values:
190 * tracefile.name
191 */
73050a5f 192 g_string_free(f,TRUE);
193 f=g_ptr_array_remove_index(fp,0);
80f9611a 194 if(!g_strcasecmp(f->str,"name")) {
389ba50e 195 se->field = LTTV_FILTER_TRACEFILE_NAME;
196 }
73050a5f 197// else return FALSE;
80f9611a 198 } else if(!g_strcasecmp(f->str,"state") ) {
47aa6e58 199 /*
200 * Possible values:
201 * state.pid
202 * state.ppid
203 * state.creation_time
204 * state.insertion_time
205 * state.process_name
206 * state.execution_mode
207 * state.execution_submode
208 * state.process_status
209 * state.cpu
210 */
73050a5f 211 g_string_free(f,TRUE);
212 f=g_ptr_array_remove_index(fp,0);
80f9611a 213 if(!g_strcasecmp(f->str,"pid") ) {
389ba50e 214 se->field = LTTV_FILTER_STATE_PID;
215 }
80f9611a 216 else if(!g_strcasecmp(f->str,"ppid") ) {
389ba50e 217 se->field = LTTV_FILTER_STATE_PPID;
218 }
80f9611a 219 else if(!g_strcasecmp(f->str,"creation_time") ) {
389ba50e 220 se->field = LTTV_FILTER_STATE_CT;
221 }
80f9611a 222 else if(!g_strcasecmp(f->str,"insertion_time") ) {
389ba50e 223 se->field = LTTV_FILTER_STATE_IT;
224 }
80f9611a 225 else if(!g_strcasecmp(f->str,"process_name") ) {
389ba50e 226 se->field = LTTV_FILTER_STATE_P_NAME;
227 }
80f9611a 228 else if(!g_strcasecmp(f->str,"execution_mode") ) {
389ba50e 229 se->field = LTTV_FILTER_STATE_EX_MODE;
230 }
80f9611a 231 else if(!g_strcasecmp(f->str,"execution_submode") ) {
389ba50e 232 se->field = LTTV_FILTER_STATE_EX_SUBMODE;
233 }
80f9611a 234 else if(!g_strcasecmp(f->str,"process_status") ) {
389ba50e 235 se->field = LTTV_FILTER_STATE_P_STATUS;
236 }
80f9611a 237 else if(!g_strcasecmp(f->str,"cpu") ) {
389ba50e 238 se->field = LTTV_FILTER_STATE_CPU;
239 }
73050a5f 240// else return FALSE;
80f9611a 241 } else if(!g_strcasecmp(f->str,"event") ) {
389ba50e 242 /*
243 * Possible values:
244 * event.name
245 * event.category
246 * event.time
247 * event.tsc
248 */
73050a5f 249 g_string_free(f,TRUE);
250 f=g_ptr_array_remove_index(fp,0);
80f9611a 251 if(!g_strcasecmp(f->str,"name") ) {
389ba50e 252 se->field = LTTV_FILTER_EVENT_NAME;
253 }
80f9611a 254 else if(!g_strcasecmp(f->str,"category") ) {
389ba50e 255 /*
256 * FIXME: Category not yet functional in lttv
257 */
258 se->field = LTTV_FILTER_EVENT_CATEGORY;
259 }
80f9611a 260 else if(!g_strcasecmp(f->str,"time") ) {
389ba50e 261 se->field = LTTV_FILTER_EVENT_TIME;
2b99ec10 262 // offset = &((LttEvent*)NULL)->event_time);
263 }
80f9611a 264 else if(!g_strcasecmp(f->str,"tsc") ) {
389ba50e 265 se->field = LTTV_FILTER_EVENT_TSC;
2b99ec10 266 // offset = &((LttEvent*)NULL)->event_cycle_count);
267 }
268 else { /* core.xml specified options */
389ba50e 269 se->field = LTTV_FILTER_EVENT_FIELD;
270 //se->offset = (...);
2b99ec10 271 }
91ad3f0a 272 } else {
273 g_warning("Unrecognized field in filter string");
73050a5f 274// return FALSE;
0769c82f 275 }
47aa6e58 276
73050a5f 277 g_string_free(f,TRUE);
278 g_assert(fp->len == 0);
bb87caa7 279
73050a5f 280 if(se->field == LTTV_FILTER_UNDEFINED) return FALSE;
91ad3f0a 281 return TRUE;
0769c82f 282}
283
bb87caa7 284/**
285 * Sets the function pointer for the current
286 * Simple Expression
287 * @param se current simple expression
288 * @return success/failure of operation
289 */
290gboolean assign_operator(LttvSimpleExpression* se, LttvExpressionOp op) {
aa4600f3 291
cec3d7b0 292// g_print("se->field = %i\n",se->field);
293// g_print("se->offset = %i\n",se->offset);
294// g_print("se->op = %p\n",se->op);
295// g_print("se->value = %s\n",se->value);
73050a5f 296
bb87caa7 297 switch(se->field) {
298 /* char */
299 case LTTV_FILTER_TRACE_NAME:
300 case LTTV_FILTER_TRACEFILE_NAME:
301 case LTTV_FILTER_STATE_P_NAME:
302 case LTTV_FILTER_EVENT_NAME:
303 switch(op) {
304 case LTTV_FIELD_EQ:
305 se->op = lttv_apply_op_eq_string;
306 break;
307 case LTTV_FIELD_NE:
308 se->op = lttv_apply_op_eq_string;
309 break;
310 default:
73050a5f 311 g_warning("Error encountered in operator assignment = or != expected");
bb87caa7 312 return FALSE;
313 }
314 break;
315 case LTTV_FILTER_STATE_PID:
316 case LTTV_FILTER_STATE_PPID:
317 case LTTV_FILTER_STATE_EX_MODE:
318 case LTTV_FILTER_STATE_EX_SUBMODE:
319 case LTTV_FILTER_STATE_P_STATUS:
320 switch(op) {
321 case LTTV_FIELD_EQ:
322 se->op = lttv_apply_op_eq_uint64;
323 break;
324 case LTTV_FIELD_NE:
325 se->op = lttv_apply_op_ne_uint64;
326 break;
327 case LTTV_FIELD_LT:
328 se->op = lttv_apply_op_lt_uint64;
329 break;
330 case LTTV_FIELD_LE:
331 se->op = lttv_apply_op_le_uint64;
332 break;
333 case LTTV_FIELD_GT:
334 se->op = lttv_apply_op_gt_uint64;
335 break;
336 case LTTV_FIELD_GE:
337 se->op = lttv_apply_op_ge_uint64;
338 break;
339 default:
340 g_warning("Error encountered in operator assignment");
341 return FALSE;
342 }
343 break;
344 case LTTV_FILTER_STATE_CT:
345 case LTTV_FILTER_STATE_IT:
346 case LTTV_FILTER_EVENT_TIME:
347 case LTTV_FILTER_EVENT_TSC:
348 switch(op) {
349 case LTTV_FIELD_EQ:
350 se->op = lttv_apply_op_eq_double;
351 break;
352 case LTTV_FIELD_NE:
353 se->op = lttv_apply_op_ne_double;
354 break;
355 case LTTV_FIELD_LT:
356 se->op = lttv_apply_op_lt_double;
357 break;
358 case LTTV_FIELD_LE:
359 se->op = lttv_apply_op_le_double;
360 break;
361 case LTTV_FIELD_GT:
362 se->op = lttv_apply_op_gt_double;
363 break;
364 case LTTV_FIELD_GE:
365 se->op = lttv_apply_op_ge_double;
366 break;
367 default:
368 g_warning("Error encountered in operator assignment");
369 return FALSE;
370 }
371 break;
372 default:
73050a5f 373 g_warning("Error encountered in operator assignment ! Bad field type ...");
bb87caa7 374 return FALSE;
375 }
aa4600f3 376
377 return TRUE;
bb87caa7 378
379}
380
31452f49 381/**
80f9611a 382 * Finds the structure type depending
383 * on the fields in parameters
384 * @params ft Field of the current structure
385 * @return LttvStructType enum or -1 for error
84a333d6 386 */
80f9611a 387gint
388lttv_struct_type(gint ft) {
5f185a2b 389
80f9611a 390 switch(ft) {
391 case LTTV_FILTER_TRACE_NAME:
392 return LTTV_FILTER_TRACE;
393 break;
394 case LTTV_FILTER_TRACEFILE_NAME:
395 return LTTV_FILTER_TRACEFILE;
396 break;
397 case LTTV_FILTER_STATE_PID:
398 case LTTV_FILTER_STATE_PPID:
399 case LTTV_FILTER_STATE_CT:
400 case LTTV_FILTER_STATE_IT:
401 case LTTV_FILTER_STATE_P_NAME:
402 case LTTV_FILTER_STATE_EX_MODE:
403 case LTTV_FILTER_STATE_EX_SUBMODE:
404 case LTTV_FILTER_STATE_P_STATUS:
405 case LTTV_FILTER_STATE_CPU:
406 return LTTV_FILTER_STATE;
407 break;
408 case LTTV_FILTER_EVENT_NAME:
409 case LTTV_FILTER_EVENT_CATEGORY:
410 case LTTV_FILTER_EVENT_TIME:
411 case LTTV_FILTER_EVENT_TSC:
412 case LTTV_FILTER_EVENT_FIELD:
413 return LTTV_FILTER_EVENT;
414 break;
415 default:
416 return -1;
417 }
84a333d6 418}
419
150f0d33 420/**
421 * Applies the '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 */
83aa92fc 427gboolean lttv_apply_op_eq_uint64(gpointer v1, char* v2) {
428
429 guint64* r = (guint64*) v1;
430 guint64 l = atoi(v2);
431 return (*r == l);
432
433}
150f0d33 434
5b729fcf 435/**
436 * Applies the 'equal' operator to the
47aa6e58 437 * specified structure and value
438 * @param v1 left member of comparison
439 * @param v2 right member of comparison
5b729fcf 440 * @return success/failure of operation
441 */
83aa92fc 442gboolean lttv_apply_op_eq_uint32(gpointer v1, char* v2) {
443 guint32* r = (guint32*) v1;
444 guint32 l = atoi(v2);
445 return (*r == l);
446}
5b729fcf 447
448/**
449 * Applies the 'equal' operator to the
47aa6e58 450 * specified structure and value
451 * @param v1 left member of comparison
452 * @param v2 right member of comparison
5b729fcf 453 * @return success/failure of operation
454 */
83aa92fc 455gboolean lttv_apply_op_eq_uint16(gpointer v1, char* v2) {
456 guint16* r = (guint16*) v1;
457 guint16 l = atoi(v2);
458 return (*r == l);
459}
5b729fcf 460
461/**
462 * Applies the 'equal' operator to the
47aa6e58 463 * specified structure and value
464 * @param v1 left member of comparison
465 * @param v2 right member of comparison
5b729fcf 466 * @return success/failure of operation
467 */
83aa92fc 468gboolean lttv_apply_op_eq_double(gpointer v1, char* v2) {
469 double* r = (double*) v1;
470 double l = atof(v2);
471 return (*r == l);
472}
5b729fcf 473
474/**
475 * Applies the 'equal' 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 */
83aa92fc 481gboolean lttv_apply_op_eq_string(gpointer v1, char* v2) {
482 char* r = (char*) v1;
80f9611a 483 return (!g_strcasecmp(r,v2));
83aa92fc 484}
150f0d33 485
486/**
487 * Applies the 'not equal' operator to the
47aa6e58 488 * specified structure and value
489 * @param v1 left member of comparison
490 * @param v2 right member of comparison
150f0d33 491 * @return success/failure of operation
492 */
83aa92fc 493gboolean lttv_apply_op_ne_uint64(gpointer v1, char* v2) {
494 guint64* r = (guint64*) v1;
495 guint64 l = atoi(v2);
496 return (*r != l);
497}
150f0d33 498
5b729fcf 499/**
500 * Applies the 'not equal' operator to the
47aa6e58 501 * specified structure and value
502 * @param v1 left member of comparison
503 * @param v2 right member of comparison
5b729fcf 504 * @return success/failure of operation
505 */
83aa92fc 506gboolean lttv_apply_op_ne_uint32(gpointer v1, char* v2) {
507 guint32* r = (guint32*) v1;
508 guint32 l = atoi(v2);
509 return (*r != l);
510}
5b729fcf 511
512/**
513 * Applies the 'not equal' operator to the
47aa6e58 514 * specified structure and value
515 * @param v1 left member of comparison
516 * @param v2 right member of comparison
5b729fcf 517 * @return success/failure of operation
518 */
83aa92fc 519gboolean lttv_apply_op_ne_uint16(gpointer v1, char* v2) {
520 guint16* r = (guint16*) v1;
521 guint16 l = atoi(v2);
522 return (*r != l);
523}
5b729fcf 524
525/**
526 * Applies the 'not equal' operator to the
47aa6e58 527 * specified structure and value
528 * @param v1 left member of comparison
529 * @param v2 right member of comparison
5b729fcf 530 * @return success/failure of operation
531 */
83aa92fc 532gboolean lttv_apply_op_ne_double(gpointer v1, char* v2) {
533 double* r = (double*) v1;
534 double l = atof(v2);
535 return (*r != l);
536}
5b729fcf 537
538/**
539 * Applies the 'not equal' operator to the
47aa6e58 540 * specified structure and value
541 * @param v1 left member of comparison
542 * @param v2 right member of comparison
5b729fcf 543 * @return success/failure of operation
544 */
83aa92fc 545gboolean lttv_apply_op_ne_string(gpointer v1, char* v2) {
546 char* r = (char*) v1;
80f9611a 547 return (g_strcasecmp(r,v2));
83aa92fc 548}
150f0d33 549
550/**
551 * Applies the 'lower than' operator to the
47aa6e58 552 * specified structure and value
553 * @param v1 left member of comparison
554 * @param v2 right member of comparison
150f0d33 555 * @return success/failure of operation
556 */
83aa92fc 557gboolean lttv_apply_op_lt_uint64(gpointer v1, char* v2) {
558 guint64* r = (guint64*) v1;
559 guint64 l = atoi(v2);
560 return (*r < l);
561}
150f0d33 562
5b729fcf 563/**
564 * Applies the 'lower than' operator to the
47aa6e58 565 * specified structure and value
566 * @param v1 left member of comparison
567 * @param v2 right member of comparison
5b729fcf 568 * @return success/failure of operation
569 */
83aa92fc 570gboolean lttv_apply_op_lt_uint32(gpointer v1, char* v2) {
571 guint32* r = (guint32*) v1;
572 guint32 l = atoi(v2);
573 return (*r < l);
574}
5b729fcf 575
576/**
577 * Applies the 'lower than' operator to the
47aa6e58 578 * specified structure and value
579 * @param v1 left member of comparison
580 * @param v2 right member of comparison
5b729fcf 581 * @return success/failure of operation
582 */
83aa92fc 583gboolean lttv_apply_op_lt_uint16(gpointer v1, char* v2) {
584 guint16* r = (guint16*) v1;
585 guint16 l = atoi(v2);
586 return (*r < l);
587}
5b729fcf 588
589/**
590 * Applies the 'lower than' operator to the
47aa6e58 591 * specified structure and value
592 * @param v1 left member of comparison
593 * @param v2 right member of comparison
5b729fcf 594 * @return success/failure of operation
595 */
83aa92fc 596gboolean lttv_apply_op_lt_double(gpointer v1, char* v2) {
597 double* r = (double*) v1;
598 double l = atof(v2);
599 return (*r < l);
600}
5b729fcf 601
602/**
603 * Applies the 'lower than' operator to the
47aa6e58 604 * specified structure and value
605 * @param v1 left member of comparison
606 * @param v2 right member of comparison
5b729fcf 607 * @return success/failure of operation
608 */
83aa92fc 609gboolean lttv_apply_op_le_uint64(gpointer v1, char* v2) {
610 guint64* r = (guint64*) v1;
611 guint64 l = atoi(v2);
612 return (*r <= l);
613}
150f0d33 614
615/**
616 * Applies the 'lower or equal' operator to the
47aa6e58 617 * specified structure and value
618 * @param v1 left member of comparison
619 * @param v2 right member of comparison
150f0d33 620 * @return success/failure of operation
621 */
83aa92fc 622gboolean lttv_apply_op_le_uint32(gpointer v1, char* v2) {
623 guint32* r = (guint32*) v1;
624 guint32 l = atoi(v2);
625 return (*r <= l);
626}
150f0d33 627
5b729fcf 628/**
629 * Applies the 'lower or equal' operator to the
47aa6e58 630 * specified structure and value
631 * @param v1 left member of comparison
632 * @param v2 right member of comparison
5b729fcf 633 * @return success/failure of operation
634 */
83aa92fc 635gboolean lttv_apply_op_le_uint16(gpointer v1, char* v2) {
636 guint16* r = (guint16*) v1;
637 guint16 l = atoi(v2);
638 return (*r <= l);
639}
5b729fcf 640
641/**
642 * Applies the 'lower or equal' operator to the
47aa6e58 643 * specified structure and value
644 * @param v1 left member of comparison
645 * @param v2 right member of comparison
5b729fcf 646 * @return success/failure of operation
647 */
83aa92fc 648gboolean lttv_apply_op_le_double(gpointer v1, char* v2) {
649 double* r = (double*) v1;
650 double l = atof(v2);
651 return (*r <= l);
652}
5b729fcf 653
654/**
83aa92fc 655 * Applies the 'greater than' operator to the
47aa6e58 656 * specified structure and value
657 * @param v1 left member of comparison
658 * @param v2 right member of comparison
5b729fcf 659 * @return success/failure of operation
660 */
83aa92fc 661gboolean lttv_apply_op_gt_uint64(gpointer v1, char* v2) {
662 guint64* r = (guint64*) v1;
663 guint64 l = atoi(v2);
664 return (*r > l);
665}
150f0d33 666
667/**
668 * Applies the 'greater than' operator to the
47aa6e58 669 * specified structure and value
670 * @param v1 left member of comparison
671 * @param v2 right member of comparison
150f0d33 672 * @return success/failure of operation
673 */
83aa92fc 674gboolean lttv_apply_op_gt_uint32(gpointer v1, char* v2) {
675 guint32* r = (guint32*) v1;
676 guint32 l = atoi(v2);
677 return (*r > l);
678}
150f0d33 679
5b729fcf 680/**
681 * Applies the 'greater than' operator to the
47aa6e58 682 * specified structure and value
683 * @param v1 left member of comparison
684 * @param v2 right member of comparison
5b729fcf 685 * @return success/failure of operation
686 */
83aa92fc 687gboolean lttv_apply_op_gt_uint16(gpointer v1, char* v2) {
688 guint16* r = (guint16*) v1;
689 guint16 l = atoi(v2);
690 return (*r > l);
691}
5b729fcf 692
693/**
694 * Applies the 'greater than' operator to the
47aa6e58 695 * specified structure and value
696 * @param v1 left member of comparison
697 * @param v2 right member of comparison
5b729fcf 698 * @return success/failure of operation
699 */
83aa92fc 700gboolean lttv_apply_op_gt_double(gpointer v1, char* v2) {
701 double* r = (double*) v1;
702 double l = atof(v2);
703 return (*r > l);
704}
5b729fcf 705
706/**
83aa92fc 707 * Applies the 'greater or equal' operator to the
47aa6e58 708 * specified structure and value
709 * @param v1 left member of comparison
710 * @param v2 right member of comparison
5b729fcf 711 * @return success/failure of operation
712 */
83aa92fc 713gboolean lttv_apply_op_ge_uint64(gpointer v1, char* v2) {
714 guint64* r = (guint64*) v1;
715 guint64 l = atoi(v2);
716 return (*r >= l);
717}
150f0d33 718
719/**
720 * Applies the 'greater or equal' operator to the
47aa6e58 721 * specified structure and value
722 * @param v1 left member of comparison
723 * @param v2 right member of comparison
150f0d33 724 * @return success/failure of operation
725 */
83aa92fc 726gboolean lttv_apply_op_ge_uint32(gpointer v1, char* v2) {
727 guint32* r = (guint32*) v1;
728 guint32 l = atoi(v2);
729 return (*r >= l);
730}
150f0d33 731
5b729fcf 732/**
733 * Applies the 'greater or equal' operator to the
47aa6e58 734 * specified structure and value
735 * @param v1 left member of comparison
736 * @param v2 right member of comparison
5b729fcf 737 * @return success/failure of operation
738 */
83aa92fc 739gboolean lttv_apply_op_ge_uint16(gpointer v1, char* v2) {
740 guint16* r = (guint16*) v1;
741 guint16 l = atoi(v2);
742 return (*r >= l);
743}
150f0d33 744
5b729fcf 745/**
746 * Applies the 'greater or equal' operator to the
47aa6e58 747 * specified structure and value
748 * @param v1 left member of comparison
749 * @param v2 right member of comparison
5b729fcf 750 * @return success/failure of operation
751 */
83aa92fc 752gboolean lttv_apply_op_ge_double(gpointer v1, char* v2) {
753 double* r = (double*) v1;
754 double l = atof(v2);
755 return (*r >= l);
756}
150f0d33 757
758
759/**
760 * Makes a copy of the current filter tree
761 * @param tree pointer to the current tree
762 * @return new copy of the filter tree
763 */
764LttvFilterTree*
765lttv_filter_tree_clone(LttvFilterTree* tree) {
766
8c89f5a8 767 LttvFilterTree* newtree = lttv_filter_tree_new();
150f0d33 768
8c89f5a8 769 newtree->node = tree->node;
770
771 newtree->left = tree->left;
772 if(newtree->left == LTTV_TREE_NODE) {
773 newtree->l_child.t = lttv_filter_tree_clone(tree->l_child.t);
774 } else if(newtree->left == LTTV_TREE_LEAF) {
775 newtree->l_child.leaf = lttv_simple_expression_new();
776 newtree->l_child.leaf->field = tree->l_child.leaf->field;
777 newtree->l_child.leaf->offset = tree->l_child.leaf->offset;
778 newtree->l_child.leaf->op = tree->l_child.leaf->op;
779 newtree->l_child.leaf->value = g_strconcat(tree->l_child.leaf->value);
780 }
781
782 newtree->right = tree->right;
783 if(newtree->right == LTTV_TREE_NODE) {
784 newtree->r_child.t = lttv_filter_tree_clone(tree->r_child.t);
785 } else if(newtree->right == LTTV_TREE_LEAF) {
786 newtree->r_child.leaf = lttv_simple_expression_new();
787 newtree->r_child.leaf->field = tree->r_child.leaf->field;
788 newtree->r_child.leaf->offset = tree->r_child.leaf->offset;
789 newtree->r_child.leaf->op = tree->r_child.leaf->op;
790 newtree->r_child.leaf->value = g_strconcat(tree->r_child.leaf->value);
791 }
792
793 return newtree;
794
150f0d33 795}
796
797/**
798 * Makes a copy of the current filter
799 * @param filter pointer to the current filter
800 * @return new copy of the filter
801 */
802LttvFilter*
803lttv_filter_clone(LttvFilter* filter) {
804
805
806 LttvFilter* newfilter = g_new(LttvFilter,1);
807
808 // newfilter->expression = g_new(char,1)
809 strcpy(newfilter->expression,filter->expression);
810
811 newfilter->head = lttv_filter_tree_clone(filter->head);
812
813 return newfilter;
814
815}
816
817
84a333d6 818/**
819 * Creates a new lttv_filter
31452f49 820 * @param expression filtering options string
821 * @param t pointer to the current LttvTrace
84a333d6 822 * @return the current lttv_filter or NULL if error
31452f49 823 */
2ea36caf 824LttvFilter*
5f185a2b 825lttv_filter_new() {
a4c292d4 826
5f185a2b 827 LttvFilter* filter = g_new(LttvFilter,1);
828 filter->expression = NULL;
829 filter->head = NULL;
830
831}
a4c292d4 832
8c89f5a8 833/**
834 * Updates the current LttvFilter by building
835 * its tree based upon the expression string
836 * @param filter pointer to the current LttvFilter
837 * @return Failure/Success of operation
838 */
5f185a2b 839gboolean
840lttv_filter_update(LttvFilter* filter) {
841
842 g_print("filter::lttv_filter_new()\n"); /* debug */
843
844 if(filter->expression == NULL) return FALSE;
845
a4c292d4 846 unsigned
847 i,
91ad3f0a 848 p_nesting=0, /* parenthesis nesting value */
a4c292d4 849 b=0; /* current breakpoint in expression string */
1601b365 850
851 /* trees */
5b729fcf 852 LttvFilterTree
1601b365 853 *tree = lttv_filter_tree_new(), /* main tree */
854 *subtree = NULL, /* buffer for subtrees */
855 *t1, /* buffer #1 */
856 *t2; /* buffer #2 */
857
5f185a2b 858 /*
859 * the filter
860 * If the tree already exists,
861 * destroy it and build a new one
862 */
863 if(filter->head != NULL) lttv_filter_tree_destroy(filter->head);
864 filter->head = tree;
865
1601b365 866 /*
867 * Tree Stack
f4e9dd16 868 * each element of the list
869 * is a sub tree created
870 * by the use of parenthesis in the
871 * global expression. The final tree
1601b365 872 * will be the one left at the root of
f4e9dd16 873 * the list
874 */
18d1226f 875 GPtrArray *tree_stack = g_ptr_array_new();
876 g_ptr_array_add( tree_stack,(gpointer) tree );
f4e9dd16 877
a4c292d4 878 /* temporary values */
0769c82f 879 GString *a_field_component = g_string_new("");
f4e9dd16 880 GPtrArray *a_field_path = NULL;
881
389ba50e 882 LttvSimpleExpression* a_simple_expression = lttv_simple_expression_new();
0769c82f 883
a4c292d4 884 /*
885 * Parse entire expression and construct
886 * the binary tree. There are two steps
887 * in browsing that string
f4e9dd16 888 * 1. finding boolean ops " &,|,^,! " and parenthesis " {,(,[,],),} "
a4c292d4 889 * 2. finding simple expressions
0769c82f 890 * - field path ( separated by dots )
a4c292d4 891 * - op ( >, <, =, >=, <=, !=)
0769c82f 892 * - value ( integer, string ... )
893 * To spare computing time, the whole
894 * string is parsed in this loop for a
895 * O(n) complexity order.
1601b365 896 *
18d1226f 897 * When encountering logical op &,|,^
898 * 1. parse the last value if any
899 * 2. create a new tree
900 * 3. add the expression (simple exp, or exp (subtree)) to the tree
901 * 4. concatenate this tree with the current tree on top of the stack
902 * When encountering math ops >,>=,<,<=,=,!=
903 * 1. add to op to the simple expression
904 * 2. concatenate last field component to field path
905 * When encountering concatening ops .
906 * 1. concatenate last field component to field path
907 * When encountering opening parenthesis (,{,[
908 * 1. create a new subtree on top of tree stack
909 * When encountering closing parenthesis ),},]
910 * 1. add the expression on right child of the current tree
911 * 2. the subtree is completed, allocate a new subtree
912 * 3. pop the tree value from the tree stack
913 */
914
f4e9dd16 915 a_field_path = g_ptr_array_new();
80f9611a 916// g_ptr_array_set_size(a_field_path,2); /* by default, recording 2 field expressions */
f4e9dd16 917
73050a5f 918
919 g_print("expression: %s\n",filter->expression);
920 g_print("strlen(expression): %i\n",strlen(filter->expression));
5f185a2b 921 for(i=0;i<strlen(filter->expression);i++) {
922 // debug
923 g_print("%c ",filter->expression[i]);
924 switch(filter->expression[i]) {
a4c292d4 925 /*
926 * logical operators
927 */
928 case '&': /* and */
aa4600f3 929
5b729fcf 930 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 931 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
18d1226f 932 t2 = lttv_filter_tree_new();
0cdc2470 933 t2->node = LTTV_LOGICAL_AND;
bb87caa7 934 if(subtree != NULL) { /* append subtree to current tree */
18d1226f 935 t2->left = LTTV_TREE_NODE;
936 t2->l_child.t = subtree;
f4e9dd16 937 subtree = NULL;
18d1226f 938 t1->right = LTTV_TREE_NODE;
410c83da 939 t1->r_child.t = t2;
bb87caa7 940 } else { /* append a simple expression */
73050a5f 941 a_simple_expression->value = g_string_free(a_field_component,FALSE);
18d1226f 942 a_field_component = g_string_new("");
943 t2->left = LTTV_TREE_LEAF;
0cdc2470 944 t2->l_child.leaf = a_simple_expression;
389ba50e 945 a_simple_expression = lttv_simple_expression_new();
18d1226f 946 t1->right = LTTV_TREE_NODE;
410c83da 947 t1->r_child.t = t2;
f4e9dd16 948 }
f4e9dd16 949 break;
aa4600f3 950
a4c292d4 951 case '|': /* or */
aa4600f3 952
2ea36caf 953 t1 = (LttvFilter*)g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 954 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
1601b365 955 t2 = lttv_filter_tree_new();
0cdc2470 956 t2->node = LTTV_LOGICAL_OR;
bb87caa7 957 if(subtree != NULL) { /* append subtree to current tree */
1601b365 958 t2->left = LTTV_TREE_NODE;
959 t2->l_child.t = subtree;
960 subtree = NULL;
961 t1->right = LTTV_TREE_NODE;
962 t1->r_child.t = t2;
bb87caa7 963 } else { /* append a simple expression */
73050a5f 964 a_simple_expression->value = g_string_free(a_field_component,FALSE);
1601b365 965 a_field_component = g_string_new("");
966 t2->left = LTTV_TREE_LEAF;
0cdc2470 967 t2->l_child.leaf = a_simple_expression;
389ba50e 968 a_simple_expression = lttv_simple_expression_new();
1601b365 969 t1->right = LTTV_TREE_NODE;
970 t1->r_child.t = t2;
971 }
f4e9dd16 972 break;
aa4600f3 973
a4c292d4 974 case '^': /* xor */
aa4600f3 975
2ea36caf 976 t1 = (LttvFilter*)g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 977 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
1601b365 978 t2 = lttv_filter_tree_new();
0cdc2470 979 t2->node = LTTV_LOGICAL_XOR;
bb87caa7 980 if(subtree != NULL) { /* append subtree to current tree */
1601b365 981 t2->left = LTTV_TREE_NODE;
982 t2->l_child.t = subtree;
983 subtree = NULL;
984 t1->right = LTTV_TREE_NODE;
985 t1->r_child.t = t2;
bb87caa7 986 } else { /* append a simple expression */
73050a5f 987 a_simple_expression->value = g_string_free(a_field_component,FALSE);
1601b365 988 a_field_component = g_string_new("");
989 t2->left = LTTV_TREE_LEAF;
0cdc2470 990 t2->l_child.leaf = a_simple_expression;
389ba50e 991 a_simple_expression = lttv_simple_expression_new();
1601b365 992 t1->right = LTTV_TREE_NODE;
993 t1->r_child.t = t2;
994 }
a4c292d4 995 break;
aa4600f3 996
a4c292d4 997 case '!': /* not, or not equal (math op) */
aa4600f3 998
5f185a2b 999 if(filter->expression[i+1] == '=') { /* != */
0cdc2470 1000 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
389ba50e 1001 parse_field_path(a_field_path,a_simple_expression);
0cdc2470 1002 a_field_component = g_string_new("");
aa4600f3 1003 assign_operator(a_simple_expression,LTTV_FIELD_NE);
1004 i++;
a4c292d4 1005 } else { /* ! */
1601b365 1006 // g_print("%s\n",a_field_component);
1007 // a_field_component = g_string_new("");
2ea36caf 1008 t1 = (LttvFilter*)g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 1009 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
1601b365 1010 t2 = lttv_filter_tree_new();
0cdc2470 1011 t2->node = LTTV_LOGICAL_NOT;
1601b365 1012 t1->right = LTTV_TREE_NODE;
1013 t1->r_child.t = t2;
a4c292d4 1014 }
1015 break;
aa4600f3 1016
a4c292d4 1017 case '(': /* start of parenthesis */
91ad3f0a 1018 case '[':
1019 case '{':
aa4600f3 1020
91ad3f0a 1021 p_nesting++; /* incrementing parenthesis nesting value */
1601b365 1022 t1 = lttv_filter_tree_new();
1023 g_ptr_array_add( tree_stack,(gpointer) t1 );
a4c292d4 1024 break;
aa4600f3 1025
a4c292d4 1026 case ')': /* end of parenthesis */
91ad3f0a 1027 case ']':
1028 case '}':
aa4600f3 1029
91ad3f0a 1030 p_nesting--; /* decrementing parenthesis nesting value */
18d1226f 1031 if(p_nesting<0 || tree_stack->len<2) {
f4e9dd16 1032 g_warning("Wrong filtering options, the string\n\"%s\"\n\
5f185a2b 1033 is not valid due to parenthesis incorrect use",filter->expression);
1034 return FALSE;
f4e9dd16 1035 }
18d1226f 1036
1037 g_assert(tree_stack->len>0);
bb87caa7 1038 if(subtree != NULL) { /* append subtree to current tree */
18d1226f 1039 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 1040 while(t1->right != LTTV_TREE_IDLE && t1->right != LTTV_TREE_LEAF) {
18d1226f 1041 g_assert(t1!=NULL && t1->r_child.t != NULL);
1042 t1 = t1->r_child.t;
1043 }
1044 t1->right = LTTV_TREE_NODE;
1045 t1->r_child.t = subtree;
1046 subtree = g_ptr_array_index(tree_stack,tree_stack->len-1);
1047 g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
bb87caa7 1048 } else { /* assign subtree as current tree */
73050a5f 1049 a_simple_expression->value = g_string_free(a_field_component,FALSE);
18d1226f 1050 a_field_component = g_string_new("");
1051 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 1052 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
18d1226f 1053 t1->right = LTTV_TREE_LEAF;
0cdc2470 1054 t1->r_child.leaf = a_simple_expression;
389ba50e 1055 a_simple_expression = lttv_simple_expression_new();
18d1226f 1056 subtree = g_ptr_array_index(tree_stack,tree_stack->len-1);
1601b365 1057 g_assert(subtree != NULL);
18d1226f 1058 g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
1059 }
a4c292d4 1060 break;
1061
1062 /*
1063 * mathematic operators
1064 */
1065 case '<': /* lower, lower or equal */
aa4600f3 1066
1067 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1068 parse_field_path(a_field_path,a_simple_expression);
1069 a_field_component = g_string_new("");
5f185a2b 1070 if(filter->expression[i+1] == '=') { /* <= */
a4c292d4 1071 i++;
bb87caa7 1072 assign_operator(a_simple_expression,LTTV_FIELD_LE);
1073 } else assign_operator(a_simple_expression,LTTV_FIELD_LT);
aa4600f3 1074 break;
1075
1076 case '>': /* higher, higher or equal */
1077
1078 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
389ba50e 1079 parse_field_path(a_field_path,a_simple_expression);
f4e9dd16 1080 a_field_component = g_string_new("");
5f185a2b 1081 if(filter->expression[i+1] == '=') { /* >= */
a4c292d4 1082 i++;
bb87caa7 1083 assign_operator(a_simple_expression,LTTV_FIELD_GE);
1084 } else assign_operator(a_simple_expression,LTTV_FIELD_GT);
aa4600f3 1085 break;
1086
a4c292d4 1087 case '=': /* equal */
aa4600f3 1088
f4e9dd16 1089 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
389ba50e 1090 parse_field_path(a_field_path,a_simple_expression);
f4e9dd16 1091 a_field_component = g_string_new("");
aa4600f3 1092 assign_operator(a_simple_expression,LTTV_FIELD_EQ);
a4c292d4 1093 break;
aa4600f3 1094
0769c82f 1095 /*
1096 * Field concatening caracter
1097 */
1098 case '.': /* dot */
aa4600f3 1099
bb87caa7 1100 /*
1101 * divide field expression into elements
1102 * in a_field_path array.
1103 */
80f9611a 1104// if(a_simple_expression->op == NULL) {
bb87caa7 1105 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1106 a_field_component = g_string_new("");
80f9611a 1107// }
0769c82f 1108 break;
aa4600f3 1109
a4c292d4 1110 default: /* concatening current string */
73050a5f 1111 // fprintf(stderr,"%i>> %p:%s et %p\n",i,a_field_component,a_field_component->str,filter->expression[i]);
1112 g_string_append_c(a_field_component,filter->expression[i]);
a4c292d4 1113 }
1114 }
1601b365 1115
1116 g_print("subtree:%p, tree:%p, t1:%p, t2:%p\n",subtree,tree,t1,t2);
0cdc2470 1117 g_print("stack size: %i\n",tree_stack->len);
1118
1119 /*
1120 * Preliminary check to see
1121 * if tree was constructed correctly
1122 */
1123 if( p_nesting>0 ) {
1124 g_warning("Wrong filtering options, the string\n\"%s\"\n\
5f185a2b 1125 is not valid due to parenthesis incorrect use",filter->expression);
1126 return FALSE;
0cdc2470 1127 }
1128
1129 if(tree_stack->len != 1) /* only root tree should remain */
5f185a2b 1130 return FALSE;
1601b365 1131
410c83da 1132 /* processing last element of expression */
410c83da 1133 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
2a734d8e 1134 while(t1->right != LTTV_TREE_IDLE) t1 = t1->r_child.t;
410c83da 1135 if(subtree != NULL) { /* add the subtree */
1136 t1->right = LTTV_TREE_NODE;
0cdc2470 1137 t1->r_child.t = subtree;
410c83da 1138 subtree = NULL;
1139 } else { /* add a leaf */
73050a5f 1140 a_simple_expression->value = g_string_free(a_field_component,FALSE);
1141// a_field_component = g_string_new("");
410c83da 1142 t1->right = LTTV_TREE_LEAF;
0cdc2470 1143 t1->r_child.leaf = a_simple_expression;
2ea36caf 1144 /*
1145 * FIXME: is it really necessary to reallocate
1146 * LttvSimpleExpression at this point ??
1147 */
73050a5f 1148// a_simple_expression = lttv_simple_expression_new();
410c83da 1149 }
1150
73050a5f 1151 /* free the pointer array */
1152 g_assert(a_field_path->len == 0);
1153 g_ptr_array_free(a_field_path,TRUE);
1154
410c83da 1155 g_assert(tree != NULL);
1156 g_assert(subtree == NULL);
a4c292d4 1157
73050a5f 1158// lttv_print_tree(filter->head) ;
aa4600f3 1159
80f9611a 1160 g_print("ended update tree!\n");
5f185a2b 1161 return TRUE;
80f9611a 1162
5f185a2b 1163// return filter;
410c83da 1164
31452f49 1165}
1166
8c89f5a8 1167/**
1168 * Destroy the current LttvFilter
1169 * @param filter pointer to the current LttvFilter
1170 */
1da1525d 1171void
2ea36caf 1172lttv_filter_destroy(LttvFilter* filter) {
5f185a2b 1173
1174 g_free(filter->expression);
1175 lttv_filter_tree_destroy(filter->head);
1176 g_free(filter);
1177
1da1525d 1178}
1179
150f0d33 1180/**
1181 * Assign a new tree for the current expression
1182 * or sub expression
1183 * @return pointer of LttvFilterTree
1184 */
5f185a2b 1185LttvFilterTree*
1186lttv_filter_tree_new() {
150f0d33 1187 LttvFilterTree* tree;
1188
1189 tree = g_new(LttvFilter,1);
1190 tree->node = 0; //g_new(lttv_expression,1);
150f0d33 1191 tree->left = LTTV_TREE_IDLE;
1192 tree->right = LTTV_TREE_IDLE;
1193
1194 return tree;
1195}
1196
80f9611a 1197/**
1198 * Append a new expression to the expression
1199 * defined in the current filter
1200 * @param filter pointer to the current LttvFilter
1201 * @param expression string that must be appended
1202 */
1203void lttv_filter_append_expression(LttvFilter* filter, char *expression) {
1204
1205 if(expression == NULL) return;
1206 if(filter == NULL) {
1207 filter = lttv_filter_new();
1208 filter->expression = expression;
1209 } else if(filter->expression == NULL) {
1210 filter->expression = expression;
1211 } else {
1212 filter->expression = g_strconcat(filter->expression,"&",expression);
1213 }
1214
1215 lttv_filter_update(filter);
1216
1217}
1218
1219/**
1220 * Clear the filter expression from the
1221 * current filter and sets its pointer to NULL
1222 * @param filter pointer to the current LttvFilter
1223 */
1224void lttv_filter_clear_expression(LttvFilter* filter) {
1225
1226 if(filter->expression != NULL) {
1227 g_free(filter->expression);
1228 filter->expression = NULL;
1229 }
1230
1231}
1232
150f0d33 1233/**
1234 * Destroys the tree and his sub-trees
1235 * @param tree Tree which must be destroyed
1236 */
5f185a2b 1237void
1238lttv_filter_tree_destroy(LttvFilterTree* tree) {
150f0d33 1239
1240 if(tree == NULL) return;
1241
1242 if(tree->left == LTTV_TREE_LEAF) g_free(tree->l_child.leaf);
1243 else if(tree->left == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->l_child.t);
1244
1245 if(tree->right == LTTV_TREE_LEAF) g_free(tree->r_child.leaf);
1246 else if(tree->right == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->r_child.t);
1247
1248 g_free(tree->node);
1249 g_free(tree);
1250}
1251
84a333d6 1252/**
80f9611a 1253 * Global parsing function for the current
1254 * LttvFilterTree
1255 * @param tree pointer to the current LttvFilterTree
1256 * @param event current LttEvent, NULL if not used
1257 * @param tracefile current LttTracefile, NULL if not used
1258 * @param trace current LttTrace, NULL if not used
1259 * @param state current LttvProcessState, NULL if not used
84a333d6 1260 */
31452f49 1261gboolean
80f9611a 1262lttv_filter_tree_parse(
1263 LttvFilterTree* t,
1264 LttEvent* event,
1265 LttTracefile* tracefile,
1266 LttTrace* trace,
1267 LttvProcessState* state
1268 /*,...*/)
1269{
0769c82f 1270
80f9611a 1271 /*
1601b365 1272 * Each tree is parsed in inorder.
1273 * This way, it's possible to apply the left filter of the
1274 * tree, then decide whether or not the right branch should
1275 * be parsed depending on the linking logical operator
1276 *
80f9611a 1277 * Each node consists in a
1278 * 1. logical operator
1279 * 2. left child ( node or simple expression )
1280 * 3. right child ( node or simple expression )
1281 *
1282 * When the child is a simple expression, we must
1283 * before all determine if the expression refers to
1284 * a structure which is whithin observation ( not NULL ).
1285 * -If so, the expression is evaluated.
1286 * -If not, the result is set to TRUE since this particular
1287 * operation does not interfere with the lttv structure
1288 *
1289 * The result of each simple expression will directly
1290 * affect the next branch. This way, depending on
1291 * the linking logical operator, the parser will decide
1292 * to explore or not the next branch.
1293 * 1. AND OPERATOR
1294 * -If result of left branch is 0 / FALSE
1295 * then don't explore right branch and return 0;
1296 * -If result of left branch is 1 / TRUE then explore
1297 * 2. OR OPERATOR
1298 * -If result of left branch is 1 / TRUE
1299 * then don't explore right branch and return 1;
1300 * -If result of left branch is 0 / FALSE then explore
1301 * 3. XOR OPERATOR
1302 * -Result of left branchwill not affect exploration of
1303 * right branch
1601b365 1304 */
73050a5f 1305 g_print("filter::lttv_parse_tree(...)\n");
1306
80f9611a 1307 gboolean lresult = FALSE, rresult = FALSE;
0769c82f 1308
80f9611a 1309 /*
1310 * Parse left branch
1311 */
1312 if(t->left == LTTV_TREE_NODE) lresult = lttv_filter_tree_parse(t->l_child.t,event,tracefile,trace,state);
5b729fcf 1313 else if(t->left == LTTV_TREE_LEAF) {
80f9611a 1314 //g_print("%p: left is %i %p %s\n",t,t->l_child.leaf->field,t->l_child.leaf->op,t->l_child.leaf->value);
1315 char* v;
1316 g_assert(v = t->l_child.leaf->value);
1317 switch(t->l_child.leaf->field) {
1318
1319 case LTTV_FILTER_TRACE_NAME:
1320 if(trace == NULL) lresult = TRUE;
1321 else lresult = t->l_child.leaf->op((gpointer)ltt_trace_name(trace),v);
1322 break;
1323 case LTTV_FILTER_TRACEFILE_NAME:
1324 if(tracefile == NULL) lresult = TRUE;
1325 else lresult = t->l_child.leaf->op((gpointer)ltt_tracefile_name(tracefile),v);
1326 break;
1327 case LTTV_FILTER_STATE_PID:
1328 if(state == NULL) lresult = TRUE;
1329 else lresult = t->l_child.leaf->op((gpointer)&state->pid,v);
1330 break;
1331 case LTTV_FILTER_STATE_PPID:
1332 if(state == NULL) lresult = TRUE;
1333 else lresult = t->l_child.leaf->op((gpointer)&state->ppid,v);
1334 break;
1335 case LTTV_FILTER_STATE_CT:
1336 if(state == NULL) lresult = TRUE;
1337 else {
1338 double val = ltt_time_to_double(state->creation_time);
1339 lresult = t->l_child.leaf->op((gpointer)&val,v);
1340 }
1341 break;
1342 case LTTV_FILTER_STATE_IT:
1343 if(state == NULL) lresult = TRUE;
1344 else {
1345 double val = ltt_time_to_double(state->insertion_time);
1346 lresult = t->l_child.leaf->op((gpointer)&val,v);
1347 }
1348 break;
1349 case LTTV_FILTER_STATE_P_NAME:
1350 /*
1351 * FIXME: Yet to be done ( I think ? )
1352 */
1353 lresult = TRUE;
1354 break;
1355 case LTTV_FILTER_STATE_EX_MODE:
1356 if(state == NULL) lresult = TRUE;
1357 else lresult = t->l_child.leaf->op((gpointer)&state->state->t,v);
1358 break;
1359 case LTTV_FILTER_STATE_EX_SUBMODE:
1360 if(state == NULL) lresult = TRUE;
1361 else lresult = t->l_child.leaf->op((gpointer)&state->state->n,v);
1362 break;
1363 case LTTV_FILTER_STATE_P_STATUS:
1364 if(state == NULL) lresult = TRUE;
1365 else lresult = t->l_child.leaf->op((gpointer)&state->state->s,v);
1366 break;
1367 case LTTV_FILTER_STATE_CPU:
1368 /*
1369 * FIXME: What is the comparison value ?
1370 */
1371 lresult = TRUE;
1372 break;
1373 case LTTV_FILTER_EVENT_NAME:
1374 if(event == NULL) lresult = TRUE;
1375 else lresult = t->l_child.leaf->op((gpointer)ltt_event_eventtype(event),v);
1376 break;
1377
1378 case LTTV_FILTER_EVENT_CATEGORY:
1379 /*
1380 * FIXME: Not yet implemented
1381 */
1382 lresult = TRUE;
1383 break;
1384 case LTTV_FILTER_EVENT_TIME:
1385// if(event == NULL) lresult = TRUE;
1386// else {
1387// double val = ltt_time_to_double(event->event_time);
1388// lresult = t->l_child.leaf->op((gpointer)&val,v);
1389// }
1390 lresult = TRUE;
1391 break;
1392 case LTTV_FILTER_EVENT_TSC:
1393// if(event == NULL) lresult = TRUE;
1394// else {
1395// double val = ltt_time_to_double(event->event_time);
1396// lresult = t->l_child.leaf->op((gpointer)&val,v);
1397// }
1398 /*
1399 * FIXME: Where is event.tsc
1400 */
1401 lresult = TRUE;
1402 break;
1403 case LTTV_FILTER_EVENT_FIELD:
1404 /*
1405 * TODO: Use the offset to
1406 * find the dynamic field
1407 * in the event struct
1408 */
1409 lresult = TRUE;
1410 default:
1411 /*
1412 * This case should never be
1413 * parsed, if so, the whole
1414 * filtering is cancelled
1415 */
1416 g_warning("Error while parsing the filter tree");
1417 return TRUE;
1418 }
0cdc2470 1419 }
80f9611a 1420
1421 /*
1422 * Parse linking operator
1423 * make a cutoff if possible
1424 */
1425 if((t->node & LTTV_LOGICAL_OR) && lresult == TRUE) return TRUE;
1426 if((t->node & LTTV_LOGICAL_AND) && lresult == FALSE) return FALSE;
1427
1428 /*
1429 * Parse right branch
1430 */
1431 if(t->right == LTTV_TREE_NODE) rresult = lttv_filter_tree_parse(t->r_child.t,event,tracefile,trace,state);
5b729fcf 1432 else if(t->right == LTTV_TREE_LEAF) {
80f9611a 1433 //g_print("%p: right is %i %p %s\n",t,t->r_child.leaf->field,t->r_child.leaf->op,t->r_child.leaf->value);
1434 char* v;
1435 g_assert(v = t->r_child.leaf->value);
1436 switch(t->r_child.leaf->field) {
1437
1438 case LTTV_FILTER_TRACE_NAME:
1439 if(trace == NULL) rresult = TRUE;
1440 else rresult = t->r_child.leaf->op((gpointer)ltt_trace_name(trace),v);
1441 break;
1442 case LTTV_FILTER_TRACEFILE_NAME:
1443 if(tracefile == NULL) rresult = TRUE;
1444 else rresult = t->r_child.leaf->op((gpointer)ltt_tracefile_name(tracefile),v);
1445 break;
1446 case LTTV_FILTER_STATE_PID:
1447 if(state == NULL) rresult = TRUE;
1448 else rresult = t->r_child.leaf->op((gpointer)&state->pid,v);
1449 break;
1450 case LTTV_FILTER_STATE_PPID:
1451 if(state == NULL) rresult = TRUE;
1452 else rresult = t->r_child.leaf->op((gpointer)&state->ppid,v);
1453 break;
1454 case LTTV_FILTER_STATE_CT:
1455 if(state == NULL) rresult = TRUE;
1456 else {
1457 double val = ltt_time_to_double(state->creation_time);
1458 rresult = t->r_child.leaf->op((gpointer)&val,v);
1459 }
1460 break;
1461 case LTTV_FILTER_STATE_IT:
1462 if(state == NULL) rresult = TRUE;
1463 else {
1464 double val = ltt_time_to_double(state->insertion_time);
1465 rresult = t->r_child.leaf->op((gpointer)&val,v);
1466 }
1467 break;
1468 case LTTV_FILTER_STATE_P_NAME:
1469 /*
1470 * FIXME: Yet to be done ( I think ? )
1471 */
1472 rresult = TRUE;
1473 break;
1474 case LTTV_FILTER_STATE_EX_MODE:
1475 if(state == NULL) rresult = TRUE;
1476 else rresult = t->r_child.leaf->op((gpointer)&state->state->t,v);
1477 break;
1478 case LTTV_FILTER_STATE_EX_SUBMODE:
1479 if(state == NULL) rresult = TRUE;
1480 else rresult = t->r_child.leaf->op((gpointer)&state->state->n,v);
1481 break;
1482 case LTTV_FILTER_STATE_P_STATUS:
1483 if(state == NULL) rresult = TRUE;
1484 else rresult = t->r_child.leaf->op((gpointer)&state->state->s,v);
1485 break;
1486 case LTTV_FILTER_STATE_CPU:
1487 /*
1488 * FIXME: What is the comparison value ?
1489 */
1490 rresult = TRUE;
1491 break;
1492 case LTTV_FILTER_EVENT_NAME:
1493 if(event == NULL) rresult = TRUE;
1494 else rresult = t->r_child.leaf->op((gpointer)ltt_event_eventtype(event),v);
1495 break;
1496
1497 case LTTV_FILTER_EVENT_CATEGORY:
1498 /*
1499 * FIXME: Not yet implemented
1500 */
1501 rresult = TRUE;
1502 break;
1503 case LTTV_FILTER_EVENT_TIME:
1504// if(event == NULL) rresult = TRUE;
1505// else {
1506// double val = ltt_time_to_double(event->event_time);
1507// rresult = t->r_child.leaf->op((gpointer)&val,v);
1508// }
1509 rresult = TRUE;
1510 break;
1511 case LTTV_FILTER_EVENT_TSC:
1512// if(event == NULL) rresult = TRUE;
1513// else {
1514// double val = ltt_time_to_double(event->event_time);
1515// rresult = t->r_child.leaf->op((gpointer)&val,v);
1516// }
1517 /*
1518 * FIXME: Where is event.tsc
1519 */
1520 rresult = TRUE;
1521 break;
1522 case LTTV_FILTER_EVENT_FIELD:
1523 /*
1524 * TODO: Use the offset to
1525 * find the dynamic field
1526 * in the event struct
1527 */
1528 rresult = TRUE;
1529 default:
1530 /*
1531 * This case should never be
1532 * parsed, if so, this subtree
1533 * is cancelled !
1534 */
1535 g_warning("Error while parsing the filter tree");
1536 return TRUE;
1537 }
0cdc2470 1538 }
5f185a2b 1539
80f9611a 1540 /*
1541 * Apply and return the
1542 * logical link between the
1543 * two operation
1544 */
1545 switch(t->node) {
1546 case LTTV_LOGICAL_OR: return (lresult | rresult);
1547 case LTTV_LOGICAL_AND: return (lresult & rresult);
1548 case LTTV_LOGICAL_NOT: return (!rresult);
1549 case LTTV_LOGICAL_XOR: return (lresult ^ rresult);
1550 default:
1551 /*
1552 * This case should never be
1553 * parsed, if so, this subtree
1554 * is cancelled !
1555 */
1556 return TRUE;
1557 }
0769c82f 1558
80f9611a 1559}
0769c82f 1560
80f9611a 1561/**
1562 * Debug
1563 */
1564void
1565lttv_print_tree(LttvFilterTree* t) {
0769c82f 1566
73050a5f 1567 g_print("node:%p lchild:%p rchild:%p\n",t, //t->l_child.t,t->r_child.t);
80f9611a 1568 (t->left==LTTV_TREE_NODE)?t->l_child.t:NULL,
1569 (t->right==LTTV_TREE_NODE)?t->r_child.t:NULL);
1570 g_print("node type: %i / [left] %i / [right] %i\n",t->node,t->left,t->right);
1571 if(t->left == LTTV_TREE_NODE) lttv_print_tree(t->l_child.t);
1572 else if(t->left == LTTV_TREE_LEAF) {
73050a5f 1573// g_assert(t->l_child.leaf->value != NULL);
80f9611a 1574 g_print("%p: left is %i %p %s\n",t,t->l_child.leaf->field,t->l_child.leaf->op,t->l_child.leaf->value);
0769c82f 1575 }
80f9611a 1576 g_print("1\n");
1577 if(t->right == LTTV_TREE_NODE) lttv_print_tree(t->r_child.t);
1578 else if(t->right == LTTV_TREE_LEAF) {
73050a5f 1579 fprintf(stderr,"leaf!\n");
1580// g_assert(t->r_child.leaf->value != NULL);
1581 fprintf(stderr,"%p: right is %i %p %s\n",t,t->r_child.leaf->field,t->r_child.leaf->op,t->r_child.leaf->value);
80f9611a 1582 }
1583 g_print("end\n");
1584
1585}
1586
1587/**
1588 * Apply the filter to a specific trace
1589 * @param filter the current filter applied
1590 * @param tracefile the trace to apply the filter to
1591 * @return success/failure of operation
0769c82f 1592 */
80f9611a 1593gboolean
1594lttv_filter_tracefile(LttvFilter *filter, LttTracefile *tracefile) {
1595
1596 return lttv_filter_tree_parse(filter->head,NULL,tracefile,NULL,NULL);
1597
31452f49 1598}
1599
1a7fa682 1600gboolean
2ea36caf 1601lttv_filter_tracestate(LttvFilter *filter, LttvTraceState *tracestate) {
341aa948 1602
1603}
1a7fa682 1604
84a333d6 1605/**
1606 * Apply the filter to a specific event
1607 * @param filter the current filter applied
1608 * @param event the event to apply the filter to
1609 * @return success/failure of operation
1610 */
31452f49 1611gboolean
2ea36caf 1612lttv_filter_event(LttvFilter *filter, LttEvent *event) {
31452f49 1613
1614}
1a7fa682 1615
91ad3f0a 1616/**
1617 * Initializes the filter module and specific values
1618 */
1a7fa682 1619static void module_init()
1620{
91ad3f0a 1621
1622 /*
1623 * Quarks initialization
1624 * for hardcoded filtering options
1625 *
1626 * TODO: traceset has no yet been defined
1627 */
1628
1629 /* top fields */
5b729fcf 1630// LTTV_FILTER_EVENT = g_quark_from_string("event");
1631// LTTV_FILTER_TRACE = g_quark_from_string("trace");
1632// LTTV_FILTER_TRACESET = g_quark_from_string("traceset");
1633// LTTV_FILTER_STATE = g_quark_from_string("state");
1634// LTTV_FILTER_TRACEFILE = g_quark_from_string("tracefile");
1a7fa682 1635
91ad3f0a 1636 /* event.name, tracefile.name, trace.name */
5b729fcf 1637// LTTV_FILTER_NAME = g_quark_from_string("name");
91ad3f0a 1638
1639 /* event sub fields */
5b729fcf 1640// LTTV_FILTER_CATEGORY = g_quark_from_string("category");
1641// LTTV_FILTER_TIME = g_quark_from_string("time");
1642// LTTV_FILTER_TSC = g_quark_from_string("tsc");
91ad3f0a 1643
1644 /* state sub fields */
5b729fcf 1645// LTTV_FILTER_PID = g_quark_from_string("pid");
1646// LTTV_FILTER_PPID = g_quark_from_string("ppid");
1647// LTTV_FILTER_C_TIME = g_quark_from_string("creation_time");
1648// LTTV_FILTER_I_TIME = g_quark_from_string("insertion_time");
1649// LTTV_FILTER_P_NAME = g_quark_from_string("process_name");
1650// LTTV_FILTER_EX_MODE = g_quark_from_string("execution_mode");
1651// LTTV_FILTER_EX_SUBMODE = g_quark_from_string("execution_submode");
1652// LTTV_FILTER_P_STATUS = g_quark_from_string("process_status");
1653// LTTV_FILTER_CPU = g_quark_from_string("cpu");
91ad3f0a 1654
1a7fa682 1655}
1656
91ad3f0a 1657/**
1658 * Destroys the filter module and specific values
1659 */
1a7fa682 1660static void module_destroy()
1661{
1662}
1663
1664
91ad3f0a 1665LTTV_MODULE("filter", "Filters traceset and events", \
1666 "Filters traceset and events specifically to user input", \
1a7fa682 1667 module_init, module_destroy)
1668
1669
1670
This page took 0.10446 seconds and 4 git commands to generate.