filter core:
[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;
591 g_print("v1:%i v2:%i\n",*r,v2.v_uint32);
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;
1193// g_print("%i\n",t2->left);
1194// g_print("*************************************\n");
1195// lttv_print_tree(t2,0);
1196// g_print("*************************************\n");
1197// lttv_print_tree(t3,0);
1198// g_print("*************************************\n");
1199 t2 = t3;
1200 not = 0;
1201// g_print("ici t1:%p t2:%p t3:%p\n",t1,t2,t3);
1202 }
bb87caa7 1203 if(subtree != NULL) { /* append subtree to current tree */
18d1226f 1204 t2->left = LTTV_TREE_NODE;
1205 t2->l_child.t = subtree;
f4e9dd16 1206 subtree = NULL;
bb87caa7 1207 } else { /* append a simple expression */
9ab5ebd7 1208 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
18d1226f 1209 a_field_component = g_string_new("");
1210 t2->left = LTTV_TREE_LEAF;
0cdc2470 1211 t2->l_child.leaf = a_simple_expression;
389ba50e 1212 a_simple_expression = lttv_simple_expression_new();
f4e9dd16 1213 }
f4e9dd16 1214 break;
aa4600f3 1215
a4c292d4 1216 case '|': /* or */
aa4600f3 1217
e00d6a24 1218 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
9ab5ebd7 1219 while(t1->right != LTTV_TREE_IDLE) {
1220 g_assert(t1->right == LTTV_TREE_NODE);
1221 t1 = t1->r_child.t;
1222 }
1601b365 1223 t2 = lttv_filter_tree_new();
0cdc2470 1224 t2->node = LTTV_LOGICAL_OR;
72911c5d 1225 t1->right = LTTV_TREE_NODE;
1226 t1->r_child.t = t2;
1227 if(not) { // add not operator to tree
1228 t3 = lttv_filter_tree_new();
1229 t3->node = LTTV_LOGICAL_NOT;
1230 t2->left = LTTV_TREE_NODE;
1231 t2->l_child.t = t3;
1232 t2 = t3;
1233 not = 0;
1234 }
1235 if(subtree != NULL) { /* append subtree to current tree */
1601b365 1236 t2->left = LTTV_TREE_NODE;
1237 t2->l_child.t = subtree;
1238 subtree = NULL;
72911c5d 1239 } else { /* append a simple expression */
9ab5ebd7 1240 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1601b365 1241 a_field_component = g_string_new("");
1242 t2->left = LTTV_TREE_LEAF;
0cdc2470 1243 t2->l_child.leaf = a_simple_expression;
389ba50e 1244 a_simple_expression = lttv_simple_expression_new();
1601b365 1245 }
f4e9dd16 1246 break;
aa4600f3 1247
a4c292d4 1248 case '^': /* xor */
aa4600f3 1249
e00d6a24 1250 t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1);
9ab5ebd7 1251 while(t1->right != LTTV_TREE_IDLE) {
1252 g_assert(t1->right == LTTV_TREE_NODE);
1253 t1 = t1->r_child.t;
1254 }
1601b365 1255 t2 = lttv_filter_tree_new();
0cdc2470 1256 t2->node = LTTV_LOGICAL_XOR;
72911c5d 1257 t1->right = LTTV_TREE_NODE;
1258 t1->r_child.t = t2;
1259 if(not) { // add not operator to tree
1260 t3 = lttv_filter_tree_new();
1261 t3->node = LTTV_LOGICAL_NOT;
1262 t2->left = LTTV_TREE_NODE;
1263 t2->l_child.t = t3;
1264 t2 = t3;
1265 not = 0;
1266 }
bb87caa7 1267 if(subtree != NULL) { /* append subtree to current tree */
1601b365 1268 t2->left = LTTV_TREE_NODE;
1269 t2->l_child.t = subtree;
1270 subtree = NULL;
bb87caa7 1271 } else { /* append a simple expression */
9ab5ebd7 1272 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
1601b365 1273 a_field_component = g_string_new("");
1274 t2->left = LTTV_TREE_LEAF;
0cdc2470 1275 t2->l_child.leaf = a_simple_expression;
389ba50e 1276 a_simple_expression = lttv_simple_expression_new();
1601b365 1277 }
a4c292d4 1278 break;
aa4600f3 1279
a4c292d4 1280 case '!': /* not, or not equal (math op) */
aa4600f3 1281
5f185a2b 1282 if(filter->expression[i+1] == '=') { /* != */
0cdc2470 1283 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
9ab5ebd7 1284 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
0cdc2470 1285 a_field_component = g_string_new("");
56e29124 1286 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_NE);
aa4600f3 1287 i++;
a4c292d4 1288 } else { /* ! */
72911c5d 1289 not=1;
a4c292d4 1290 }
1291 break;
aa4600f3 1292
a4c292d4 1293 case '(': /* start of parenthesis */
91ad3f0a 1294 case '[':
1295 case '{':
aa4600f3 1296
91ad3f0a 1297 p_nesting++; /* incrementing parenthesis nesting value */
1601b365 1298 t1 = lttv_filter_tree_new();
72911c5d 1299 if(not) { /* add not operator to tree */
1300 t3 = lttv_filter_tree_new();
1301 t3->node = LTTV_LOGICAL_NOT;
1302 t1->right = LTTV_TREE_NODE;
1303 t1->r_child.t = t3;
1304 not = 0;
1305 }
1601b365 1306 g_ptr_array_add( tree_stack,(gpointer) t1 );
a4c292d4 1307 break;
aa4600f3 1308
a4c292d4 1309 case ')': /* end of parenthesis */
91ad3f0a 1310 case ']':
1311 case '}':
aa4600f3 1312
91ad3f0a 1313 p_nesting--; /* decrementing parenthesis nesting value */
18d1226f 1314 if(p_nesting<0 || tree_stack->len<2) {
f4e9dd16 1315 g_warning("Wrong filtering options, the string\n\"%s\"\n\
5f185a2b 1316 is not valid due to parenthesis incorrect use",filter->expression);
1317 return FALSE;
f4e9dd16 1318 }
56e29124 1319
1320 /* there must at least be the root tree left in the array */
18d1226f 1321 g_assert(tree_stack->len>0);
72911c5d 1322
1323 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
1324 while(t1->right != LTTV_TREE_IDLE) {
1325 t1 = t1->r_child.t;
1326 }
1327 if(not) { // add not operator to tree
1328 g_print("ici");
1329 t3 = lttv_filter_tree_new();
1330 t3->node = LTTV_LOGICAL_NOT;
1331 t1->right = LTTV_TREE_NODE;
1332 t1->r_child.t = t3;
1333 t1 = t3;
1334 not = 0;
1335 }
bb87caa7 1336 if(subtree != NULL) { /* append subtree to current tree */
18d1226f 1337 t1->right = LTTV_TREE_NODE;
1338 t1->r_child.t = subtree;
1339 subtree = g_ptr_array_index(tree_stack,tree_stack->len-1);
1340 g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
bb87caa7 1341 } else { /* assign subtree as current tree */
9ab5ebd7 1342 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
18d1226f 1343 a_field_component = g_string_new("");
18d1226f 1344 t1->right = LTTV_TREE_LEAF;
0cdc2470 1345 t1->r_child.leaf = a_simple_expression;
389ba50e 1346 a_simple_expression = lttv_simple_expression_new();
9ab5ebd7 1347 subtree = g_ptr_array_remove_index(tree_stack,tree_stack->len-1);
18d1226f 1348 }
a4c292d4 1349 break;
1350
1351 /*
1352 * mathematic operators
1353 */
1354 case '<': /* lower, lower or equal */
aa4600f3 1355
1356 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
9ab5ebd7 1357 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
aa4600f3 1358 a_field_component = g_string_new("");
5f185a2b 1359 if(filter->expression[i+1] == '=') { /* <= */
a4c292d4 1360 i++;
56e29124 1361 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_LE);
1362 } else lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_LT);
aa4600f3 1363 break;
1364
1365 case '>': /* higher, higher or equal */
1366
1367 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
9ab5ebd7 1368 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
f4e9dd16 1369 a_field_component = g_string_new("");
5f185a2b 1370 if(filter->expression[i+1] == '=') { /* >= */
a4c292d4 1371 i++;
56e29124 1372 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_GE);
1373 } else lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_GT);
aa4600f3 1374 break;
1375
a4c292d4 1376 case '=': /* equal */
aa4600f3 1377
f4e9dd16 1378 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
9ab5ebd7 1379 lttv_simple_expression_assign_field(a_field_path,a_simple_expression);
f4e9dd16 1380 a_field_component = g_string_new("");
56e29124 1381 lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_EQ);
a4c292d4 1382 break;
aa4600f3 1383
0769c82f 1384 /*
1385 * Field concatening caracter
1386 */
1387 case '.': /* dot */
aa4600f3 1388
bb87caa7 1389 /*
1390 * divide field expression into elements
1391 * in a_field_path array.
4d9ff942 1392 *
1393 * A dot can also be present in double values
bb87caa7 1394 */
8ff6243c 1395 if(a_simple_expression->field == LTTV_FILTER_UNDEFINED) {
bb87caa7 1396 g_ptr_array_add( a_field_path,(gpointer) a_field_component );
1397 a_field_component = g_string_new("");
8ff6243c 1398 }
1399 break;
4d9ff942 1400 case ' ': /* ignore */
1401 case '\n': /* ignore */
0769c82f 1402 break;
a4c292d4 1403 default: /* concatening current string */
73050a5f 1404 g_string_append_c(a_field_component,filter->expression[i]);
a4c292d4 1405 }
1406 }
1601b365 1407
0cdc2470 1408 /*
1409 * Preliminary check to see
1410 * if tree was constructed correctly
1411 */
1412 if( p_nesting>0 ) {
1413 g_warning("Wrong filtering options, the string\n\"%s\"\n\
5f185a2b 1414 is not valid due to parenthesis incorrect use",filter->expression);
1415 return FALSE;
0cdc2470 1416 }
1417
1418 if(tree_stack->len != 1) /* only root tree should remain */
5f185a2b 1419 return FALSE;
1601b365 1420
72911c5d 1421 /*
1422 * processing last element of expression
1423 */
410c83da 1424 t1 = g_ptr_array_index(tree_stack,tree_stack->len-1);
9ab5ebd7 1425 while(t1->right != LTTV_TREE_IDLE) {
1426 g_assert(t1->right == LTTV_TREE_NODE);
1427 t1 = t1->r_child.t;
1428 }
72911c5d 1429 if(not) { // add not operator to tree
1430 t3 = lttv_filter_tree_new();
1431 t3->node = LTTV_LOGICAL_NOT;
1432 t1->right = LTTV_TREE_NODE;
1433 t1->r_child.t = t3;
1434 t1 = t3;
1435 not = 0;
1436 }
410c83da 1437 if(subtree != NULL) { /* add the subtree */
1438 t1->right = LTTV_TREE_NODE;
0cdc2470 1439 t1->r_child.t = subtree;
410c83da 1440 subtree = NULL;
1441 } else { /* add a leaf */
9ab5ebd7 1442 lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE));
56e29124 1443 a_field_component = NULL;
410c83da 1444 t1->right = LTTV_TREE_LEAF;
0cdc2470 1445 t1->r_child.leaf = a_simple_expression;
56e29124 1446 a_simple_expression = NULL;
410c83da 1447 }
1448
56e29124 1449
73050a5f 1450 /* free the pointer array */
1451 g_assert(a_field_path->len == 0);
1452 g_ptr_array_free(a_field_path,TRUE);
56e29124 1453
1454 /* free the tree stack -- but keep the root tree */
f3020899 1455 filter->head = g_ptr_array_remove_index(tree_stack,0);
1456 g_ptr_array_free(tree_stack,TRUE);
1457
56e29124 1458 /* free the field buffer if allocated */
1459 if(a_field_component != NULL) g_string_free(a_field_component,TRUE);
1460
1461 /* free the simple expression buffer if allocated */
1462 if(a_simple_expression != NULL) lttv_simple_expression_destroy(a_simple_expression);
73050a5f 1463
f3020899 1464 g_assert(filter->head != NULL); /* tree should exist */
56e29124 1465 g_assert(subtree == NULL); /* remaining subtree should be included in main tree */
be66ef34 1466
1467#ifdef TEST
1468 gettimeofday(&endtime, NULL);
1469
1470 /* Calcul du temps de l'algorithme */
1471 double time1 = starttime.tv_sec + (starttime.tv_usec/1000000.0);
1472 double time2 = endtime.tv_sec + (endtime.tv_usec/1000000.0);
1473// g_print("Tree build took %.10f ms for strlen of %i\n",(time2-time1)*1000,strlen(filter->expression));
1474 g_print("%.10f %i\n",(time2-time1)*1000,strlen(filter->expression));
1475#endif
a4c292d4 1476
56e29124 1477 /* debug */
1478 g_print("+++++++++++++++ BEGIN PRINT ++++++++++++++++\n");
72911c5d 1479 lttv_print_tree(filter->head,0) ;
56e29124 1480 g_print("+++++++++++++++ END PRINT ++++++++++++++++++\n");
1481
1482 /* success */
5f185a2b 1483 return TRUE;
80f9611a 1484
31452f49 1485}
1486
8c89f5a8 1487/**
56e29124 1488 * @fn void lttv_filter_destroy(LttvFilter*)
1489 *
8c89f5a8 1490 * Destroy the current LttvFilter
1491 * @param filter pointer to the current LttvFilter
1492 */
1da1525d 1493void
2ea36caf 1494lttv_filter_destroy(LttvFilter* filter) {
5f185a2b 1495
1496 g_free(filter->expression);
1497 lttv_filter_tree_destroy(filter->head);
1498 g_free(filter);
1499
1da1525d 1500}
1501
150f0d33 1502/**
8ff6243c 1503 * @fn LttvFilterTree* lttv_filter_tree_new()
56e29124 1504 *
150f0d33 1505 * Assign a new tree for the current expression
1506 * or sub expression
1507 * @return pointer of LttvFilterTree
1508 */
5f185a2b 1509LttvFilterTree*
1510lttv_filter_tree_new() {
150f0d33 1511 LttvFilterTree* tree;
1512
e00d6a24 1513 tree = g_new(LttvFilterTree,1);
150f0d33 1514 tree->node = 0; //g_new(lttv_expression,1);
150f0d33 1515 tree->left = LTTV_TREE_IDLE;
1516 tree->right = LTTV_TREE_IDLE;
f3020899 1517 tree->r_child.t = NULL;
1518 tree->l_child.t = NULL;
1519
150f0d33 1520 return tree;
1521}
1522
80f9611a 1523/**
56e29124 1524 * @fn void lttv_filter_append_expression(LttvFilter*,char*)
1525 *
80f9611a 1526 * Append a new expression to the expression
1527 * defined in the current filter
1528 * @param filter pointer to the current LttvFilter
1529 * @param expression string that must be appended
56e29124 1530 * @return Success/Failure of operation
80f9611a 1531 */
be66ef34 1532gboolean
1533lttv_filter_append_expression(LttvFilter* filter, const char *expression) {
80f9611a 1534
56e29124 1535 if(expression == NULL) return FALSE;
da2e1bfb 1536 if(filter == NULL) return FALSE;
80f9611a 1537
da2e1bfb 1538 GString* s = g_string_new("");
1539 if(filter->expression != NULL) {
1540 g_string_append(s,filter->expression);
1541 g_string_append_c(s,'&');
1542 }
1543 g_string_append(s,expression);
786c5c3b 1544
1545 g_free(filter->expression);
da2e1bfb 1546 filter->expression = g_string_free(s,FALSE);
1547
1548 /* TRUE if construction of tree proceeded without errors */
56e29124 1549 return lttv_filter_update(filter);
80f9611a 1550
1551}
1552
1553/**
56e29124 1554 * @fn void lttv_filter_clear_expression(LttvFilter*)
1555 *
80f9611a 1556 * Clear the filter expression from the
1557 * current filter and sets its pointer to NULL
1558 * @param filter pointer to the current LttvFilter
1559 */
be66ef34 1560void
1561lttv_filter_clear_expression(LttvFilter* filter) {
80f9611a 1562
1563 if(filter->expression != NULL) {
1564 g_free(filter->expression);
1565 filter->expression = NULL;
1566 }
1567
1568}
1569
150f0d33 1570/**
56e29124 1571 * @fn void lttv_filter_tree_destroy(LttvFilterTree*)
1572 *
150f0d33 1573 * Destroys the tree and his sub-trees
1574 * @param tree Tree which must be destroyed
1575 */
5f185a2b 1576void
1577lttv_filter_tree_destroy(LttvFilterTree* tree) {
56e29124 1578
150f0d33 1579 if(tree == NULL) return;
1580
56e29124 1581 if(tree->left == LTTV_TREE_LEAF) lttv_simple_expression_destroy(tree->l_child.leaf);
150f0d33 1582 else if(tree->left == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->l_child.t);
1583
56e29124 1584 if(tree->right == LTTV_TREE_LEAF) lttv_simple_expression_destroy(tree->r_child.leaf);
150f0d33 1585 else if(tree->right == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->r_child.t);
1586
e00d6a24 1587// g_free(tree->node);
150f0d33 1588 g_free(tree);
1589}
1590
84a333d6 1591/**
80f9611a 1592 * Global parsing function for the current
1593 * LttvFilterTree
7e7af7f2 1594 * @param t pointer to the current LttvFilterTree
80f9611a 1595 * @param event current LttEvent, NULL if not used
1596 * @param tracefile current LttTracefile, NULL if not used
1597 * @param trace current LttTrace, NULL if not used
1598 * @param state current LttvProcessState, NULL if not used
4d9ff942 1599 * @param context current LttvTracefileContext, NULL if not used
1600 * @return response of filter
84a333d6 1601 */
31452f49 1602gboolean
80f9611a 1603lttv_filter_tree_parse(
4d9ff942 1604 const LttvFilterTree* t,
1605 const LttEvent* event,
1606 const LttTracefile* tracefile,
1607 const LttTrace* trace,
1608 const LttvProcessState* state,
1609 const LttvTracefileContext* context
80f9611a 1610 /*,...*/)
1611{
0769c82f 1612
80f9611a 1613 /*
1601b365 1614 * Each tree is parsed in inorder.
1615 * This way, it's possible to apply the left filter of the
1616 * tree, then decide whether or not the right branch should
1617 * be parsed depending on the linking logical operator
1618 *
80f9611a 1619 * Each node consists in a
1620 * 1. logical operator
1621 * 2. left child ( node or simple expression )
1622 * 3. right child ( node or simple expression )
1623 *
1624 * When the child is a simple expression, we must
1625 * before all determine if the expression refers to
1626 * a structure which is whithin observation ( not NULL ).
1627 * -If so, the expression is evaluated.
1628 * -If not, the result is set to TRUE since this particular
1629 * operation does not interfere with the lttv structure
1630 *
1631 * The result of each simple expression will directly
1632 * affect the next branch. This way, depending on
1633 * the linking logical operator, the parser will decide
1634 * to explore or not the next branch.
1635 * 1. AND OPERATOR
1636 * -If result of left branch is 0 / FALSE
1637 * then don't explore right branch and return 0;
1638 * -If result of left branch is 1 / TRUE then explore
1639 * 2. OR OPERATOR
1640 * -If result of left branch is 1 / TRUE
1641 * then don't explore right branch and return 1;
1642 * -If result of left branch is 0 / FALSE then explore
1643 * 3. XOR OPERATOR
56e29124 1644 * -Result of left branch will not affect exploration of
80f9611a 1645 * right branch
1601b365 1646 */
73050a5f 1647
80f9611a 1648 gboolean lresult = FALSE, rresult = FALSE;
0769c82f 1649
80f9611a 1650 /*
1651 * Parse left branch
1652 */
4d9ff942 1653 if(t->left == LTTV_TREE_NODE) {
1654 lresult = lttv_filter_tree_parse(t->l_child.t,event,tracefile,trace,state,context);
1655 }
5b729fcf 1656 else if(t->left == LTTV_TREE_LEAF) {
4d9ff942 1657 lresult = lttv_filter_tree_parse_branch(t->l_child.leaf,event,tracefile,trace,state,context);
0cdc2470 1658 }
4d9ff942 1659
80f9611a 1660 /*
1661 * Parse linking operator
1662 * make a cutoff if possible
1663 */
1664 if((t->node & LTTV_LOGICAL_OR) && lresult == TRUE) return TRUE;
1665 if((t->node & LTTV_LOGICAL_AND) && lresult == FALSE) return FALSE;
1666
1667 /*
1668 * Parse right branch
1669 */
4d9ff942 1670 if(t->right == LTTV_TREE_NODE) {
1671 rresult = lttv_filter_tree_parse(t->r_child.t,event,tracefile,trace,state,context);
1672 }
5b729fcf 1673 else if(t->right == LTTV_TREE_LEAF) {
4d9ff942 1674 rresult = lttv_filter_tree_parse_branch(t->r_child.leaf,event,tracefile,trace,state,context);
1675 }
1676
1677 /*
1678 * Apply and return the
1679 * logical link between the
1680 * two operation
1681 */
1682 switch(t->node) {
1683 case LTTV_LOGICAL_OR: return (lresult | rresult);
1684 case LTTV_LOGICAL_AND: return (lresult & rresult);
72911c5d 1685 case LTTV_LOGICAL_NOT:
1686 return (t->left==LTTV_TREE_LEAF)?!lresult:((t->right==LTTV_TREE_LEAF)?!rresult:TRUE);
4d9ff942 1687 case LTTV_LOGICAL_XOR: return (lresult ^ rresult);
1688 case 0: return (rresult);
1689 default:
1690 /*
1691 * This case should never be
1692 * parsed, if so, this subtree
1693 * is cancelled !
1694 */
1695 return TRUE;
1696 }
1697
1698}
1699
1700/**
4d9ff942 1701 * This function parses a particular branch of the tree
7e7af7f2 1702 * @param se pointer to the current LttvSimpleExpression
4d9ff942 1703 * @param event current LttEvent, NULL if not used
1704 * @param tracefile current LttTracefile, NULL if not used
1705 * @param trace current LttTrace, NULL if not used
1706 * @param state current LttvProcessState, NULL if not used
1707 * @param context current LttvTracefileContext, NULL if not used
1708 * @return response of filter
1709 */
be66ef34 1710gboolean
1711lttv_filter_tree_parse_branch(
4d9ff942 1712 const LttvSimpleExpression* se,
1713 const LttEvent* event,
1714 const LttTracefile* tracefile,
1715 const LttTrace* trace,
1716 const LttvProcessState* state,
1717 const LttvTracefileContext* context) {
1718
9ab5ebd7 1719 LttvFieldValue v;
4d9ff942 1720 v = se->value;
1721 switch(se->field) {
80f9611a 1722 case LTTV_FILTER_TRACE_NAME:
4d9ff942 1723 if(trace == NULL) return TRUE;
c6832b57 1724 else {
bbd9d557 1725 char* trace_name = ltt_trace_name(trace);
1726 GQuark quark = g_quark_from_string(trace_name);
c6832b57 1727 return se->op((gpointer)&quark,v);
1728 }
80f9611a 1729 break;
1730 case LTTV_FILTER_TRACEFILE_NAME:
4d9ff942 1731 if(tracefile == NULL) return TRUE;
c6832b57 1732 else {
bbd9d557 1733 char* tracefile_name = ltt_tracefile_name(tracefile);
1734 GQuark quark = g_quark_from_string(tracefile_name);
c6832b57 1735 return se->op((gpointer)&quark,v);
1736 }
80f9611a 1737 break;
1738 case LTTV_FILTER_STATE_PID:
4d9ff942 1739 if(state == NULL) return TRUE;
1740 else return se->op((gpointer)&state->pid,v);
80f9611a 1741 break;
1742 case LTTV_FILTER_STATE_PPID:
4d9ff942 1743 if(state == NULL) return TRUE;
1744 else return se->op((gpointer)&state->ppid,v);
80f9611a 1745 break;
1746 case LTTV_FILTER_STATE_CT:
4d9ff942 1747 if(state == NULL) return TRUE;
80f9611a 1748 else {
4d9ff942 1749 return se->op((gpointer)&state->creation_time,v);
80f9611a 1750 }
1751 break;
1752 case LTTV_FILTER_STATE_IT:
4d9ff942 1753 if(state == NULL) return TRUE;
80f9611a 1754 else {
4d9ff942 1755 return se->op((gpointer)&state->insertion_time,v);
80f9611a 1756 }
1757 break;
1758 case LTTV_FILTER_STATE_P_NAME:
1759 /*
4d9ff942 1760 * All 'unnamed' for the moment
80f9611a 1761 */
4d9ff942 1762 if(state == NULL) return TRUE;
46c40a93 1763 else {
bbd9d557 1764 GQuark quark = state->name;
c6832b57 1765 return se->op((gpointer)&quark,v);
46c40a93 1766 }
80f9611a 1767 break;
1768 case LTTV_FILTER_STATE_EX_MODE:
4d9ff942 1769 if(state == NULL) return TRUE;
1770 else return se->op((gpointer)&state->state->t,v);
80f9611a 1771 break;
1772 case LTTV_FILTER_STATE_EX_SUBMODE:
4d9ff942 1773 if(state == NULL) return TRUE;
1774 else return se->op((gpointer)&state->state->n,v);
80f9611a 1775 break;
1776 case LTTV_FILTER_STATE_P_STATUS:
4d9ff942 1777 if(state == NULL) return TRUE;
1778 else return se->op((gpointer)&state->state->s,v);
80f9611a 1779 break;
1780 case LTTV_FILTER_STATE_CPU:
4d9ff942 1781 if(context == NULL) return TRUE;
46c40a93 1782 else {
bbd9d557 1783 /* FIXME: not sure of that one */
1784 GQuark quark = ((LttvTracefileState*)context)->cpu_name;
1785 return se->op((gpointer)&quark,v);
46c40a93 1786 }
80f9611a 1787 break;
1788 case LTTV_FILTER_EVENT_NAME:
4d9ff942 1789 if(event == NULL) return TRUE;
1790 else {
46c40a93 1791 LttEventType* et;
1792 et = ltt_event_eventtype(event);
bbd9d557 1793 char* event_name = ltt_eventtype_name(et);
1794 GQuark quark = g_quark_from_string(event_name);
c6832b57 1795 return se->op((gpointer)&quark,v);
4d9ff942 1796 }
1797 break;
1798
80f9611a 1799 case LTTV_FILTER_EVENT_CATEGORY:
1800 /*
c6832b57 1801 * TODO: Not yet implemented
80f9611a 1802 */
4d9ff942 1803 return TRUE;
80f9611a 1804 break;
1805 case LTTV_FILTER_EVENT_TIME:
4d9ff942 1806 if(event == NULL) return TRUE;
46c40a93 1807 else {
1808 LttTime time = ltt_event_time(event);
4d9ff942 1809 return se->op((gpointer)&time,v);
46c40a93 1810 }
80f9611a 1811 break;
1812 case LTTV_FILTER_EVENT_TSC:
bbd9d557 1813 if(event == NULL) return TRUE;
1814 else {
1815 LttCycleCount count = ltt_event_cycle_count(event);
1816 return se->op((gpointer)&count,v);
1817 }
80f9611a 1818 break;
1819 case LTTV_FILTER_EVENT_FIELD:
1820 /*
1821 * TODO: Use the offset to
1822 * find the dynamic field
1823 * in the event struct
1824 */
4d9ff942 1825 return TRUE;
80f9611a 1826 default:
1827 /*
1828 * This case should never be
4d9ff942 1829 * parsed, if so, the whole
1830 * filtering is cancelled
80f9611a 1831 */
1832 g_warning("Error while parsing the filter tree");
1833 return TRUE;
1834 }
4d9ff942 1835
1836 /* should never get here */
1837 return TRUE;
1838
80f9611a 1839}
0769c82f 1840
4d9ff942 1841
1842
80f9611a 1843/**
7e7af7f2 1844 * Debug function. Prints tree memory allocation.
56e29124 1845 * @param t the pointer to the current LttvFilterTree
80f9611a 1846 */
1847void
72911c5d 1848lttv_print_tree(const LttvFilterTree* t, const int count) {
0769c82f 1849
72911c5d 1850 g_print("node:%p lchild:%p rchild:%p depth:%i\n",t, //t->l_child.t,t->r_child.t);
80f9611a 1851 (t->left==LTTV_TREE_NODE)?t->l_child.t:NULL,
72911c5d 1852 (t->right==LTTV_TREE_NODE)?t->r_child.t:NULL,
1853 count);
1854 g_print("logic operator: %s\n",(t->node&1)?"OR":((t->node&2)?"AND":((t->node&4)?"NOT":((t->node&8)?"XOR":"IDLE"))));
1855 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"));
1856 if(t->left == LTTV_TREE_LEAF) {
1857 g_print("| |-> field type number: %i\n",t->l_child.leaf->field);
1858 g_print("| |-> offset is: %i\n",t->l_child.leaf->offset);
1859 g_print("| |-> operator function is: %p\n",t->l_child.leaf->op);
0769c82f 1860 }
72911c5d 1861 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"));
1862 if(t->right == LTTV_TREE_LEAF) {
1863 g_print("| |-> field type number: %i\n",t->r_child.leaf->field);
1864 g_print("| |-> offset is: %i\n",t->r_child.leaf->offset);
1865 g_print("| |-> operator function is: %p\n",t->r_child.leaf->op);
80f9611a 1866 }
72911c5d 1867
1868 if(t->left == LTTV_TREE_NODE) lttv_print_tree(t->l_child.t,count+1);
1869 if(t->right == LTTV_TREE_NODE) lttv_print_tree(t->r_child.t,count+1);
80f9611a 1870}
1871
91ad3f0a 1872/**
56e29124 1873 * @fn static void module_init()
1874 *
91ad3f0a 1875 * Initializes the filter module and specific values
1876 */
1a7fa682 1877static void module_init()
1878{
91ad3f0a 1879
1a7fa682 1880}
1881
91ad3f0a 1882/**
7e7af7f2 1883 * Destroys the filter module and specific values
91ad3f0a 1884 */
1a7fa682 1885static void module_destroy()
1886{
56e29124 1887
1a7fa682 1888}
1889
1890
91ad3f0a 1891LTTV_MODULE("filter", "Filters traceset and events", \
1892 "Filters traceset and events specifically to user input", \
1a7fa682 1893 module_init, module_destroy)
1894
1895
1896
This page took 0.123936 seconds and 4 git commands to generate.