filter fix
[lttv.git] / ltt / branches / poly / lttv / lttv / filter.c
CommitLineData
9c312311 1/* This file is part of the Linux Trace Toolkit viewer
852f16bb 2 * Copyright (C) 2003-2005 Michel Dagenais and Simon Bouvier-Zappa
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
7e7af7f2 19/*! \file lttv/lttv/filter.c
20 * \brief Defines the core filter of application
21 *
22 * consist in AND, OR and NOT nested expressions, forming a tree with
23 * simple relations as leaves. The simple relations test if a field
24 * in an event is equal, not equal, smaller, smaller or equal, larger, or
25 * larger or equal to a specified value.
26 *
27 * Fields specified in a simple expression can take following
28 * values
29 *
da2e1bfb 30 * \verbatim
31 * LttvTracefileContext{}
7e7af7f2 32 * |->event\
33 * | |->name (String, converted to GQuark)
34 * | |->category (String, not yet implemented)
35 * | |->time (LttTime)
bbd9d557 36 * | |->tsc (LttCycleCount --> uint64)
7e7af7f2 37 * | |->fields
38 * | |->"event name"
39 * | |->"field name"
40 * | |->"sub-field name"
41 * | |->...
42 * | |->"leaf-field name" (field type)
43 * |->tracefile
44 * | |->name (String, converted to GQuark)
45 * |->trace
46 * | |->name (String, converted to GQuark)
47 * |->state
48 * |->pid (uint64)
49 * |->ppid (uint64)
50 * |->creation_time (LttTime)
51 * |->insertion_time (LttTime)
52 * |->process_name (String, converted to GQuark)
53 * |->execution_mode (LttvExecutionMode)
54 * |->execution_submode (LttvExecutionSubmode)
55 * |->process_status (LttvProcessStatus)
da2e1bfb 56 * |->cpu (GQuark)
57 * \endverbatim
150f0d33 58 */
59
60/*
bbd9d557 61 * \todo
150f0d33 62 * - refine switch of expression in multiple uses functions
be66ef34 63 * - remove the idle expressions in the tree
150f0d33 64 */
65
72911c5d 66//#define TEST
be66ef34 67#ifdef TEST
68#include <time.h>
69#include <sys/time.h>
70#endif
71
150f0d33 72#include <lttv/filter.h>
80f9611a 73
74/**
56e29124 75 * @fn LttvSimpleExpression* lttv_simple_expression_new()
76 *
80f9611a 77 * Constructor for LttvSimpleExpression
78 * @return pointer to new LttvSimpleExpression
79 */
80LttvSimpleExpression*
81lttv_simple_expression_new() {
82
83 LttvSimpleExpression* se = g_new(LttvSimpleExpression,1);
84
85 se->field = LTTV_FILTER_UNDEFINED;
86 se->op = NULL;
87 se->offset = 0;
80f9611a 88
89 return se;
90}
91
0769c82f 92/**
7e7af7f2 93 * @fn gboolean lttv_simple_expression_assign_field(GPtrArray*,LttvSimpleExpression*)
56e29124 94 *
0769c82f 95 * Parse through filtering field hierarchy as specified
96 * by user. This function compares each value to
97 * predetermined quarks
98 * @param fp The field path list
bb87caa7 99 * @param se current simple expression
0769c82f 100 * @return success/failure of operation
101 */
102gboolean
9ab5ebd7 103lttv_simple_expression_assign_field(GPtrArray* fp, LttvSimpleExpression* se) {
0769c82f 104
f4e9dd16 105 GString* f = NULL;
73050a5f 106
2b99ec10 107 if(fp->len < 2) return FALSE;
56e29124 108 g_assert(f=g_ptr_array_remove_index(fp,0));
73050a5f 109
47aa6e58 110 /*
111 * Parse through the specified
112 * hardcoded fields.
113 *
114 * Take note however that the
115 * 'event' subfields might change
116 * depending on values specified
117 * in core.xml file. Hence, if
118 * none of the subfields in the
119 * array match the hardcoded
120 * subfields, it will be considered
121 * as a dynamic field
122 */
80f9611a 123 if(!g_strcasecmp(f->str,"trace") ) {
47aa6e58 124 /*
125 * Possible values:
126 * trace.name
127 */
73050a5f 128 g_string_free(f,TRUE);
129 f=g_ptr_array_remove_index(fp,0);
80f9611a 130 if(!g_strcasecmp(f->str,"name")) {
389ba50e 131 se->field = LTTV_FILTER_TRACE_NAME;
132 }
80f9611a 133 } else if(!g_strcasecmp(f->str,"traceset") ) {
47aa6e58 134 /*
135 * FIXME: not yet implemented !
136 */
80f9611a 137 } else if(!g_strcasecmp(f->str,"tracefile") ) {
47aa6e58 138 /*
139 * Possible values:
140 * tracefile.name
141 */
73050a5f 142 g_string_free(f,TRUE);
143 f=g_ptr_array_remove_index(fp,0);
80f9611a 144 if(!g_strcasecmp(f->str,"name")) {
389ba50e 145 se->field = LTTV_FILTER_TRACEFILE_NAME;
146 }
80f9611a 147 } else if(!g_strcasecmp(f->str,"state") ) {
47aa6e58 148 /*
149 * Possible values:
150 * state.pid
151 * state.ppid
152 * state.creation_time
153 * state.insertion_time
154 * state.process_name
155 * state.execution_mode
156 * state.execution_submode
157 * state.process_status
158 * state.cpu
159 */
73050a5f 160 g_string_free(f,TRUE);
161 f=g_ptr_array_remove_index(fp,0);
80f9611a 162 if(!g_strcasecmp(f->str,"pid") ) {
389ba50e 163 se->field = LTTV_FILTER_STATE_PID;
164 }
80f9611a 165 else if(!g_strcasecmp(f->str,"ppid") ) {
389ba50e 166 se->field = LTTV_FILTER_STATE_PPID;
167 }
80f9611a 168 else if(!g_strcasecmp(f->str,"creation_time") ) {
389ba50e 169 se->field = LTTV_FILTER_STATE_CT;
170 }
80f9611a 171 else if(!g_strcasecmp(f->str,"insertion_time") ) {
389ba50e 172 se->field = LTTV_FILTER_STATE_IT;
173 }
80f9611a 174 else if(!g_strcasecmp(f->str,"process_name") ) {
389ba50e 175 se->field = LTTV_FILTER_STATE_P_NAME;
176 }
80f9611a 177 else if(!g_strcasecmp(f->str,"execution_mode") ) {
389ba50e 178 se->field = LTTV_FILTER_STATE_EX_MODE;
179 }
80f9611a 180 else if(!g_strcasecmp(f->str,"execution_submode") ) {
389ba50e 181 se->field = LTTV_FILTER_STATE_EX_SUBMODE;
182 }
80f9611a 183 else if(!g_strcasecmp(f->str,"process_status") ) {
389ba50e 184 se->field = LTTV_FILTER_STATE_P_STATUS;
185 }
80f9611a 186 else if(!g_strcasecmp(f->str,"cpu") ) {
389ba50e 187 se->field = LTTV_FILTER_STATE_CPU;
188 }
80f9611a 189 } else if(!g_strcasecmp(f->str,"event") ) {
389ba50e 190 /*
191 * Possible values:
192 * event.name
193 * event.category
194 * event.time
195 * event.tsc
196 */
73050a5f 197 g_string_free(f,TRUE);
198 f=g_ptr_array_remove_index(fp,0);
80f9611a 199 if(!g_strcasecmp(f->str,"name") ) {
389ba50e 200 se->field = LTTV_FILTER_EVENT_NAME;
201 }
80f9611a 202 else if(!g_strcasecmp(f->str,"category") ) {
389ba50e 203 /*
204 * FIXME: Category not yet functional in lttv
205 */
206 se->field = LTTV_FILTER_EVENT_CATEGORY;
207 }
80f9611a 208 else if(!g_strcasecmp(f->str,"time") ) {
389ba50e 209 se->field = LTTV_FILTER_EVENT_TIME;
2b99ec10 210 }
80f9611a 211 else if(!g_strcasecmp(f->str,"tsc") ) {
389ba50e 212 se->field = LTTV_FILTER_EVENT_TSC;
2b99ec10 213 }
214 else { /* core.xml specified options */
389ba50e 215 se->field = LTTV_FILTER_EVENT_FIELD;
2b99ec10 216 }
91ad3f0a 217 } else {
218 g_warning("Unrecognized field in filter string");
0769c82f 219 }
47aa6e58 220
56e29124 221 /* free memory for last string */
73050a5f 222 g_string_free(f,TRUE);
56e29124 223
224 /* array should be empty */
73050a5f 225 g_assert(fp->len == 0);
56e29124 226
56e29124 227 if(se->field == LTTV_FILTER_UNDEFINED) {
228 g_warning("The specified field was not recognized !");
229 return FALSE;
230 }
91ad3f0a 231 return TRUE;
0769c82f 232}
233
bb87caa7 234/**
56e29124 235 * @fn gboolean lttv_simple_expression_assign_operator(LttvSimpleExpression*,LttvExpressionOp)
236 *
bb87caa7 237 * Sets the function pointer for the current
238 * Simple Expression
239 * @param se current simple expression
7e7af7f2 240 * @param op current operator
bb87caa7 241 * @return success/failure of operation
242 */
be66ef34 243gboolean
244lttv_simple_expression_assign_operator(LttvSimpleExpression* se, LttvExpressionOp op) {
aa4600f3 245
bb87caa7 246 switch(se->field) {
56e29124 247 /*
248 * string
249 */
bb87caa7 250 case LTTV_FILTER_TRACE_NAME:
251 case LTTV_FILTER_TRACEFILE_NAME:
252 case LTTV_FILTER_STATE_P_NAME:
253 case LTTV_FILTER_EVENT_NAME:
bbd9d557 254 case LTTV_FILTER_STATE_CPU:
be66ef34 255 case LTTV_FILTER_STATE_EX_MODE:
256 case LTTV_FILTER_STATE_EX_SUBMODE:
257 case LTTV_FILTER_STATE_P_STATUS:
bb87caa7 258 switch(op) {
259 case LTTV_FIELD_EQ:
c6832b57 260 se->op = lttv_apply_op_eq_quark;
bb87caa7 261 break;
262 case LTTV_FIELD_NE:
c6832b57 263 se->op = lttv_apply_op_ne_quark;
bb87caa7 264 break;
265 default:
73050a5f 266 g_warning("Error encountered in operator assignment = or != expected");
bb87caa7 267 return FALSE;
268 }
269 break;
56e29124 270 /*
271 * integer
272 */
bb87caa7 273 case LTTV_FILTER_STATE_PID:
274 case LTTV_FILTER_STATE_PPID:
bbd9d557 275 case LTTV_FILTER_EVENT_TSC:
bb87caa7 276 switch(op) {
277 case LTTV_FIELD_EQ:
278 se->op = lttv_apply_op_eq_uint64;
279 break;
280 case LTTV_FIELD_NE:
281 se->op = lttv_apply_op_ne_uint64;
282 break;
283 case LTTV_FIELD_LT:
284 se->op = lttv_apply_op_lt_uint64;
285 break;
286 case LTTV_FIELD_LE:
287 se->op = lttv_apply_op_le_uint64;
288 break;
289 case LTTV_FIELD_GT:
290 se->op = lttv_apply_op_gt_uint64;
291 break;
292 case LTTV_FIELD_GE:
293 se->op = lttv_apply_op_ge_uint64;
294 break;
295 default:
296 g_warning("Error encountered in operator assignment");
297 return FALSE;
298 }
299 break;
f017db44 300 /*
301 * Enums
be66ef34 302 * Entered as string, converted to enum
303 *
f017db44 304 * can only be compared with 'equal' or 'not equal' operators
305 *
306 * unsigned int of 16 bits are used here since enums
be66ef34 307 * should not go over 2^16-1 values
f017db44 308 */
be66ef34 309// case /*NOTHING*/:
310// switch(op) {
311// case LTTV_FIELD_EQ:
312// se->op = lttv_apply_op_eq_uint16;
313// break;
314// case LTTV_FIELD_NE:
315// se->op = lttv_apply_op_ne_uint16;
316// break;
317// default:
318// g_warning("Error encountered in operator assignment = or != expected");
319// return FALSE;
320// }
321// break;
56e29124 322 /*
7145a073 323 * Ltttime
56e29124 324 */
bb87caa7 325 case LTTV_FILTER_STATE_CT:
326 case LTTV_FILTER_STATE_IT:
327 case LTTV_FILTER_EVENT_TIME:
bb87caa7 328 switch(op) {
329 case LTTV_FIELD_EQ:
7145a073 330 se->op = lttv_apply_op_eq_ltttime;
bb87caa7 331 break;
332 case LTTV_FIELD_NE:
7145a073 333 se->op = lttv_apply_op_ne_ltttime;
bb87caa7 334 break;
335 case LTTV_FIELD_LT:
7145a073 336 se->op = lttv_apply_op_lt_ltttime;
bb87caa7 337 break;
338 case LTTV_FIELD_LE:
7145a073 339 se->op = lttv_apply_op_le_ltttime;
bb87caa7 340 break;
341 case LTTV_FIELD_GT:
7145a073 342 se->op = lttv_apply_op_gt_ltttime;
bb87caa7 343 break;
344 case LTTV_FIELD_GE:
7145a073 345 se->op = lttv_apply_op_ge_ltttime;
bb87caa7 346 break;
347 default:
348 g_warning("Error encountered in operator assignment");
349 return FALSE;
350 }
351 break;
352 default:
9ab5ebd7 353 g_warning("Error encountered in operator assignation ! Field type:%i",se->field);
bb87caa7 354 return FALSE;
355 }
aa4600f3 356
357 return TRUE;
bb87caa7 358
359}
360
9ab5ebd7 361/**
7e7af7f2 362 * @fn gboolean lttv_simple_expression_assign_value(LttvSimpleExpression*,char*)
9ab5ebd7 363 *
364 * Assign the value field to the current LttvSimpleExpression
365 * @param se pointer to the current LttvSimpleExpression
366 * @param value string value for simple expression
367 */
be66ef34 368gboolean
369lttv_simple_expression_assign_value(LttvSimpleExpression* se, char* value) {
9ab5ebd7 370
46c40a93 371 unsigned i;
372 gboolean is_double = FALSE;
c6832b57 373 LttTime t = ltt_time_zero;
374 GString* v;
375 GQuark quark;
9ab5ebd7 376
377 switch(se->field) {
378 /*
be66ef34 379 * Strings
380 * entered as strings, converted to Quarks
9ab5ebd7 381 */
382 case LTTV_FILTER_TRACE_NAME:
383 case LTTV_FILTER_TRACEFILE_NAME:
384 case LTTV_FILTER_STATE_P_NAME:
385 case LTTV_FILTER_EVENT_NAME:
bbd9d557 386 case LTTV_FILTER_STATE_CPU:
be66ef34 387 case LTTV_FILTER_STATE_EX_MODE:
388 case LTTV_FILTER_STATE_EX_SUBMODE:
389 case LTTV_FILTER_STATE_P_STATUS:
390 // se->value.v_string = value;
bbd9d557 391 se->value.v_uint32 = g_quark_from_string(value);
c6832b57 392 g_free(value);
9ab5ebd7 393 break;
394 /*
be66ef34 395 * integer -- supposed to be uint64
9ab5ebd7 396 */
397 case LTTV_FILTER_STATE_PID:
398 case LTTV_FILTER_STATE_PPID:
bbd9d557 399 case LTTV_FILTER_EVENT_TSC:
9ab5ebd7 400 se->value.v_uint64 = atoi(value);
401 g_free(value);
402 break;
403 /*
7145a073 404 * LttTime
9ab5ebd7 405 */
406 case LTTV_FILTER_STATE_CT:
407 case LTTV_FILTER_STATE_IT:
408 case LTTV_FILTER_EVENT_TIME:
7145a073 409 //se->value.v_double = atof(value);
46c40a93 410 /*
411 * parsing logic could be optimised,
412 * but as for now, simpler this way
413 */
414 v = g_string_new("");
415 for(i=0;i<strlen(value);i++) {
416 if(value[i] == '.') {
417 /* cannot specify number with more than one '.' */
418 if(is_double) return FALSE;
419 else is_double = TRUE;
420 t.tv_sec = atoi(v);
421 g_string_free(v,TRUE);
422 v = g_string_new("");
423 } else g_string_append_c(v,value[i]);
424 }
425 /* number can be integer or double */
426 if(is_double) t.tv_nsec = atoi(v);
c6832b57 427 else t.tv_sec = atoi(v);
428
46c40a93 429 g_string_free(v,TRUE);
430
431 se->value.v_ltttime = t;
9ab5ebd7 432 g_free(value);
433 break;
434 default:
435 g_warning("Error encountered in value assignation ! Field type = %i",se->field);
c6832b57 436 g_free(value);
9ab5ebd7 437 return FALSE;
438 }
439
440 return TRUE;
441
442}
443
31452f49 444/**
56e29124 445 * @fn void lttv_simple_expression_destroy(LttvSimpleExpression*)
446 *
9ab5ebd7 447 * Disallocate memory for the current
56e29124 448 * simple expression
449 * @param se pointer to the current LttvSimpleExpression
450 */
451void
452lttv_simple_expression_destroy(LttvSimpleExpression* se) {
453
9ab5ebd7 454 // g_free(se->value);
786c5c3b 455// switch(se->field) {
456// case LTTV_FILTER_TRACE_NAME:
457// case LTTV_FILTER_TRACEFILE_NAME:
458// case LTTV_FILTER_STATE_P_NAME:
459// case LTTV_FILTER_EVENT_NAME:
460// g_free(se->value.v_string);
461// break;
462// }
56e29124 463 g_free(se);
464
465}
466
467/**
468 * @fn gint lttv_struct_type(gint)
469 *
80f9611a 470 * Finds the structure type depending
471 * on the fields in parameters
472 * @params ft Field of the current structure
473 * @return LttvStructType enum or -1 for error
84a333d6 474 */
80f9611a 475gint
476lttv_struct_type(gint ft) {
5f185a2b 477
80f9611a 478 switch(ft) {
479 case LTTV_FILTER_TRACE_NAME:
480 return LTTV_FILTER_TRACE;
481 break;
482 case LTTV_FILTER_TRACEFILE_NAME:
483 return LTTV_FILTER_TRACEFILE;
484 break;
485 case LTTV_FILTER_STATE_PID:
486 case LTTV_FILTER_STATE_PPID:
487 case LTTV_FILTER_STATE_CT:
488 case LTTV_FILTER_STATE_IT:
489 case LTTV_FILTER_STATE_P_NAME:
490 case LTTV_FILTER_STATE_EX_MODE:
491 case LTTV_FILTER_STATE_EX_SUBMODE:
492 case LTTV_FILTER_STATE_P_STATUS:
493 case LTTV_FILTER_STATE_CPU:
494 return LTTV_FILTER_STATE;
495 break;
496 case LTTV_FILTER_EVENT_NAME:
497 case LTTV_FILTER_EVENT_CATEGORY:
498 case LTTV_FILTER_EVENT_TIME:
499 case LTTV_FILTER_EVENT_TSC:
500 case LTTV_FILTER_EVENT_FIELD:
501 return LTTV_FILTER_EVENT;
502 break;
503 default:
504 return -1;
505 }
84a333d6 506}
507
150f0d33 508/**
7e7af7f2 509 * @fn gboolean lttv_apply_op_eq_uint64(gpointer,LttvFieldValue)
56e29124 510 *
150f0d33 511 * Applies the '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 */
4d9ff942 517gboolean lttv_apply_op_eq_uint64(const gpointer v1, LttvFieldValue v2) {
83aa92fc 518
519 guint64* r = (guint64*) v1;
9ab5ebd7 520 return (*r == v2.v_uint64);
83aa92fc 521
522}
150f0d33 523
5b729fcf 524/**
7e7af7f2 525 * @fn gboolean lttv_apply_op_eq_uint32(gpointer,LttvFieldValue)
56e29124 526 *
5b729fcf 527 * Applies the 'equal' operator to the
47aa6e58 528 * specified structure and value
529 * @param v1 left member of comparison
530 * @param v2 right member of comparison
5b729fcf 531 * @return success/failure of operation
532 */
4d9ff942 533gboolean lttv_apply_op_eq_uint32(const gpointer v1, LttvFieldValue v2) {
83aa92fc 534 guint32* r = (guint32*) v1;
9ab5ebd7 535 return (*r == v2.v_uint32);
83aa92fc 536}
5b729fcf 537
538/**
7e7af7f2 539 * @fn gboolean lttv_apply_op_eq_uint16(gpointer,LttvFieldValue)
56e29124 540 *
5b729fcf 541 * Applies the 'equal' operator to the
47aa6e58 542 * specified structure and value
543 * @param v1 left member of comparison
544 * @param v2 right member of comparison
5b729fcf 545 * @return success/failure of operation
546 */
4d9ff942 547gboolean lttv_apply_op_eq_uint16(const gpointer v1, LttvFieldValue v2) {
83aa92fc 548 guint16* r = (guint16*) v1;
9ab5ebd7 549 return (*r == v2.v_uint16);
83aa92fc 550}
5b729fcf 551
552/**
7e7af7f2 553 * @fn gboolean lttv_apply_op_eq_double(gpointer,LttvFieldValue)
56e29124 554 *
5b729fcf 555 * Applies the 'equal' operator to the
47aa6e58 556 * specified structure and value
557 * @param v1 left member of comparison
558 * @param v2 right member of comparison
5b729fcf 559 * @return success/failure of operation
560 */
4d9ff942 561gboolean lttv_apply_op_eq_double(const gpointer v1, LttvFieldValue v2) {
83aa92fc 562 double* r = (double*) v1;
9ab5ebd7 563 return (*r == v2.v_double);
83aa92fc 564}
5b729fcf 565
566/**
7e7af7f2 567 * @fn gboolean lttv_apply_op_eq_string(gpointer,LttvFieldValue)
56e29124 568 *
5b729fcf 569 * Applies the 'equal' operator to the
47aa6e58 570 * specified structure and value
571 * @param v1 left member of comparison
572 * @param v2 right member of comparison
5b729fcf 573 * @return success/failure of operation
574 */
4d9ff942 575gboolean lttv_apply_op_eq_string(const gpointer v1, LttvFieldValue v2) {
83aa92fc 576 char* r = (char*) v1;
9ab5ebd7 577 return (!g_strcasecmp(r,v2.v_string));
83aa92fc 578}
150f0d33 579
c6832b57 580/**
7e7af7f2 581 * @fn gboolean lttv_apply_op_eq_quark(gpointer,LttvFieldValue)
c6832b57 582 *
583 * Applies the 'equal' operator to the
584 * specified structure and value
585 * @param v1 left member of comparison
586 * @param v2 right member of comparison
587 * @return success/failure of operation
588 */
589gboolean lttv_apply_op_eq_quark(const gpointer v1, LttvFieldValue v2) {
590 GQuark* r = (GQuark*) v1;
1a252208 591// g_print("v1:%i v2:%i\n",*r,v2.v_uint32);
c6832b57 592 return (*r == v2.v_uint32);
593}
594
7145a073 595/**
7e7af7f2 596 * @fn gboolean lttv_apply_op_eq_ltttime(gpointer,LttvFieldValue)
7145a073 597 *
598 * Applies the 'equal' operator to the
599 * specified structure and value
600 * @param v1 left member of comparison
601 * @param v2 right member of comparison
602 * @return success/failure of operation
603 */
4d9ff942 604gboolean lttv_apply_op_eq_ltttime(const gpointer v1, LttvFieldValue v2) {
7145a073 605 LttTime* r = (LttTime*) v1;
c6832b57 606 return ltt_time_compare(*r, v2.v_ltttime)==0?1:0;
7145a073 607}
608
609
150f0d33 610/**
7e7af7f2 611 * @fn gboolean lttv_apply_op_ne_uint64(gpointer,LttvFieldValue)
56e29124 612 *
150f0d33 613 * Applies the 'not equal' operator to the
47aa6e58 614 * specified structure and value
615 * @param v1 left member of comparison
616 * @param v2 right member of comparison
150f0d33 617 * @return success/failure of operation
618 */
4d9ff942 619gboolean lttv_apply_op_ne_uint64(const gpointer v1, LttvFieldValue v2) {
83aa92fc 620 guint64* r = (guint64*) v1;
9ab5ebd7 621 return (*r != v2.v_uint64);
83aa92fc 622}
150f0d33 623
5b729fcf 624/**
7e7af7f2 625 * @fn gboolean lttv_apply_op_ne_uint32(gpointer,LttvFieldValue)
56e29124 626 *
5b729fcf 627 * Applies the 'not equal' operator to the
47aa6e58 628 * specified structure and value
629 * @param v1 left member of comparison
630 * @param v2 right member of comparison
5b729fcf 631 * @return success/failure of operation
632 */
4d9ff942 633gboolean lttv_apply_op_ne_uint32(const gpointer v1, LttvFieldValue v2) {
83aa92fc 634 guint32* r = (guint32*) v1;
9ab5ebd7 635 return (*r != v2.v_uint32);
83aa92fc 636}
5b729fcf 637
638/**
7e7af7f2 639 * @fn gboolean lttv_apply_op_ne_uint16(gpointer,LttvFieldValue)
56e29124 640 *
5b729fcf 641 * Applies the 'not equal' operator to the
47aa6e58 642 * specified structure and value
643 * @param v1 left member of comparison
644 * @param v2 right member of comparison
5b729fcf 645 * @return success/failure of operation
646 */
4d9ff942 647gboolean lttv_apply_op_ne_uint16(const gpointer v1, LttvFieldValue v2) {
83aa92fc 648 guint16* r = (guint16*) v1;
9ab5ebd7 649 return (*r != v2.v_uint16);
83aa92fc 650}
5b729fcf 651
652/**
7e7af7f2 653 * @fn gboolean lttv_apply_op_ne_double(gpointer,LttvFieldValue)
56e29124 654 *
5b729fcf 655 * Applies the 'not equal' 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 */
4d9ff942 661gboolean lttv_apply_op_ne_double(const gpointer v1, LttvFieldValue v2) {
83aa92fc 662 double* r = (double*) v1;
9ab5ebd7 663 return (*r != v2.v_double);
83aa92fc 664}
5b729fcf 665
666/**
7e7af7f2 667 * @fn gboolean lttv_apply_op_ne_string(gpointer,LttvFieldValue)
56e29124 668 *
5b729fcf 669 * Applies the 'not equal' operator to the
47aa6e58 670 * specified structure and value
671 * @param v1 left member of comparison
672 * @param v2 right member of comparison
5b729fcf 673 * @return success/failure of operation
674 */
4d9ff942 675gboolean lttv_apply_op_ne_string(const gpointer v1, LttvFieldValue v2) {
83aa92fc 676 char* r = (char*) v1;
9ab5ebd7 677 return (g_strcasecmp(r,v2.v_string));
83aa92fc 678}
150f0d33 679
c6832b57 680/**
7e7af7f2 681 * @fn gboolean lttv_apply_op_ne_quark(gpointer,LttvFieldValue)
c6832b57 682 *
683 * Applies the 'not equal' operator to the
684 * specified structure and value
685 * @param v1 left member of comparison
686 * @param v2 right member of comparison
687 * @return success/failure of operation
688 */
689gboolean lttv_apply_op_ne_quark(const gpointer v1, LttvFieldValue v2) {
690 GQuark* r = (GQuark*) v1;
691 return (*r != v2.v_uint32);
692}
693
694
7145a073 695/**
7e7af7f2 696 * @fn gboolean lttv_apply_op_ne_ltttime(gpointer,LttvFieldValue)
7145a073 697 *
698 * Applies the 'not equal' operator to the
699 * specified structure and value
700 * @param v1 left member of comparison
701 * @param v2 right member of comparison
702 * @return success/failure of operation
703 */
4d9ff942 704gboolean lttv_apply_op_ne_ltttime(const gpointer v1, LttvFieldValue v2) {
7145a073 705 LttTime* r = (LttTime*) v1;
46c40a93 706 return ltt_time_compare(*r, v2.v_ltttime)!=0?1:0;
7145a073 707}
708
709
150f0d33 710/**
7e7af7f2 711 * @fn gboolean lttv_apply_op_lt_uint64(gpointer,LttvFieldValue)
56e29124 712 *
150f0d33 713 * Applies the 'lower than' operator to the
47aa6e58 714 * specified structure and value
715 * @param v1 left member of comparison
716 * @param v2 right member of comparison
150f0d33 717 * @return success/failure of operation
718 */
4d9ff942 719gboolean lttv_apply_op_lt_uint64(const gpointer v1, LttvFieldValue v2) {
83aa92fc 720 guint64* r = (guint64*) v1;
9ab5ebd7 721 return (*r < v2.v_uint64);
83aa92fc 722}
150f0d33 723
5b729fcf 724/**
7e7af7f2 725 * @fn gboolean lttv_apply_op_lt_uint32(gpointer,LttvFieldValue)
56e29124 726 *
5b729fcf 727 * Applies the 'lower than' operator to the
47aa6e58 728 * specified structure and value
729 * @param v1 left member of comparison
730 * @param v2 right member of comparison
5b729fcf 731 * @return success/failure of operation
732 */
4d9ff942 733gboolean lttv_apply_op_lt_uint32(const gpointer v1, LttvFieldValue v2) {
83aa92fc 734 guint32* r = (guint32*) v1;
9ab5ebd7 735 return (*r < v2.v_uint32);
83aa92fc 736}
5b729fcf 737
738/**
7e7af7f2 739 * @fn gboolean lttv_apply_op_lt_uint16(gpointer,LttvFieldValue)
56e29124 740 *
5b729fcf 741 * Applies the 'lower than' operator to the
47aa6e58 742 * specified structure and value
743 * @param v1 left member of comparison
744 * @param v2 right member of comparison
5b729fcf 745 * @return success/failure of operation
746 */
4d9ff942 747gboolean lttv_apply_op_lt_uint16(const gpointer v1, LttvFieldValue v2) {
83aa92fc 748 guint16* r = (guint16*) v1;
9ab5ebd7 749 return (*r < v2.v_uint16);
83aa92fc 750}
5b729fcf 751
752/**
7e7af7f2 753 * @fn gboolean lttv_apply_op_lt_double(gpointer,LttvFieldValue)
56e29124 754 *
5b729fcf 755 * Applies the 'lower than' operator to the
47aa6e58 756 * specified structure and value
757 * @param v1 left member of comparison
758 * @param v2 right member of comparison
5b729fcf 759 * @return success/failure of operation
760 */
4d9ff942 761gboolean lttv_apply_op_lt_double(const gpointer v1, LttvFieldValue v2) {
83aa92fc 762 double* r = (double*) v1;
9ab5ebd7 763 return (*r < v2.v_double);
83aa92fc 764}
5b729fcf 765
7145a073 766/**
7e7af7f2 767 * @fn gboolean lttv_apply_op_lt_ltttime(gpointer,LttvFieldValue)
7145a073 768 *
769 * Applies the 'lower than' operator to the
770 * specified structure and value
771 * @param v1 left member of comparison
772 * @param v2 right member of comparison
773 * @return success/failure of operation
774 */
4d9ff942 775gboolean lttv_apply_op_lt_ltttime(const gpointer v1, LttvFieldValue v2) {
7145a073 776 LttTime* r = (LttTime*) v1;
c6832b57 777// return ((r->tv_sec < v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec < v2.v_ltttime.tv_nsec)));
778 return ltt_time_compare(*r, v2.v_ltttime)==-1?1:0;
7145a073 779}
780
781
5b729fcf 782/**
7e7af7f2 783 * @fn gboolean lttv_apply_op_le_uint64(gpointer,LttvFieldValue)
56e29124 784 *
785 * Applies the 'lower or equal' operator to the
47aa6e58 786 * specified structure and value
787 * @param v1 left member of comparison
788 * @param v2 right member of comparison
5b729fcf 789 * @return success/failure of operation
790 */
4d9ff942 791gboolean lttv_apply_op_le_uint64(const gpointer v1, LttvFieldValue v2) {
83aa92fc 792 guint64* r = (guint64*) v1;
9ab5ebd7 793 return (*r <= v2.v_uint64);
83aa92fc 794}
150f0d33 795
796/**
7e7af7f2 797 * @fn gboolean lttv_apply_op_le_uint32(gpointer,LttvFieldValue)
56e29124 798 *
150f0d33 799 * Applies the 'lower or equal' operator to the
47aa6e58 800 * specified structure and value
801 * @param v1 left member of comparison
802 * @param v2 right member of comparison
150f0d33 803 * @return success/failure of operation
804 */
4d9ff942 805gboolean lttv_apply_op_le_uint32(const gpointer v1, LttvFieldValue v2) {
83aa92fc 806 guint32* r = (guint32*) v1;
9ab5ebd7 807 return (*r <= v2.v_uint32);
83aa92fc 808}
150f0d33 809
5b729fcf 810/**
7e7af7f2 811 * @fn gboolean lttv_apply_op_le_uint16(gpointer,LttvFieldValue)
56e29124 812 *
5b729fcf 813 * Applies the 'lower or equal' operator to the
47aa6e58 814 * specified structure and value
815 * @param v1 left member of comparison
816 * @param v2 right member of comparison
5b729fcf 817 * @return success/failure of operation
818 */
4d9ff942 819gboolean lttv_apply_op_le_uint16(const gpointer v1, LttvFieldValue v2) {
83aa92fc 820 guint16* r = (guint16*) v1;
9ab5ebd7 821 return (*r <= v2.v_uint16);
83aa92fc 822}
5b729fcf 823
824/**
7e7af7f2 825 * @fn gboolean lttv_apply_op_le_double(gpointer,LttvFieldValue)
56e29124 826 *
5b729fcf 827 * Applies the 'lower or equal' operator to the
47aa6e58 828 * specified structure and value
829 * @param v1 left member of comparison
830 * @param v2 right member of comparison
5b729fcf 831 * @return success/failure of operation
832 */
4d9ff942 833gboolean lttv_apply_op_le_double(const gpointer v1, LttvFieldValue v2) {
83aa92fc 834 double* r = (double*) v1;
9ab5ebd7 835 return (*r <= v2.v_double);
83aa92fc 836}
5b729fcf 837
7145a073 838/**
7e7af7f2 839 * @fn gboolean lttv_apply_op_le_ltttime(gpointer,LttvFieldValue)
7145a073 840 *
841 * Applies the 'lower or equal' operator to the
842 * specified structure and value
843 * @param v1 left member of comparison
844 * @param v2 right member of comparison
845 * @return success/failure of operation
846 */
4d9ff942 847gboolean lttv_apply_op_le_ltttime(const gpointer v1, LttvFieldValue v2) {
7145a073 848 LttTime* r = (LttTime*) v1;
c6832b57 849// return ((r->tv_sec < v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec <= v2.v_ltttime.tv_nsec)));
850 return ltt_time_compare(*r, v2.v_ltttime)<1?1:0;
7145a073 851}
852
853
5b729fcf 854/**
7e7af7f2 855 * @fn gboolean lttv_apply_op_gt_uint64(gpointer,LttvFieldValue)
56e29124 856 *
83aa92fc 857 * Applies the 'greater than' operator to the
47aa6e58 858 * specified structure and value
859 * @param v1 left member of comparison
860 * @param v2 right member of comparison
5b729fcf 861 * @return success/failure of operation
862 */
4d9ff942 863gboolean lttv_apply_op_gt_uint64(const gpointer v1, LttvFieldValue v2) {
83aa92fc 864 guint64* r = (guint64*) v1;
9ab5ebd7 865 return (*r > v2.v_uint64);
83aa92fc 866}
150f0d33 867
868/**
7e7af7f2 869 * @fn gboolean lttv_apply_op_gt_uint32(gpointer,LttvFieldValue)
56e29124 870 *
150f0d33 871 * Applies the 'greater than' operator to the
47aa6e58 872 * specified structure and value
873 * @param v1 left member of comparison
874 * @param v2 right member of comparison
150f0d33 875 * @return success/failure of operation
876 */
4d9ff942 877gboolean lttv_apply_op_gt_uint32(const gpointer v1, LttvFieldValue v2) {
83aa92fc 878 guint32* r = (guint32*) v1;
9ab5ebd7 879 return (*r > v2.v_uint32);
83aa92fc 880}
150f0d33 881
5b729fcf 882/**
7e7af7f2 883 * @fn gboolean lttv_apply_op_gt_uint16(gpointer,LttvFieldValue)
56e29124 884 *
5b729fcf 885 * Applies the 'greater than' operator to the
47aa6e58 886 * specified structure and value
887 * @param v1 left member of comparison
888 * @param v2 right member of comparison
5b729fcf 889 * @return success/failure of operation
890 */
4d9ff942 891gboolean lttv_apply_op_gt_uint16(const gpointer v1, LttvFieldValue v2) {
83aa92fc 892 guint16* r = (guint16*) v1;
9ab5ebd7 893 return (*r > v2.v_uint16);
83aa92fc 894}
5b729fcf 895
896/**
7e7af7f2 897 * @fn gboolean lttv_apply_op_gt_double(gpointer,LttvFieldValue)
56e29124 898 *
5b729fcf 899 * Applies the 'greater than' operator to the
47aa6e58 900 * specified structure and value
901 * @param v1 left member of comparison
902 * @param v2 right member of comparison
5b729fcf 903 * @return success/failure of operation
904 */
4d9ff942 905gboolean lttv_apply_op_gt_double(const gpointer v1, LttvFieldValue v2) {
83aa92fc 906 double* r = (double*) v1;
9ab5ebd7 907 return (*r > v2.v_double);
83aa92fc 908}
5b729fcf 909
7145a073 910/**
7e7af7f2 911 * @fn gboolean lttv_apply_op_gt_ltttime(gpointer,LttvFieldValue)
7145a073 912 *
913 * Applies the 'greater than' operator to the
914 * specified structure and value
915 * @param v1 left member of comparison
916 * @param v2 right member of comparison
917 * @return success/failure of operation
918 */
4d9ff942 919gboolean lttv_apply_op_gt_ltttime(const gpointer v1, LttvFieldValue v2) {
7145a073 920 LttTime* r = (LttTime*) v1;
c6832b57 921// return ((r->tv_sec > v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec > v2.v_ltttime.tv_nsec)));
922 return ltt_time_compare(*r, v2.v_ltttime)==1?1:0;
7145a073 923}
924
925
5b729fcf 926/**
7e7af7f2 927 * @fn gboolean lttv_apply_op_ge_uint64(gpointer,LttvFieldValue)
56e29124 928 *
83aa92fc 929 * Applies the 'greater or equal' operator to the
47aa6e58 930 * specified structure and value
931 * @param v1 left member of comparison
932 * @param v2 right member of comparison
5b729fcf 933 * @return success/failure of operation
934 */
4d9ff942 935gboolean lttv_apply_op_ge_uint64(const gpointer v1, LttvFieldValue v2) {
83aa92fc 936 guint64* r = (guint64*) v1;
9ab5ebd7 937 return (*r >= v2.v_uint64);
83aa92fc 938}
150f0d33 939
940/**
7e7af7f2 941 * @fn gboolean lttv_apply_op_ge_uint32(gpointer,LttvFieldValue)
56e29124 942 *
150f0d33 943 * Applies the 'greater or equal' operator to the
47aa6e58 944 * specified structure and value
945 * @param v1 left member of comparison
946 * @param v2 right member of comparison
150f0d33 947 * @return success/failure of operation
948 */
4d9ff942 949gboolean lttv_apply_op_ge_uint32(const gpointer v1, LttvFieldValue v2) {
83aa92fc 950 guint32* r = (guint32*) v1;
9ab5ebd7 951 return (*r >= v2.v_uint32);
83aa92fc 952}
150f0d33 953
5b729fcf 954/**
7e7af7f2 955 * @fn gboolean lttv_apply_op_ge_uint16(gpointer,LttvFieldValue)
56e29124 956 *
5b729fcf 957 * Applies the 'greater or equal' operator to the
47aa6e58 958 * specified structure and value
959 * @param v1 left member of comparison
960 * @param v2 right member of comparison
5b729fcf 961 * @return success/failure of operation
962 */
4d9ff942 963gboolean lttv_apply_op_ge_uint16(const gpointer v1, LttvFieldValue v2) {
83aa92fc 964 guint16* r = (guint16*) v1;
9ab5ebd7 965 return (*r >= v2.v_uint16);
83aa92fc 966}
150f0d33 967
5b729fcf 968/**
7e7af7f2 969 * @fn gboolean lttv_apply_op_ge_double(gpointer,LttvFieldValue)
56e29124 970 *
5b729fcf 971 * Applies the 'greater or equal' operator to the
47aa6e58 972 * specified structure and value
973 * @param v1 left member of comparison
974 * @param v2 right member of comparison
5b729fcf 975 * @return success/failure of operation
976 */
4d9ff942 977gboolean lttv_apply_op_ge_double(const gpointer v1, LttvFieldValue v2) {
83aa92fc 978 double* r = (double*) v1;
9ab5ebd7 979 return (*r >= v2.v_double);
83aa92fc 980}
150f0d33 981
7145a073 982/**
7e7af7f2 983 * @fn gboolean lttv_apply_op_ge_ltttime(gpointer,LttvFieldValue)
7145a073 984 *
985 * Applies the 'greater or equal' operator to the
986 * specified structure and value
987 * @param v1 left member of comparison
988 * @param v2 right member of comparison
989 * @return success/failure of operation
990 */
4d9ff942 991gboolean lttv_apply_op_ge_ltttime(const gpointer v1, LttvFieldValue v2) {
7145a073 992 LttTime* r = (LttTime*) v1;
c6832b57 993// return ((r->tv_sec > v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec >= v2.v_ltttime.tv_nsec)));
994 return ltt_time_compare(*r, v2.v_ltttime)>-1?1:0;
7145a073 995}
996
997
150f0d33 998
999/**
56e29124 1000 * Makes a copy of the current filter tree
1001 * @param tree pointer to the current tree
1002 * @return new copy of the filter tree
150f0d33 1003 */
1004LttvFilterTree*
4d9ff942 1005lttv_filter_tree_clone(const LttvFilterTree* tree) {
150f0d33 1006
8c89f5a8 1007 LttvFilterTree* newtree = lttv_filter_tree_new();
150f0d33 1008
8c89f5a8 1009 newtree->node = tree->node;
1010
1011 newtree->left = tree->left;
1012 if(newtree->left == LTTV_TREE_NODE) {
1013 newtree->l_child.t = lttv_filter_tree_clone(tree->l_child.t);
1014 } else if(newtree->left == LTTV_TREE_LEAF) {
1015 newtree->l_child.leaf = lttv_simple_expression_new();
1016 newtree->l_child.leaf->field = tree->l_child.leaf->field;
1017 newtree->l_child.leaf->offset = tree->l_child.leaf->offset;
1018 newtree->l_child.leaf->op = tree->l_child.leaf->op;
9ab5ebd7 1019 /* FIXME: special case for string copy ! */
1020 newtree->l_child.leaf->value = tree->l_child.leaf->value;
8c89f5a8 1021 }
1022
1023 newtree->right = tree->right;
1024 if(newtree->right == LTTV_TREE_NODE) {
1025 newtree->r_child.t = lttv_filter_tree_clone(tree->r_child.t);
1026 } else if(newtree->right == LTTV_TREE_LEAF) {
1027 newtree->r_child.leaf = lttv_simple_expression_new();
1028 newtree->r_child.leaf->field = tree->r_child.leaf->field;
1029 newtree->r_child.leaf->offset = tree->r_child.leaf->offset;
1030 newtree->r_child.leaf->op = tree->r_child.leaf->op;
9ab5ebd7 1031 newtree->r_child.leaf->value = tree->r_child.leaf->value;
8c89f5a8 1032 }
1033
1034 return newtree;
1035
150f0d33 1036}
1037
1038/**
56e29124 1039 * Makes a copy of the current filter
1040 * @param filter pointer to the current filter
1041 * @return new copy of the filter
150f0d33 1042 */
1043LttvFilter*
4d9ff942 1044lttv_filter_clone(const LttvFilter* filter) {
150f0d33 1045
1046 LttvFilter* newfilter = g_new(LttvFilter,1);
1047
150f0d33 1048 strcpy(newfilter->expression,filter->expression);
1049
1050 newfilter->head = lttv_filter_tree_clone(filter->head);
1051
1052 return newfilter;
1053
1054}
1055
1056
84a333d6 1057/**
56e29124 1058 * @fn LttvFilter* lttv_filter_new()
1059 *
7e7af7f2 1060 * Creates a new LttvFilter
1061 * @return the current LttvFilter or NULL if error
31452f49 1062 */
2ea36caf 1063LttvFilter*
5f185a2b 1064lttv_filter_new() {
a4c292d4 1065
5f185a2b 1066 LttvFilter* filter = g_new(LttvFilter,1);
1067 filter->expression = NULL;
1068 filter->head = NULL;
7e7af7f2 1069
1070 return filter;
5f185a2b 1071
1072}
a4c292d4 1073
8c89f5a8 1074/**
56e29124 1075 * @fn gboolean lttv_filter_update(LttvFilter*)
1076 *
8c89f5a8 1077 * Updates the current LttvFilter by building
1078 * its tree based upon the expression string
1079 * @param filter pointer to the current LttvFilter
1080 * @return Failure/Success of operation
1081 */
5f185a2b 1082gboolean
1083lttv_filter_update(LttvFilter* filter) {
1084
4d9ff942 1085// g_print("filter::lttv_filter_new()\n"); /* debug */
5f185a2b 1086
1087 if(filter->expression == NULL) return FALSE;
1088
f3020899 1089 int
a4c292d4 1090 i,
72911c5d 1091 p_nesting=0, /* parenthesis nesting value */
1092 not=0;
1093
1601b365 1094 /* trees */
5b729fcf 1095 LttvFilterTree
1601b365 1096 *tree = lttv_filter_tree_new(), /* main tree */
1097 *subtree = NULL, /* buffer for subtrees */
1098 *t1, /* buffer #1 */
72911c5d 1099 *t2, /* buffer #2 */
1100 *t3; /* buffer #3 */
1601b365 1101
5f185a2b 1102 /*
1103 * the filter
1104 * If the tree already exists,
1105 * destroy it and build a new one
1106 */
1107 if(filter->head != NULL) lttv_filter_tree_destroy(filter->head);
f3020899 1108 filter->head = NULL; /* will be assigned at the end */
5f185a2b 1109
1601b365 1110 /*
1111 * Tree Stack
f4e9dd16 1112 * each element of the list
1113 * is a sub tree created
1114 * by the use of parenthesis in the
1115 * global expression. The final tree
1601b365 1116 * will be the one left at the root of
f4e9dd16 1117 * the list
1118 */
18d1226f 1119 GPtrArray *tree_stack = g_ptr_array_new();
1120 g_ptr_array_add( tree_stack,(gpointer) tree );
f4e9dd16 1121
a4c292d4 1122 /* temporary values */
0769c82f 1123 GString *a_field_component = g_string_new("");
56e29124 1124 GPtrArray *a_field_path = g_ptr_array_new();
1125
1126 /* simple expression buffer */
389ba50e 1127 LttvSimpleExpression* a_simple_expression = lttv_simple_expression_new();
0769c82f 1128
a4c292d4 1129 /*
1130 * Parse entire expression and construct
1131 * the binary tree. There are two steps
1132 * in browsing that string
f4e9dd16 1133 * 1. finding boolean ops " &,|,^,! " and parenthesis " {,(,[,],),} "
a4c292d4 1134 * 2. finding simple expressions
0769c82f 1135 * - field path ( separated by dots )
a4c292d4 1136 * - op ( >, <, =, >=, <=, !=)
0769c82f 1137 * - value ( integer, string ... )
1138 * To spare computing time, the whole
1139 * string is parsed in this loop for a
1140 * O(n) complexity order.
1601b365 1141 *
18d1226f 1142 * When encountering logical op &,|,^
1143 * 1. parse the last value if any
1144 * 2. create a new tree
1145 * 3. add the expression (simple exp, or exp (subtree)) to the tree
1146 * 4. concatenate this tree with the current tree on top of the stack
1147 * When encountering math ops >,>=,<,<=,=,!=
1148 * 1. add to op to the simple expression
1149 * 2. concatenate last field component to field path
1150 * When encountering concatening ops .
1151 * 1. concatenate last field component to field path
1152 * When encountering opening parenthesis (,{,[
1153 * 1. create a new subtree on top of tree stack
1154 * When encountering closing parenthesis ),},]
1155 * 1. add the expression on right child of the current tree
1156 * 2. the subtree is completed, allocate a new subtree
1157 * 3. pop the tree value from the tree stack
1158 */
be66ef34 1159
1160#ifdef TEST
1161 struct timeval starttime;
1162 struct timeval endtime;
1163 gettimeofday(&starttime, NULL);
1164#endif
18d1226f 1165
5f185a2b 1166 for(i=0;i<strlen(filter->expression);i++) {
1167 // debug
72911c5d 1168// g_print("%c\n ",filter->expression[i]);
4d9ff942 1169
5f185a2b 1170 switch(filter->expression[i]) {
a4c292d4 1171 /*
1172 * logical operators
1173 */
1174 case '&': /* and */
72911c5d 1175
1176 /* get current tree in tree stack */
5b729fcf 1177 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
72911c5d 1178
1179 /* get current node at absolute right */
9ab5ebd7 1180 while(t1->right != LTTV_TREE_IDLE) {
1181 g_assert(t1->right == LTTV_TREE_NODE);
1182 t1 = t1->r_child.t;
1183 }
18d1226f 1184 t2 = lttv_filter_tree_new();
0cdc2470 1185 t2->node = LTTV_LOGICAL_AND;
72911c5d 1186 t1->right = LTTV_TREE_NODE;
1187 t1->r_child.t = t2;
1188 if(not) { /* add not operator to tree */
1189 t3 = lttv_filter_tree_new();
1190 t3->node = LTTV_LOGICAL_NOT;
1191 t2->left = LTTV_TREE_NODE;
1192 t2->l_child.t = t3;
72911c5d 1193 t2 = t3;
1194 not = 0;
72911c5d 1195 }
bb87caa7 1196 if(subtree != NULL) { /* append subtree to current tree */
18d1226f 1197 t2->left = LTTV_TREE_NODE;
1198 t2->l_child.t = subtree;
f4e9dd16 1199 subtree = NULL;
bb87caa7 1200 } else { /* append a simple expression */
9ab5ebd7 1201 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
18d1226f 1202 a_field_component = g_string_new("");
1203 t2->left = LTTV_TREE_LEAF;
0cdc2470 1204 t2->l_child.leaf = a_simple_expression;
389ba50e 1205 a_simple_expression = lttv_simple_expression_new();
f4e9dd16 1206 }
f4e9dd16 1207 break;
aa4600f3 1208
a4c292d4 1209 case '|': /* or */
aa4600f3 1210
e00d6a24 1211 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
9ab5ebd7 1212 while(t1->right != LTTV_TREE_IDLE) {
1213 g_assert(t1->right == LTTV_TREE_NODE);
1214 t1 = t1->r_child.t;
1215 }
1601b365 1216 t2 = lttv_filter_tree_new();
0cdc2470 1217 t2->node = LTTV_LOGICAL_OR;
72911c5d 1218 t1->right = LTTV_TREE_NODE;
1219 t1->r_child.t = t2;
1220 if(not) { // add not operator to tree
1221 t3 = lttv_filter_tree_new();
1222 t3->node = LTTV_LOGICAL_NOT;
1223 t2->left = LTTV_TREE_NODE;
1224 t2->l_child.t = t3;
1225 t2 = t3;
1226 not = 0;
1227 }
1228 if(subtree != NULL) { /* append subtree to current tree */
1601b365 1229 t2->left = LTTV_TREE_NODE;
1230 t2->l_child.t = subtree;
1231 subtree = NULL;
72911c5d 1232 } else { /* append a simple expression */
9ab5ebd7 1233 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1601b365 1234 a_field_component = g_string_new("");
1235 t2->left = LTTV_TREE_LEAF;
0cdc2470 1236 t2->l_child.leaf = a_simple_expression;
389ba50e 1237 a_simple_expression = lttv_simple_expression_new();
1601b365 1238 }
f4e9dd16 1239 break;
aa4600f3 1240
a4c292d4 1241 case '^': /* xor */
aa4600f3 1242
e00d6a24 1243 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
9ab5ebd7 1244 while(t1->right != LTTV_TREE_IDLE) {
1245 g_assert(t1->right == LTTV_TREE_NODE);
1246 t1 = t1->r_child.t;
1247 }
1601b365 1248 t2 = lttv_filter_tree_new();
0cdc2470 1249 t2->node = LTTV_LOGICAL_XOR;
72911c5d 1250 t1->right = LTTV_TREE_NODE;
1251 t1->r_child.t = t2;
1252 if(not) { // add not operator to tree
1253 t3 = lttv_filter_tree_new();
1254 t3->node = LTTV_LOGICAL_NOT;
1255 t2->left = LTTV_TREE_NODE;
1256 t2->l_child.t = t3;
1257 t2 = t3;
1258 not = 0;
1259 }
bb87caa7 1260 if(subtree != NULL) { /* append subtree to current tree */
1601b365 1261 t2->left = LTTV_TREE_NODE;
1262 t2->l_child.t = subtree;
1263 subtree = NULL;
bb87caa7 1264 } else { /* append a simple expression */
9ab5ebd7 1265 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1601b365 1266 a_field_component = g_string_new("");
1267 t2->left = LTTV_TREE_LEAF;
0cdc2470 1268 t2->l_child.leaf = a_simple_expression;
389ba50e 1269 a_simple_expression = lttv_simple_expression_new();
1601b365 1270 }
a4c292d4 1271 break;
aa4600f3 1272
a4c292d4 1273 case '!': /* not, or not equal (math op) */
aa4600f3 1274
5f185a2b 1275 if(filter->expression[i+1] == '=') { /* != */
0cdc2470 1276 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
9ab5ebd7 1277 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
0cdc2470 1278 a_field_component = g_string_new("");
56e29124 1279 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_NE);
aa4600f3 1280 i++;
a4c292d4 1281 } else { /* ! */
72911c5d 1282 not=1;
a4c292d4 1283 }
1284 break;
aa4600f3 1285
a4c292d4 1286 case '(': /* start of parenthesis */
91ad3f0a 1287 case '[':
1288 case '{':
aa4600f3 1289
91ad3f0a 1290 p_nesting++; /* incrementing parenthesis nesting value */
1601b365 1291 t1 = lttv_filter_tree_new();
72911c5d 1292 if(not) { /* add not operator to tree */
1293 t3 = lttv_filter_tree_new();
1294 t3->node = LTTV_LOGICAL_NOT;
1295 t1->right = LTTV_TREE_NODE;
1296 t1->r_child.t = t3;
1297 not = 0;
1298 }
1601b365 1299 g_ptr_array_add( tree_stack,(gpointer) t1 );
a4c292d4 1300 break;
aa4600f3 1301
a4c292d4 1302 case ')': /* end of parenthesis */
91ad3f0a 1303 case ']':
1304 case '}':
aa4600f3 1305
91ad3f0a 1306 p_nesting--; /* decrementing parenthesis nesting value */
18d1226f 1307 if(p_nesting<0 || tree_stack->len<2) {
f4e9dd16 1308 g_warning("Wrong filtering options, the string\n\"%s\"\n\
5f185a2b 1309 is not valid due to parenthesis incorrect use",filter->expression);
1310 return FALSE;
f4e9dd16 1311 }
56e29124 1312
1313 /* there must at least be the root tree left in the array */
18d1226f 1314 g_assert(tree_stack->len>0);
72911c5d 1315
1316 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
1317 while(t1->right != LTTV_TREE_IDLE) {
1318 t1 = t1->r_child.t;
1319 }
1320 if(not) { // add not operator to tree
1321 g_print("ici");
1322 t3 = lttv_filter_tree_new();
1323 t3->node = LTTV_LOGICAL_NOT;
1324 t1->right = LTTV_TREE_NODE;
1325 t1->r_child.t = t3;
1326 t1 = t3;
1327 not = 0;
1328 }
bb87caa7 1329 if(subtree != NULL) { /* append subtree to current tree */
18d1226f 1330 t1->right = LTTV_TREE_NODE;
1331 t1->r_child.t = subtree;
1332 subtree = g_ptr_array_index(tree_stack,tree_stack->len-1);
1333 g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
bb87caa7 1334 } else { /* assign subtree as current tree */
9ab5ebd7 1335 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
18d1226f 1336 a_field_component = g_string_new("");
18d1226f 1337 t1->right = LTTV_TREE_LEAF;
0cdc2470 1338 t1->r_child.leaf = a_simple_expression;
389ba50e 1339 a_simple_expression = lttv_simple_expression_new();
9ab5ebd7 1340 subtree = g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
18d1226f 1341 }
a4c292d4 1342 break;
1343
1344 /*
1345 * mathematic operators
1346 */
1347 case '<': /* lower, lower or equal */
aa4600f3 1348
1349 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
9ab5ebd7 1350 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
aa4600f3 1351 a_field_component = g_string_new("");
5f185a2b 1352 if(filter->expression[i+1] == '=') { /* <= */
a4c292d4 1353 i++;
56e29124 1354 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_LE);
1355 } else lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_LT);
aa4600f3 1356 break;
1357
1358 case '>': /* higher, higher or equal */
1359
1360 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
9ab5ebd7 1361 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
f4e9dd16 1362 a_field_component = g_string_new("");
5f185a2b 1363 if(filter->expression[i+1] == '=') { /* >= */
a4c292d4 1364 i++;
56e29124 1365 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_GE);
1366 } else lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_GT);
aa4600f3 1367 break;
1368
a4c292d4 1369 case '=': /* equal */
aa4600f3 1370
f4e9dd16 1371 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
9ab5ebd7 1372 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
f4e9dd16 1373 a_field_component = g_string_new("");
56e29124 1374 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_EQ);
a4c292d4 1375 break;
aa4600f3 1376
0769c82f 1377 /*
1378 * Field concatening caracter
1379 */
1380 case '.': /* dot */
aa4600f3 1381
bb87caa7 1382 /*
1383 * divide field expression into elements
1384 * in a_field_path array.
4d9ff942 1385 *
1386 * A dot can also be present in double values
bb87caa7 1387 */
8ff6243c 1388 if(a_simple_expression->field == LTTV_FILTER_UNDEFINED) {
bb87caa7 1389 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1390 a_field_component = g_string_new("");
8ff6243c 1391 }
1392 break;
4d9ff942 1393 case ' ': /* ignore */
1394 case '\n': /* ignore */
0769c82f 1395 break;
a4c292d4 1396 default: /* concatening current string */
73050a5f 1397 g_string_append_c(a_field_component,filter->expression[i]);
a4c292d4 1398 }
1399 }
1601b365 1400
0cdc2470 1401 /*
1402 * Preliminary check to see
1403 * if tree was constructed correctly
1404 */
1405 if( p_nesting>0 ) {
1406 g_warning("Wrong filtering options, the string\n\"%s\"\n\
5f185a2b 1407 is not valid due to parenthesis incorrect use",filter->expression);
1408 return FALSE;
0cdc2470 1409 }
1410
1411 if(tree_stack->len != 1) /* only root tree should remain */
5f185a2b 1412 return FALSE;
1601b365 1413
72911c5d 1414 /*
1415 * processing last element of expression
1416 */
410c83da 1417 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
9ab5ebd7 1418 while(t1->right != LTTV_TREE_IDLE) {
1419 g_assert(t1->right == LTTV_TREE_NODE);
1420 t1 = t1->r_child.t;
1421 }
72911c5d 1422 if(not) { // add not operator to tree
1423 t3 = lttv_filter_tree_new();
1424 t3->node = LTTV_LOGICAL_NOT;
1425 t1->right = LTTV_TREE_NODE;
1426 t1->r_child.t = t3;
1427 t1 = t3;
1428 not = 0;
1429 }
410c83da 1430 if(subtree != NULL) { /* add the subtree */
1431 t1->right = LTTV_TREE_NODE;
0cdc2470 1432 t1->r_child.t = subtree;
410c83da 1433 subtree = NULL;
1434 } else { /* add a leaf */
9ab5ebd7 1435 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
56e29124 1436 a_field_component = NULL;
410c83da 1437 t1->right = LTTV_TREE_LEAF;
0cdc2470 1438 t1->r_child.leaf = a_simple_expression;
56e29124 1439 a_simple_expression = NULL;
410c83da 1440 }
1441
56e29124 1442
73050a5f 1443 /* free the pointer array */
1444 g_assert(a_field_path->len == 0);
1445 g_ptr_array_free(a_field_path,TRUE);
56e29124 1446
1447 /* free the tree stack -- but keep the root tree */
f3020899 1448 filter->head = g_ptr_array_remove_index(tree_stack,0);
1449 g_ptr_array_free(tree_stack,TRUE);
1450
56e29124 1451 /* free the field buffer if allocated */
1452 if(a_field_component != NULL) g_string_free(a_field_component,TRUE);
1453
1454 /* free the simple expression buffer if allocated */
1455 if(a_simple_expression != NULL) lttv_simple_expression_destroy(a_simple_expression);
73050a5f 1456
f3020899 1457 g_assert(filter->head != NULL); /* tree should exist */
56e29124 1458 g_assert(subtree == NULL); /* remaining subtree should be included in main tree */
be66ef34 1459
1460#ifdef TEST
1461 gettimeofday(&endtime, NULL);
1462
1463 /* Calcul du temps de l'algorithme */
1464 double time1 = starttime.tv_sec + (starttime.tv_usec/1000000.0);
1465 double time2 = endtime.tv_sec + (endtime.tv_usec/1000000.0);
1466// g_print("Tree build took %.10f ms for strlen of %i\n",(time2-time1)*1000,strlen(filter->expression));
1467 g_print("%.10f %i\n",(time2-time1)*1000,strlen(filter->expression));
1468#endif
a4c292d4 1469
56e29124 1470 /* debug */
1471 g_print("+++++++++++++++ BEGIN PRINT ++++++++++++++++\n");
72911c5d 1472 lttv_print_tree(filter->head,0) ;
56e29124 1473 g_print("+++++++++++++++ END PRINT ++++++++++++++++++\n");
1474
1475 /* success */
5f185a2b 1476 return TRUE;
80f9611a 1477
31452f49 1478}
1479
8c89f5a8 1480/**
56e29124 1481 * @fn void lttv_filter_destroy(LttvFilter*)
1482 *
8c89f5a8 1483 * Destroy the current LttvFilter
1484 * @param filter pointer to the current LttvFilter
1485 */
1da1525d 1486void
2ea36caf 1487lttv_filter_destroy(LttvFilter* filter) {
5f185a2b 1488
1489 g_free(filter->expression);
1490 lttv_filter_tree_destroy(filter->head);
1491 g_free(filter);
1492
1da1525d 1493}
1494
150f0d33 1495/**
8ff6243c 1496 * @fn LttvFilterTree* lttv_filter_tree_new()
56e29124 1497 *
150f0d33 1498 * Assign a new tree for the current expression
1499 * or sub expression
1500 * @return pointer of LttvFilterTree
1501 */
5f185a2b 1502LttvFilterTree*
1503lttv_filter_tree_new() {
150f0d33 1504 LttvFilterTree* tree;
1505
e00d6a24 1506 tree = g_new(LttvFilterTree,1);
150f0d33 1507 tree->node = 0; //g_new(lttv_expression,1);
150f0d33 1508 tree->left = LTTV_TREE_IDLE;
1509 tree->right = LTTV_TREE_IDLE;
f3020899 1510 tree->r_child.t = NULL;
1511 tree->l_child.t = NULL;
1512
150f0d33 1513 return tree;
1514}
1515
80f9611a 1516/**
56e29124 1517 * @fn void lttv_filter_append_expression(LttvFilter*,char*)
1518 *
80f9611a 1519 * Append a new expression to the expression
1520 * defined in the current filter
1521 * @param filter pointer to the current LttvFilter
1522 * @param expression string that must be appended
56e29124 1523 * @return Success/Failure of operation
80f9611a 1524 */
be66ef34 1525gboolean
1526lttv_filter_append_expression(LttvFilter* filter, const char *expression) {
80f9611a 1527
56e29124 1528 if(expression == NULL) return FALSE;
da2e1bfb 1529 if(filter == NULL) return FALSE;
80f9611a 1530
da2e1bfb 1531 GString* s = g_string_new("");
1532 if(filter->expression != NULL) {
1533 g_string_append(s,filter->expression);
1534 g_string_append_c(s,'&');
1535 }
1536 g_string_append(s,expression);
786c5c3b 1537
1538 g_free(filter->expression);
da2e1bfb 1539 filter->expression = g_string_free(s,FALSE);
1540
1541 /* TRUE if construction of tree proceeded without errors */
56e29124 1542 return lttv_filter_update(filter);
80f9611a 1543
1544}
1545
1546/**
56e29124 1547 * @fn void lttv_filter_clear_expression(LttvFilter*)
1548 *
80f9611a 1549 * Clear the filter expression from the
1550 * current filter and sets its pointer to NULL
1551 * @param filter pointer to the current LttvFilter
1552 */
be66ef34 1553void
1554lttv_filter_clear_expression(LttvFilter* filter) {
80f9611a 1555
1556 if(filter->expression != NULL) {
1557 g_free(filter->expression);
1558 filter->expression = NULL;
1559 }
1560
1561}
1562
150f0d33 1563/**
56e29124 1564 * @fn void lttv_filter_tree_destroy(LttvFilterTree*)
1565 *
150f0d33 1566 * Destroys the tree and his sub-trees
1567 * @param tree Tree which must be destroyed
1568 */
5f185a2b 1569void
1570lttv_filter_tree_destroy(LttvFilterTree* tree) {
56e29124 1571
150f0d33 1572 if(tree == NULL) return;
1573
56e29124 1574 if(tree->left == LTTV_TREE_LEAF) lttv_simple_expression_destroy(tree->l_child.leaf);
150f0d33 1575 else if(tree->left == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->l_child.t);
1576
56e29124 1577 if(tree->right == LTTV_TREE_LEAF) lttv_simple_expression_destroy(tree->r_child.leaf);
150f0d33 1578 else if(tree->right == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->r_child.t);
1579
e00d6a24 1580// g_free(tree->node);
150f0d33 1581 g_free(tree);
1582}
1583
84a333d6 1584/**
80f9611a 1585 * Global parsing function for the current
1586 * LttvFilterTree
7e7af7f2 1587 * @param t pointer to the current LttvFilterTree
80f9611a 1588 * @param event current LttEvent, NULL if not used
1589 * @param tracefile current LttTracefile, NULL if not used
1590 * @param trace current LttTrace, NULL if not used
1591 * @param state current LttvProcessState, NULL if not used
4d9ff942 1592 * @param context current LttvTracefileContext, NULL if not used
1593 * @return response of filter
84a333d6 1594 */
31452f49 1595gboolean
80f9611a 1596lttv_filter_tree_parse(
4d9ff942 1597 const LttvFilterTree* t,
1598 const LttEvent* event,
1599 const LttTracefile* tracefile,
1600 const LttTrace* trace,
1601 const LttvProcessState* state,
1602 const LttvTracefileContext* context
80f9611a 1603 /*,...*/)
1604{
0769c82f 1605
80f9611a 1606 /*
1601b365 1607 * Each tree is parsed in inorder.
1608 * This way, it's possible to apply the left filter of the
1609 * tree, then decide whether or not the right branch should
1610 * be parsed depending on the linking logical operator
1611 *
80f9611a 1612 * Each node consists in a
1613 * 1. logical operator
1614 * 2. left child ( node or simple expression )
1615 * 3. right child ( node or simple expression )
1616 *
1617 * When the child is a simple expression, we must
1618 * before all determine if the expression refers to
1619 * a structure which is whithin observation ( not NULL ).
1620 * -If so, the expression is evaluated.
1621 * -If not, the result is set to TRUE since this particular
1622 * operation does not interfere with the lttv structure
1623 *
1624 * The result of each simple expression will directly
1625 * affect the next branch. This way, depending on
1626 * the linking logical operator, the parser will decide
1627 * to explore or not the next branch.
1628 * 1. AND OPERATOR
1629 * -If result of left branch is 0 / FALSE
1630 * then don't explore right branch and return 0;
1631 * -If result of left branch is 1 / TRUE then explore
1632 * 2. OR OPERATOR
1633 * -If result of left branch is 1 / TRUE
1634 * then don't explore right branch and return 1;
1635 * -If result of left branch is 0 / FALSE then explore
1636 * 3. XOR OPERATOR
56e29124 1637 * -Result of left branch will not affect exploration of
80f9611a 1638 * right branch
1601b365 1639 */
73050a5f 1640
80f9611a 1641 gboolean lresult = FALSE, rresult = FALSE;
0769c82f 1642
80f9611a 1643 /*
1644 * Parse left branch
1645 */
4d9ff942 1646 if(t->left == LTTV_TREE_NODE) {
1647 lresult = lttv_filter_tree_parse(t->l_child.t,event,tracefile,trace,state,context);
1648 }
5b729fcf 1649 else if(t->left == LTTV_TREE_LEAF) {
4d9ff942 1650 lresult = lttv_filter_tree_parse_branch(t->l_child.leaf,event,tracefile,trace,state,context);
0cdc2470 1651 }
4d9ff942 1652
80f9611a 1653 /*
1654 * Parse linking operator
1655 * make a cutoff if possible
1656 */
1657 if((t->node & LTTV_LOGICAL_OR) && lresult == TRUE) return TRUE;
1658 if((t->node & LTTV_LOGICAL_AND) && lresult == FALSE) return FALSE;
1659
1660 /*
1661 * Parse right branch
1662 */
4d9ff942 1663 if(t->right == LTTV_TREE_NODE) {
1664 rresult = lttv_filter_tree_parse(t->r_child.t,event,tracefile,trace,state,context);
1665 }
5b729fcf 1666 else if(t->right == LTTV_TREE_LEAF) {
4d9ff942 1667 rresult = lttv_filter_tree_parse_branch(t->r_child.leaf,event,tracefile,trace,state,context);
1668 }
2bdb97c5 1669
2bdb97c5 1670
4d9ff942 1671 /*
1672 * Apply and return the
1673 * logical link between the
1674 * two operation
1675 */
1676 switch(t->node) {
1677 case LTTV_LOGICAL_OR: return (lresult | rresult);
1678 case LTTV_LOGICAL_AND: return (lresult & rresult);
72911c5d 1679 case LTTV_LOGICAL_NOT:
1680 return (t->left==LTTV_TREE_LEAF)?!lresult:((t->right==LTTV_TREE_LEAF)?!rresult:TRUE);
4d9ff942 1681 case LTTV_LOGICAL_XOR: return (lresult ^ rresult);
1682 case 0: return (rresult);
1683 default:
1684 /*
1685 * This case should never be
1686 * parsed, if so, this subtree
1687 * is cancelled !
1688 */
1689 return TRUE;
1690 }
1691
1692}
1693
1694/**
4d9ff942 1695 * This function parses a particular branch of the tree
7e7af7f2 1696 * @param se pointer to the current LttvSimpleExpression
4d9ff942 1697 * @param event current LttEvent, NULL if not used
1698 * @param tracefile current LttTracefile, NULL if not used
1699 * @param trace current LttTrace, NULL if not used
1700 * @param state current LttvProcessState, NULL if not used
1701 * @param context current LttvTracefileContext, NULL if not used
1702 * @return response of filter
1703 */
be66ef34 1704gboolean
1705lttv_filter_tree_parse_branch(
4d9ff942 1706 const LttvSimpleExpression* se,
1707 const LttEvent* event,
1708 const LttTracefile* tracefile,
1709 const LttTrace* trace,
1710 const LttvProcessState* state,
1711 const LttvTracefileContext* context) {
1712
9ab5ebd7 1713 LttvFieldValue v;
4d9ff942 1714 v = se->value;
1715 switch(se->field) {
80f9611a 1716 case LTTV_FILTER_TRACE_NAME:
4d9ff942 1717 if(trace == NULL) return TRUE;
c6832b57 1718 else {
bbd9d557 1719 char* trace_name = ltt_trace_name(trace);
1720 GQuark quark = g_quark_from_string(trace_name);
c6832b57 1721 return se->op((gpointer)&quark,v);
1722 }
80f9611a 1723 break;
1724 case LTTV_FILTER_TRACEFILE_NAME:
4d9ff942 1725 if(tracefile == NULL) return TRUE;
c6832b57 1726 else {
bbd9d557 1727 char* tracefile_name = ltt_tracefile_name(tracefile);
1728 GQuark quark = g_quark_from_string(tracefile_name);
c6832b57 1729 return se->op((gpointer)&quark,v);
1730 }
80f9611a 1731 break;
1732 case LTTV_FILTER_STATE_PID:
4d9ff942 1733 if(state == NULL) return TRUE;
1734 else return se->op((gpointer)&state->pid,v);
80f9611a 1735 break;
1736 case LTTV_FILTER_STATE_PPID:
4d9ff942 1737 if(state == NULL) return TRUE;
1738 else return se->op((gpointer)&state->ppid,v);
80f9611a 1739 break;
1740 case LTTV_FILTER_STATE_CT:
4d9ff942 1741 if(state == NULL) return TRUE;
80f9611a 1742 else {
4d9ff942 1743 return se->op((gpointer)&state->creation_time,v);
80f9611a 1744 }
1745 break;
1746 case LTTV_FILTER_STATE_IT:
4d9ff942 1747 if(state == NULL) return TRUE;
80f9611a 1748 else {
4d9ff942 1749 return se->op((gpointer)&state->insertion_time,v);
80f9611a 1750 }
1751 break;
1752 case LTTV_FILTER_STATE_P_NAME:
1753 /*
4d9ff942 1754 * All 'unnamed' for the moment
80f9611a 1755 */
4d9ff942 1756 if(state == NULL) return TRUE;
46c40a93 1757 else {
bbd9d557 1758 GQuark quark = state->name;
c6832b57 1759 return se->op((gpointer)&quark,v);
46c40a93 1760 }
80f9611a 1761 break;
1762 case LTTV_FILTER_STATE_EX_MODE:
4d9ff942 1763 if(state == NULL) return TRUE;
1764 else return se->op((gpointer)&state->state->t,v);
80f9611a 1765 break;
1766 case LTTV_FILTER_STATE_EX_SUBMODE:
4d9ff942 1767 if(state == NULL) return TRUE;
1768 else return se->op((gpointer)&state->state->n,v);
80f9611a 1769 break;
1770 case LTTV_FILTER_STATE_P_STATUS:
4d9ff942 1771 if(state == NULL) return TRUE;
1772 else return se->op((gpointer)&state->state->s,v);
80f9611a 1773 break;
1774 case LTTV_FILTER_STATE_CPU:
4d9ff942 1775 if(context == NULL) return TRUE;
46c40a93 1776 else {
bbd9d557 1777 /* FIXME: not sure of that one */
1778 GQuark quark = ((LttvTracefileState*)context)->cpu_name;
1779 return se->op((gpointer)&quark,v);
46c40a93 1780 }
80f9611a 1781 break;
1782 case LTTV_FILTER_EVENT_NAME:
4d9ff942 1783 if(event == NULL) return TRUE;
1784 else {
46c40a93 1785 LttEventType* et;
1786 et = ltt_event_eventtype(event);
bbd9d557 1787 char* event_name = ltt_eventtype_name(et);
1788 GQuark quark = g_quark_from_string(event_name);
c6832b57 1789 return se->op((gpointer)&quark,v);
4d9ff942 1790 }
1791 break;
1792
80f9611a 1793 case LTTV_FILTER_EVENT_CATEGORY:
1794 /*
c6832b57 1795 * TODO: Not yet implemented
80f9611a 1796 */
4d9ff942 1797 return TRUE;
80f9611a 1798 break;
1799 case LTTV_FILTER_EVENT_TIME:
4d9ff942 1800 if(event == NULL) return TRUE;
46c40a93 1801 else {
1802 LttTime time = ltt_event_time(event);
4d9ff942 1803 return se->op((gpointer)&time,v);
46c40a93 1804 }
80f9611a 1805 break;
1806 case LTTV_FILTER_EVENT_TSC:
bbd9d557 1807 if(event == NULL) return TRUE;
1808 else {
1809 LttCycleCount count = ltt_event_cycle_count(event);
1810 return se->op((gpointer)&count,v);
1811 }
80f9611a 1812 break;
1813 case LTTV_FILTER_EVENT_FIELD:
1814 /*
1815 * TODO: Use the offset to
1816 * find the dynamic field
1817 * in the event struct
1818 */
4d9ff942 1819 return TRUE;
80f9611a 1820 default:
1821 /*
1822 * This case should never be
4d9ff942 1823 * parsed, if so, the whole
1824 * filtering is cancelled
80f9611a 1825 */
1826 g_warning("Error while parsing the filter tree");
1827 return TRUE;
1828 }
4d9ff942 1829
1830 /* should never get here */
1831 return TRUE;
1832
80f9611a 1833}
0769c82f 1834
4d9ff942 1835
1836
80f9611a 1837/**
7e7af7f2 1838 * Debug function. Prints tree memory allocation.
56e29124 1839 * @param t the pointer to the current LttvFilterTree
80f9611a 1840 */
1841void
72911c5d 1842lttv_print_tree(const LttvFilterTree* t, const int count) {
0769c82f 1843
72911c5d 1844 g_print("node:%p lchild:%p rchild:%p depth:%i\n",t, //t->l_child.t,t->r_child.t);
80f9611a 1845 (t->left==LTTV_TREE_NODE)?t->l_child.t:NULL,
72911c5d 1846 (t->right==LTTV_TREE_NODE)?t->r_child.t:NULL,
1847 count);
1848 g_print("logic operator: %s\n",(t->node&1)?"OR":((t->node&2)?"AND":((t->node&4)?"NOT":((t->node&8)?"XOR":"IDLE"))));
1849 g_print("|-> left branch %p is a %s\n",t->l_child.t,(t->left==LTTV_TREE_NODE)?"NODE":((t->left==LTTV_TREE_LEAF)?"LEAF":"IDLE"));
1850 if(t->left == LTTV_TREE_LEAF) {
1851 g_print("| |-> field type number: %i\n",t->l_child.leaf->field);
1852 g_print("| |-> offset is: %i\n",t->l_child.leaf->offset);
1853 g_print("| |-> operator function is: %p\n",t->l_child.leaf->op);
0769c82f 1854 }
72911c5d 1855 g_print("|-> right branch %p is a %s\n",t->r_child.t,(t->right==LTTV_TREE_NODE)?"NODE":((t->right==LTTV_TREE_LEAF)?"LEAF":"IDLE"));
1856 if(t->right == LTTV_TREE_LEAF) {
1857 g_print("| |-> field type number: %i\n",t->r_child.leaf->field);
1858 g_print("| |-> offset is: %i\n",t->r_child.leaf->offset);
1859 g_print("| |-> operator function is: %p\n",t->r_child.leaf->op);
80f9611a 1860 }
72911c5d 1861
1862 if(t->left == LTTV_TREE_NODE) lttv_print_tree(t->l_child.t,count+1);
1863 if(t->right == LTTV_TREE_NODE) lttv_print_tree(t->r_child.t,count+1);
80f9611a 1864}
1865
91ad3f0a 1866/**
56e29124 1867 * @fn static void module_init()
1868 *
91ad3f0a 1869 * Initializes the filter module and specific values
1870 */
1a7fa682 1871static void module_init()
1872{
91ad3f0a 1873
1a7fa682 1874}
1875
91ad3f0a 1876/**
7e7af7f2 1877 * Destroys the filter module and specific values
91ad3f0a 1878 */
1a7fa682 1879static void module_destroy()
1880{
56e29124 1881
1a7fa682 1882}
1883
1884
91ad3f0a 1885LTTV_MODULE("filter", "Filters traceset and events", \
1886 "Filters traceset and events specifically to user input", \
1a7fa682 1887 module_init, module_destroy)
1888
1889
1890
This page took 0.129104 seconds and 4 git commands to generate.