1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2005 Michel Dagenais
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 simple expr [ op expr ]
26 read_simple_expression
27 read_field_path [ rel value ]
30 read_field_component [. field path]
39 path(component...) -> field
41 consist in AND, OR and NOT nested expressions, forming a tree with
42 simple relations as leaves. The simple relations test is a field
43 in an event is equal, not equal, smaller, smaller or equal, larger, or
44 larger or equal to a specified value.
54 * - refine switch of expression in multiple uses functions
55 * - remove the idle expressions in the tree ****
56 * - add the current simple expression to the tree
57 * * clear the field_path array after use
60 #include <lttv/filter.h>
66 LTTV_FILTER_TRACEFILE,
79 LTTV_FILTER_EX_SUBMODE,
85 * @fn void lttv_filter_tree_add_node(GPtrArray*,LttvFilterTree*,LttvLogicalOp)
87 * add a node to the current tree
88 * FIXME: Might be used to lower coding in lttv_filter_new switch expression
89 * @param stack the tree stack
90 * @param subtree the subtree if available (pointer or NULL)
91 * @param op the logical operator that will form the node
94 lttv_filter_tree_add_node(GPtrArray
* stack
, LttvFilterTree
* subtree
, LttvLogicalOp op
) {
96 LttvFilterTree
* t1
= NULL
;
97 LttvFilterTree
* t2
= NULL
;
99 t1
= (LttvFilterTree
*)g_ptr_array_index(stack
,stack
->len
-1);
100 while(t1
->right
!= LTTV_TREE_IDLE
) t1
= (LttvFilterTree
*)t1
->r_child
.t
;
101 t2
= lttv_filter_tree_new();
103 if(subtree
!= NULL
) {
104 t2
->left
= LTTV_TREE_NODE
;
105 t2
->l_child
.t
= subtree
;
107 t1
->right
= LTTV_TREE_NODE
;
110 // a_simple_expression->value = a_field_component->str;
111 // a_field_component = g_string_new("");
112 t2
->left
= LTTV_TREE_LEAF
;
113 // t2->l_child.leaf = a_simple_expression;
114 // a_simple_expression = g_new(lttv_simple_expression,1);
115 t1
->right
= LTTV_TREE_NODE
;
123 * @fn LttvSimpleExpression* lttv_simple_expression_new()
125 * Constructor for LttvSimpleExpression
126 * @return pointer to new LttvSimpleExpression
128 LttvSimpleExpression
*
129 lttv_simple_expression_new() {
131 LttvSimpleExpression
* se
= g_new(LttvSimpleExpression
,1);
133 se
->field
= LTTV_FILTER_UNDEFINED
;
136 // se->value.v_uint64 = 0;
142 * @fn gboolean lttv_simple_expression_add_field(GPtrArray*,LttvSimpleExpression*)
144 * Parse through filtering field hierarchy as specified
145 * by user. This function compares each value to
146 * predetermined quarks
147 * @param fp The field path list
148 * @param se current simple expression
149 * @return success/failure of operation
152 lttv_simple_expression_assign_field(GPtrArray
* fp
, LttvSimpleExpression
* se
) {
156 if(fp
->len
< 2) return FALSE
;
157 g_assert(f
=g_ptr_array_remove_index(fp
,0));
160 * Parse through the specified
163 * Take note however that the
164 * 'event' subfields might change
165 * depending on values specified
166 * in core.xml file. Hence, if
167 * none of the subfields in the
168 * array match the hardcoded
169 * subfields, it will be considered
172 if(!g_strcasecmp(f
->str
,"trace") ) {
177 g_string_free(f
,TRUE
);
178 f
=g_ptr_array_remove_index(fp
,0);
179 if(!g_strcasecmp(f
->str
,"name")) {
180 se
->field
= LTTV_FILTER_TRACE_NAME
;
182 } else if(!g_strcasecmp(f
->str
,"traceset") ) {
184 * FIXME: not yet implemented !
186 } else if(!g_strcasecmp(f
->str
,"tracefile") ) {
191 g_string_free(f
,TRUE
);
192 f
=g_ptr_array_remove_index(fp
,0);
193 if(!g_strcasecmp(f
->str
,"name")) {
194 se
->field
= LTTV_FILTER_TRACEFILE_NAME
;
196 } else if(!g_strcasecmp(f
->str
,"state") ) {
201 * state.creation_time
202 * state.insertion_time
204 * state.execution_mode
205 * state.execution_submode
206 * state.process_status
209 g_string_free(f
,TRUE
);
210 f
=g_ptr_array_remove_index(fp
,0);
211 if(!g_strcasecmp(f
->str
,"pid") ) {
212 se
->field
= LTTV_FILTER_STATE_PID
;
214 else if(!g_strcasecmp(f
->str
,"ppid") ) {
215 se
->field
= LTTV_FILTER_STATE_PPID
;
217 else if(!g_strcasecmp(f
->str
,"creation_time") ) {
218 se
->field
= LTTV_FILTER_STATE_CT
;
220 else if(!g_strcasecmp(f
->str
,"insertion_time") ) {
221 se
->field
= LTTV_FILTER_STATE_IT
;
223 else if(!g_strcasecmp(f
->str
,"process_name") ) {
224 se
->field
= LTTV_FILTER_STATE_P_NAME
;
226 else if(!g_strcasecmp(f
->str
,"execution_mode") ) {
227 se
->field
= LTTV_FILTER_STATE_EX_MODE
;
229 else if(!g_strcasecmp(f
->str
,"execution_submode") ) {
230 se
->field
= LTTV_FILTER_STATE_EX_SUBMODE
;
232 else if(!g_strcasecmp(f
->str
,"process_status") ) {
233 se
->field
= LTTV_FILTER_STATE_P_STATUS
;
235 else if(!g_strcasecmp(f
->str
,"cpu") ) {
236 se
->field
= LTTV_FILTER_STATE_CPU
;
238 } else if(!g_strcasecmp(f
->str
,"event") ) {
246 g_string_free(f
,TRUE
);
247 f
=g_ptr_array_remove_index(fp
,0);
248 if(!g_strcasecmp(f
->str
,"name") ) {
249 se
->field
= LTTV_FILTER_EVENT_NAME
;
251 else if(!g_strcasecmp(f
->str
,"category") ) {
253 * FIXME: Category not yet functional in lttv
255 se
->field
= LTTV_FILTER_EVENT_CATEGORY
;
257 else if(!g_strcasecmp(f
->str
,"time") ) {
258 se
->field
= LTTV_FILTER_EVENT_TIME
;
260 else if(!g_strcasecmp(f
->str
,"tsc") ) {
261 se
->field
= LTTV_FILTER_EVENT_TSC
;
263 else { /* core.xml specified options */
264 se
->field
= LTTV_FILTER_EVENT_FIELD
;
267 g_warning("Unrecognized field in filter string");
270 /* free memory for last string */
271 g_string_free(f
,TRUE
);
273 /* array should be empty */
274 g_assert(fp
->len
== 0);
276 g_print("field: %i\n",se
->field
);
277 if(se
->field
== LTTV_FILTER_UNDEFINED
) {
278 g_warning("The specified field was not recognized !");
285 * @fn gboolean lttv_simple_expression_assign_operator(LttvSimpleExpression*,LttvExpressionOp)
287 * Sets the function pointer for the current
289 * @param se current simple expression
290 * @return success/failure of operation
292 gboolean
lttv_simple_expression_assign_operator(LttvSimpleExpression
* se
, LttvExpressionOp op
) {
294 // g_print("se->field = %i\n",se->field);
295 // g_print("se->offset = %i\n",se->offset);
296 // g_print("se->op = %p\n",se->op);
297 // g_print("se->value = %s\n",se->value);
303 case LTTV_FILTER_TRACE_NAME
:
304 case LTTV_FILTER_TRACEFILE_NAME
:
305 case LTTV_FILTER_STATE_P_NAME
:
306 case LTTV_FILTER_EVENT_NAME
:
309 se
->op
= lttv_apply_op_eq_string
;
312 se
->op
= lttv_apply_op_ne_string
;
315 g_warning("Error encountered in operator assignment = or != expected");
322 case LTTV_FILTER_STATE_PID
:
323 case LTTV_FILTER_STATE_PPID
:
324 case LTTV_FILTER_STATE_EX_MODE
:
325 case LTTV_FILTER_STATE_EX_SUBMODE
:
326 case LTTV_FILTER_STATE_P_STATUS
:
329 se
->op
= lttv_apply_op_eq_uint64
;
332 se
->op
= lttv_apply_op_ne_uint64
;
335 se
->op
= lttv_apply_op_lt_uint64
;
338 se
->op
= lttv_apply_op_le_uint64
;
341 se
->op
= lttv_apply_op_gt_uint64
;
344 se
->op
= lttv_apply_op_ge_uint64
;
347 g_warning("Error encountered in operator assignment");
354 case LTTV_FILTER_STATE_CT
:
355 case LTTV_FILTER_STATE_IT
:
356 case LTTV_FILTER_EVENT_TIME
:
357 case LTTV_FILTER_EVENT_TSC
:
360 se
->op
= lttv_apply_op_eq_ltttime
;
363 se
->op
= lttv_apply_op_ne_ltttime
;
366 se
->op
= lttv_apply_op_lt_ltttime
;
369 se
->op
= lttv_apply_op_le_ltttime
;
372 se
->op
= lttv_apply_op_gt_ltttime
;
375 se
->op
= lttv_apply_op_ge_ltttime
;
378 g_warning("Error encountered in operator assignment");
383 g_warning("Error encountered in operator assignation ! Field type:%i",se
->field
);
392 * @fn void lttv_simple_expression_assign_value(LttvSimpleExpression*,char*)
394 * Assign the value field to the current LttvSimpleExpression
395 * @param se pointer to the current LttvSimpleExpression
396 * @param value string value for simple expression
398 gboolean
lttv_simple_expression_assign_value(LttvSimpleExpression
* se
, char* value
) {
400 // g_print("se->value:%s\n",value);
406 case LTTV_FILTER_TRACE_NAME
:
407 case LTTV_FILTER_TRACEFILE_NAME
:
408 case LTTV_FILTER_STATE_P_NAME
:
409 case LTTV_FILTER_EVENT_NAME
:
410 se
->value
.v_string
= value
;
415 case LTTV_FILTER_STATE_PID
:
416 case LTTV_FILTER_STATE_PPID
:
417 case LTTV_FILTER_STATE_EX_MODE
:
418 case LTTV_FILTER_STATE_EX_SUBMODE
:
419 case LTTV_FILTER_STATE_P_STATUS
:
420 se
->value
.v_uint64
= atoi(value
);
426 case LTTV_FILTER_STATE_CT
:
427 case LTTV_FILTER_STATE_IT
:
428 case LTTV_FILTER_EVENT_TIME
:
429 case LTTV_FILTER_EVENT_TSC
:
430 //se->value.v_double = atof(value);
431 se
->value
.v_ltttime
= ltt_time_from_double(atof(value
));
435 g_warning("Error encountered in value assignation ! Field type = %i",se
->field
);
444 * @fn void lttv_simple_expression_destroy(LttvSimpleExpression*)
446 * Disallocate memory for the current
448 * @param se pointer to the current LttvSimpleExpression
451 lttv_simple_expression_destroy(LttvSimpleExpression
* se
) {
453 // g_free(se->value);
455 case LTTV_FILTER_TRACE_NAME
:
456 case LTTV_FILTER_TRACEFILE_NAME
:
457 case LTTV_FILTER_STATE_P_NAME
:
458 case LTTV_FILTER_EVENT_NAME
:
459 g_free(se
->value
.v_string
);
467 * @fn gint lttv_struct_type(gint)
469 * Finds the structure type depending
470 * on the fields in parameters
471 * @params ft Field of the current structure
472 * @return LttvStructType enum or -1 for error
475 lttv_struct_type(gint ft
) {
478 case LTTV_FILTER_TRACE_NAME
:
479 return LTTV_FILTER_TRACE
;
481 case LTTV_FILTER_TRACEFILE_NAME
:
482 return LTTV_FILTER_TRACEFILE
;
484 case LTTV_FILTER_STATE_PID
:
485 case LTTV_FILTER_STATE_PPID
:
486 case LTTV_FILTER_STATE_CT
:
487 case LTTV_FILTER_STATE_IT
:
488 case LTTV_FILTER_STATE_P_NAME
:
489 case LTTV_FILTER_STATE_EX_MODE
:
490 case LTTV_FILTER_STATE_EX_SUBMODE
:
491 case LTTV_FILTER_STATE_P_STATUS
:
492 case LTTV_FILTER_STATE_CPU
:
493 return LTTV_FILTER_STATE
;
495 case LTTV_FILTER_EVENT_NAME
:
496 case LTTV_FILTER_EVENT_CATEGORY
:
497 case LTTV_FILTER_EVENT_TIME
:
498 case LTTV_FILTER_EVENT_TSC
:
499 case LTTV_FILTER_EVENT_FIELD
:
500 return LTTV_FILTER_EVENT
;
508 * @fn gboolean lttv_apply_op_eq_uint64(gpointer,LttvFieldValue)
510 * Applies the 'equal' operator to the
511 * specified structure and value
512 * @param v1 left member of comparison
513 * @param v2 right member of comparison
514 * @return success/failure of operation
516 gboolean
lttv_apply_op_eq_uint64(gpointer v1
, LttvFieldValue v2
) {
518 guint64
* r
= (guint64
*) v1
;
519 return (*r
== v2
.v_uint64
);
524 * @fn gboolean lttv_apply_op_eq_uint32(gpointer,LttvFieldValue)
526 * Applies the 'equal' operator to the
527 * specified structure and value
528 * @param v1 left member of comparison
529 * @param v2 right member of comparison
530 * @return success/failure of operation
532 gboolean
lttv_apply_op_eq_uint32(gpointer v1
, LttvFieldValue v2
) {
533 guint32
* r
= (guint32
*) v1
;
534 return (*r
== v2
.v_uint32
);
538 * @fn gboolean lttv_apply_op_eq_uint16(gpointer,LttvFieldValue)
540 * Applies the 'equal' operator to the
541 * specified structure and value
542 * @param v1 left member of comparison
543 * @param v2 right member of comparison
544 * @return success/failure of operation
546 gboolean
lttv_apply_op_eq_uint16(gpointer v1
, LttvFieldValue v2
) {
547 guint16
* r
= (guint16
*) v1
;
548 return (*r
== v2
.v_uint16
);
552 * @fn gboolean lttv_apply_op_eq_double(gpointer,LttvFieldValue)
554 * Applies the 'equal' operator to the
555 * specified structure and value
556 * @param v1 left member of comparison
557 * @param v2 right member of comparison
558 * @return success/failure of operation
560 gboolean
lttv_apply_op_eq_double(gpointer v1
, LttvFieldValue v2
) {
561 double* r
= (double*) v1
;
562 return (*r
== v2
.v_double
);
566 * @fn gboolean lttv_apply_op_eq_string(gpointer,LttvFieldValue)
568 * Applies the 'equal' operator to the
569 * specified structure and value
570 * @param v1 left member of comparison
571 * @param v2 right member of comparison
572 * @return success/failure of operation
574 gboolean
lttv_apply_op_eq_string(gpointer v1
, LttvFieldValue v2
) {
575 char* r
= (char*) v1
;
576 g_print("v1:%s = v2:%s\n",r
,v2
.v_string
);
577 return (!g_strcasecmp(r
,v2
.v_string
));
581 * @fn gboolean lttv_apply_op_eq_ltttime(gpointer,LttvFieldValue)
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
589 gboolean
lttv_apply_op_eq_ltttime(gpointer v1
, LttvFieldValue v2
) {
590 LttTime
* r
= (LttTime
*) v1
;
591 return ((r
->tv_sec
== v2
.v_ltttime
.tv_sec
) && (r
->tv_nsec
== v2
.v_ltttime
.tv_nsec
));
596 * @fn gboolean lttv_apply_op_ne_uint64(gpointer,LttvFieldValue)
598 * Applies the 'not 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
604 gboolean
lttv_apply_op_ne_uint64(gpointer v1
, LttvFieldValue v2
) {
605 guint64
* r
= (guint64
*) v1
;
606 return (*r
!= v2
.v_uint64
);
610 * @fn gboolean lttv_apply_op_ne_uint32(gpointer,LttvFieldValue)
612 * Applies the 'not equal' operator to the
613 * specified structure and value
614 * @param v1 left member of comparison
615 * @param v2 right member of comparison
616 * @return success/failure of operation
618 gboolean
lttv_apply_op_ne_uint32(gpointer v1
, LttvFieldValue v2
) {
619 guint32
* r
= (guint32
*) v1
;
620 return (*r
!= v2
.v_uint32
);
624 * @fn gboolean lttv_apply_op_ne_uint16(gpointer,LttvFieldValue)
626 * Applies the 'not equal' operator to the
627 * specified structure and value
628 * @param v1 left member of comparison
629 * @param v2 right member of comparison
630 * @return success/failure of operation
632 gboolean
lttv_apply_op_ne_uint16(gpointer v1
, LttvFieldValue v2
) {
633 guint16
* r
= (guint16
*) v1
;
634 return (*r
!= v2
.v_uint16
);
638 * @fn gboolean lttv_apply_op_ne_double(gpointer,LttvFieldValue)
640 * Applies the 'not equal' operator to the
641 * specified structure and value
642 * @param v1 left member of comparison
643 * @param v2 right member of comparison
644 * @return success/failure of operation
646 gboolean
lttv_apply_op_ne_double(gpointer v1
, LttvFieldValue v2
) {
647 double* r
= (double*) v1
;
648 return (*r
!= v2
.v_double
);
652 * @fn gboolean lttv_apply_op_ne_string(gpointer,LttvFieldValue)
654 * Applies the 'not equal' operator to the
655 * specified structure and value
656 * @param v1 left member of comparison
657 * @param v2 right member of comparison
658 * @return success/failure of operation
660 gboolean
lttv_apply_op_ne_string(gpointer v1
, LttvFieldValue v2
) {
661 char* r
= (char*) v1
;
662 return (g_strcasecmp(r
,v2
.v_string
));
666 * @fn gboolean lttv_apply_op_ne_ltttime(gpointer,LttvFieldValue)
668 * Applies the 'not equal' operator to the
669 * specified structure and value
670 * @param v1 left member of comparison
671 * @param v2 right member of comparison
672 * @return success/failure of operation
674 gboolean
lttv_apply_op_ne_ltttime(gpointer v1
, LttvFieldValue v2
) {
675 LttTime
* r
= (LttTime
*) v1
;
676 return ((r
->tv_sec
!= v2
.v_ltttime
.tv_sec
) || (r
->tv_nsec
!= v2
.v_ltttime
.tv_nsec
));
681 * @fn gboolean lttv_apply_op_lt_uint64(gpointer,LttvFieldValue)
683 * Applies the 'lower than' 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
689 gboolean
lttv_apply_op_lt_uint64(gpointer v1
, LttvFieldValue v2
) {
690 guint64
* r
= (guint64
*) v1
;
691 return (*r
< v2
.v_uint64
);
695 * @fn gboolean lttv_apply_op_lt_uint32(gpointer,LttvFieldValue)
697 * Applies the 'lower than' operator to the
698 * specified structure and value
699 * @param v1 left member of comparison
700 * @param v2 right member of comparison
701 * @return success/failure of operation
703 gboolean
lttv_apply_op_lt_uint32(gpointer v1
, LttvFieldValue v2
) {
704 guint32
* r
= (guint32
*) v1
;
705 return (*r
< v2
.v_uint32
);
709 * @fn gboolean lttv_apply_op_lt_uint16(gpointer,LttvFieldValue)
711 * Applies the 'lower than' operator to the
712 * specified structure and value
713 * @param v1 left member of comparison
714 * @param v2 right member of comparison
715 * @return success/failure of operation
717 gboolean
lttv_apply_op_lt_uint16(gpointer v1
, LttvFieldValue v2
) {
718 guint16
* r
= (guint16
*) v1
;
719 return (*r
< v2
.v_uint16
);
723 * @fn gboolean lttv_apply_op_lt_double(gpointer,LttvFieldValue)
725 * Applies the 'lower than' operator to the
726 * specified structure and value
727 * @param v1 left member of comparison
728 * @param v2 right member of comparison
729 * @return success/failure of operation
731 gboolean
lttv_apply_op_lt_double(gpointer v1
, LttvFieldValue v2
) {
732 double* r
= (double*) v1
;
733 return (*r
< v2
.v_double
);
737 * @fn gboolean lttv_apply_op_lt_ltttime(gpointer,LttvFieldValue)
739 * Applies the 'lower than' operator to the
740 * specified structure and value
741 * @param v1 left member of comparison
742 * @param v2 right member of comparison
743 * @return success/failure of operation
745 gboolean
lttv_apply_op_lt_ltttime(gpointer v1
, LttvFieldValue v2
) {
746 LttTime
* r
= (LttTime
*) v1
;
747 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
)));
752 * @fn gboolean lttv_apply_op_le_uint64(gpointer,LttvFieldValue)
754 * Applies the 'lower or equal' operator to the
755 * specified structure and value
756 * @param v1 left member of comparison
757 * @param v2 right member of comparison
758 * @return success/failure of operation
760 gboolean
lttv_apply_op_le_uint64(gpointer v1
, LttvFieldValue v2
) {
761 guint64
* r
= (guint64
*) v1
;
762 return (*r
<= v2
.v_uint64
);
766 * @fn gboolean lttv_apply_op_le_uint32(gpointer,LttvFieldValue)
768 * Applies the 'lower or equal' operator to the
769 * specified structure and value
770 * @param v1 left member of comparison
771 * @param v2 right member of comparison
772 * @return success/failure of operation
774 gboolean
lttv_apply_op_le_uint32(gpointer v1
, LttvFieldValue v2
) {
775 guint32
* r
= (guint32
*) v1
;
776 return (*r
<= v2
.v_uint32
);
780 * @fn gboolean lttv_apply_op_le_uint16(gpointer,LttvFieldValue)
782 * Applies the 'lower or equal' operator to the
783 * specified structure and value
784 * @param v1 left member of comparison
785 * @param v2 right member of comparison
786 * @return success/failure of operation
788 gboolean
lttv_apply_op_le_uint16(gpointer v1
, LttvFieldValue v2
) {
789 guint16
* r
= (guint16
*) v1
;
790 return (*r
<= v2
.v_uint16
);
794 * @fn gboolean lttv_apply_op_le_double(gpointer,LttvFieldValue)
796 * Applies the 'lower or equal' operator to the
797 * specified structure and value
798 * @param v1 left member of comparison
799 * @param v2 right member of comparison
800 * @return success/failure of operation
802 gboolean
lttv_apply_op_le_double(gpointer v1
, LttvFieldValue v2
) {
803 double* r
= (double*) v1
;
804 return (*r
<= v2
.v_double
);
808 * @fn gboolean lttv_apply_op_le_ltttime(gpointer,LttvFieldValue)
810 * Applies the 'lower or equal' operator to the
811 * specified structure and value
812 * @param v1 left member of comparison
813 * @param v2 right member of comparison
814 * @return success/failure of operation
816 gboolean
lttv_apply_op_le_ltttime(gpointer v1
, LttvFieldValue v2
) {
817 LttTime
* r
= (LttTime
*) v1
;
818 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
)));
823 * @fn gboolean lttv_apply_op_gt_uint64(gpointer,LttvFieldValue)
825 * Applies the 'greater than' operator to the
826 * specified structure and value
827 * @param v1 left member of comparison
828 * @param v2 right member of comparison
829 * @return success/failure of operation
831 gboolean
lttv_apply_op_gt_uint64(gpointer v1
, LttvFieldValue v2
) {
832 guint64
* r
= (guint64
*) v1
;
833 return (*r
> v2
.v_uint64
);
837 * @fn gboolean lttv_apply_op_gt_uint32(gpointer,LttvFieldValue)
839 * Applies the 'greater than' operator to the
840 * specified structure and value
841 * @param v1 left member of comparison
842 * @param v2 right member of comparison
843 * @return success/failure of operation
845 gboolean
lttv_apply_op_gt_uint32(gpointer v1
, LttvFieldValue v2
) {
846 guint32
* r
= (guint32
*) v1
;
847 return (*r
> v2
.v_uint32
);
851 * @fn gboolean lttv_apply_op_gt_uint16(gpointer,LttvFieldValue)
853 * Applies the 'greater than' operator to the
854 * specified structure and value
855 * @param v1 left member of comparison
856 * @param v2 right member of comparison
857 * @return success/failure of operation
859 gboolean
lttv_apply_op_gt_uint16(gpointer v1
, LttvFieldValue v2
) {
860 guint16
* r
= (guint16
*) v1
;
861 return (*r
> v2
.v_uint16
);
865 * @fn gboolean lttv_apply_op_gt_double(gpointer,LttvFieldValue)
867 * Applies the 'greater than' operator to the
868 * specified structure and value
869 * @param v1 left member of comparison
870 * @param v2 right member of comparison
871 * @return success/failure of operation
873 gboolean
lttv_apply_op_gt_double(gpointer v1
, LttvFieldValue v2
) {
874 double* r
= (double*) v1
;
875 return (*r
> v2
.v_double
);
879 * @fn gboolean lttv_apply_op_gt_ltttime(gpointer,LttvFieldValue)
881 * Applies the 'greater than' operator to the
882 * specified structure and value
883 * @param v1 left member of comparison
884 * @param v2 right member of comparison
885 * @return success/failure of operation
887 gboolean
lttv_apply_op_gt_ltttime(gpointer v1
, LttvFieldValue v2
) {
888 LttTime
* r
= (LttTime
*) v1
;
889 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
)));
894 * @fn gboolean lttv_apply_op_ge_uint64(gpointer,LttvFieldValue)
896 * Applies the 'greater or equal' operator to the
897 * specified structure and value
898 * @param v1 left member of comparison
899 * @param v2 right member of comparison
900 * @return success/failure of operation
902 gboolean
lttv_apply_op_ge_uint64(gpointer v1
, LttvFieldValue v2
) {
903 guint64
* r
= (guint64
*) v1
;
904 return (*r
>= v2
.v_uint64
);
908 * @fn gboolean lttv_apply_op_ge_uint32(gpointer,LttvFieldValue)
910 * Applies the 'greater or equal' operator to the
911 * specified structure and value
912 * @param v1 left member of comparison
913 * @param v2 right member of comparison
914 * @return success/failure of operation
916 gboolean
lttv_apply_op_ge_uint32(gpointer v1
, LttvFieldValue v2
) {
917 guint32
* r
= (guint32
*) v1
;
918 return (*r
>= v2
.v_uint32
);
922 * @fn gboolean lttv_apply_op_ge_uint16(gpointer,LttvFieldValue)
924 * Applies the 'greater or equal' operator to the
925 * specified structure and value
926 * @param v1 left member of comparison
927 * @param v2 right member of comparison
928 * @return success/failure of operation
930 gboolean
lttv_apply_op_ge_uint16(gpointer v1
, LttvFieldValue v2
) {
931 guint16
* r
= (guint16
*) v1
;
932 return (*r
>= v2
.v_uint16
);
936 * @fn gboolean lttv_apply_op_ge_double(gpointer,LttvFieldValue)
938 * Applies the 'greater or equal' operator to the
939 * specified structure and value
940 * @param v1 left member of comparison
941 * @param v2 right member of comparison
942 * @return success/failure of operation
944 gboolean
lttv_apply_op_ge_double(gpointer v1
, LttvFieldValue v2
) {
945 double* r
= (double*) v1
;
946 return (*r
>= v2
.v_double
);
950 * @fn gboolean lttv_apply_op_ge_ltttime(gpointer,LttvFieldValue)
952 * Applies the 'greater or equal' operator to the
953 * specified structure and value
954 * @param v1 left member of comparison
955 * @param v2 right member of comparison
956 * @return success/failure of operation
958 gboolean
lttv_apply_op_ge_ltttime(gpointer v1
, LttvFieldValue v2
) {
959 LttTime
* r
= (LttTime
*) v1
;
960 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
)));
966 * @fn LttvFilterTree* lttv_filter_tree_clone(LttvFilterTree*)
968 * Makes a copy of the current filter tree
969 * @param tree pointer to the current tree
970 * @return new copy of the filter tree
973 lttv_filter_tree_clone(LttvFilterTree
* tree
) {
975 LttvFilterTree
* newtree
= lttv_filter_tree_new();
977 newtree
->node
= tree
->node
;
979 newtree
->left
= tree
->left
;
980 if(newtree
->left
== LTTV_TREE_NODE
) {
981 newtree
->l_child
.t
= lttv_filter_tree_clone(tree
->l_child
.t
);
982 } else if(newtree
->left
== LTTV_TREE_LEAF
) {
983 newtree
->l_child
.leaf
= lttv_simple_expression_new();
984 newtree
->l_child
.leaf
->field
= tree
->l_child
.leaf
->field
;
985 newtree
->l_child
.leaf
->offset
= tree
->l_child
.leaf
->offset
;
986 newtree
->l_child
.leaf
->op
= tree
->l_child
.leaf
->op
;
987 /* FIXME: special case for string copy ! */
988 newtree
->l_child
.leaf
->value
= tree
->l_child
.leaf
->value
;
991 newtree
->right
= tree
->right
;
992 if(newtree
->right
== LTTV_TREE_NODE
) {
993 newtree
->r_child
.t
= lttv_filter_tree_clone(tree
->r_child
.t
);
994 } else if(newtree
->right
== LTTV_TREE_LEAF
) {
995 newtree
->r_child
.leaf
= lttv_simple_expression_new();
996 newtree
->r_child
.leaf
->field
= tree
->r_child
.leaf
->field
;
997 newtree
->r_child
.leaf
->offset
= tree
->r_child
.leaf
->offset
;
998 newtree
->r_child
.leaf
->op
= tree
->r_child
.leaf
->op
;
999 newtree
->r_child
.leaf
->value
= tree
->r_child
.leaf
->value
;
1007 * @fn LttvFilter* lttv_filter_clone(LttvFilter*)
1009 * Makes a copy of the current filter
1010 * @param filter pointer to the current filter
1011 * @return new copy of the filter
1014 lttv_filter_clone(LttvFilter
* filter
) {
1017 LttvFilter
* newfilter
= g_new(LttvFilter
,1);
1019 // newfilter->expression = g_new(char,1)
1020 strcpy(newfilter
->expression
,filter
->expression
);
1022 newfilter
->head
= lttv_filter_tree_clone(filter
->head
);
1030 * @fn LttvFilter* lttv_filter_new()
1032 * Creates a new lttv_filter
1033 * @param expression filtering options string
1034 * @param t pointer to the current LttvTrace
1035 * @return the current lttv_filter or NULL if error
1040 LttvFilter
* filter
= g_new(LttvFilter
,1);
1041 filter
->expression
= NULL
;
1042 filter
->head
= NULL
;
1047 * @fn gboolean lttv_filter_update(LttvFilter*)
1049 * Updates the current LttvFilter by building
1050 * its tree based upon the expression string
1051 * @param filter pointer to the current LttvFilter
1052 * @return Failure/Success of operation
1055 lttv_filter_update(LttvFilter
* filter
) {
1057 g_print("filter::lttv_filter_new()\n"); /* debug */
1059 if(filter
->expression
== NULL
) return FALSE
;
1063 p_nesting
=0; /* parenthesis nesting value */
1067 *tree
= lttv_filter_tree_new(), /* main tree */
1068 *subtree
= NULL
, /* buffer for subtrees */
1069 *t1
, /* buffer #1 */
1070 *t2
; /* buffer #2 */
1074 * If the tree already exists,
1075 * destroy it and build a new one
1077 if(filter
->head
!= NULL
) lttv_filter_tree_destroy(filter
->head
);
1078 filter
->head
= NULL
; /* will be assigned at the end */
1082 * each element of the list
1083 * is a sub tree created
1084 * by the use of parenthesis in the
1085 * global expression. The final tree
1086 * will be the one left at the root of
1089 GPtrArray
*tree_stack
= g_ptr_array_new();
1090 g_ptr_array_add( tree_stack
,(gpointer
) tree
);
1092 /* temporary values */
1093 GString
*a_field_component
= g_string_new("");
1094 GPtrArray
*a_field_path
= g_ptr_array_new();
1096 /* simple expression buffer */
1097 LttvSimpleExpression
* a_simple_expression
= lttv_simple_expression_new();
1100 * Parse entire expression and construct
1101 * the binary tree. There are two steps
1102 * in browsing that string
1103 * 1. finding boolean ops " &,|,^,! " and parenthesis " {,(,[,],),} "
1104 * 2. finding simple expressions
1105 * - field path ( separated by dots )
1106 * - op ( >, <, =, >=, <=, !=)
1107 * - value ( integer, string ... )
1108 * To spare computing time, the whole
1109 * string is parsed in this loop for a
1110 * O(n) complexity order.
1112 * When encountering logical op &,|,^
1113 * 1. parse the last value if any
1114 * 2. create a new tree
1115 * 3. add the expression (simple exp, or exp (subtree)) to the tree
1116 * 4. concatenate this tree with the current tree on top of the stack
1117 * When encountering math ops >,>=,<,<=,=,!=
1118 * 1. add to op to the simple expression
1119 * 2. concatenate last field component to field path
1120 * When encountering concatening ops .
1121 * 1. concatenate last field component to field path
1122 * When encountering opening parenthesis (,{,[
1123 * 1. create a new subtree on top of tree stack
1124 * When encountering closing parenthesis ),},]
1125 * 1. add the expression on right child of the current tree
1126 * 2. the subtree is completed, allocate a new subtree
1127 * 3. pop the tree value from the tree stack
1130 // g_print("expression: %s\n",filter->expression);
1131 // g_print("strlen(expression): %i\n",strlen(filter->expression));
1132 for(i
=0;i
<strlen(filter
->expression
);i
++) {
1134 g_print("%c ",filter
->expression
[i
]);
1135 switch(filter
->expression
[i
]) {
1141 t1
= (LttvFilterTree
*)g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1142 while(t1
->right
!= LTTV_TREE_IDLE
) {
1143 g_assert(t1
->right
== LTTV_TREE_NODE
);
1146 t2
= lttv_filter_tree_new();
1147 t2
->node
= LTTV_LOGICAL_AND
;
1148 if(subtree
!= NULL
) { /* append subtree to current tree */
1149 t2
->left
= LTTV_TREE_NODE
;
1150 t2
->l_child
.t
= subtree
;
1152 t1
->right
= LTTV_TREE_NODE
;
1154 } else { /* append a simple expression */
1155 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1156 // a_simple_expression->value = g_string_free(a_field_component,FALSE);
1157 a_field_component
= g_string_new("");
1158 t2
->left
= LTTV_TREE_LEAF
;
1159 t2
->l_child
.leaf
= a_simple_expression
;
1160 a_simple_expression
= lttv_simple_expression_new();
1161 t1
->right
= LTTV_TREE_NODE
;
1163 g_print("t1:%p t1->child:%p\n",t1
,t1
->r_child
.t
);
1169 t1
= (LttvFilterTree
*)g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1170 while(t1
->right
!= LTTV_TREE_IDLE
) {
1171 g_assert(t1
->right
== LTTV_TREE_NODE
);
1174 t2
= lttv_filter_tree_new();
1175 t2
->node
= LTTV_LOGICAL_OR
;
1176 if(subtree
!= NULL
) { /* append subtree to current tree */
1177 t2
->left
= LTTV_TREE_NODE
;
1178 t2
->l_child
.t
= subtree
;
1180 t1
->right
= LTTV_TREE_NODE
;
1182 } else { /* append a simple expression */
1183 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1184 //a_simple_expression->value = g_string_free(a_field_component,FALSE);
1185 a_field_component
= g_string_new("");
1186 t2
->left
= LTTV_TREE_LEAF
;
1187 t2
->l_child
.leaf
= a_simple_expression
;
1188 a_simple_expression
= lttv_simple_expression_new();
1189 t1
->right
= LTTV_TREE_NODE
;
1196 t1
= (LttvFilterTree
*)g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1197 while(t1
->right
!= LTTV_TREE_IDLE
) {
1198 g_assert(t1
->right
== LTTV_TREE_NODE
);
1201 t2
= lttv_filter_tree_new();
1202 t2
->node
= LTTV_LOGICAL_XOR
;
1203 if(subtree
!= NULL
) { /* append subtree to current tree */
1204 t2
->left
= LTTV_TREE_NODE
;
1205 t2
->l_child
.t
= subtree
;
1207 t1
->right
= LTTV_TREE_NODE
;
1209 } else { /* append a simple expression */
1210 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1211 //a_simple_expression->value = g_string_free(a_field_component,FALSE);
1212 a_field_component
= g_string_new("");
1213 t2
->left
= LTTV_TREE_LEAF
;
1214 t2
->l_child
.leaf
= a_simple_expression
;
1215 a_simple_expression
= lttv_simple_expression_new();
1216 t1
->right
= LTTV_TREE_NODE
;
1221 case '!': /* not, or not equal (math op) */
1223 if(filter
->expression
[i
+1] == '=') { /* != */
1224 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1225 lttv_simple_expression_assign_field(a_field_path
,a_simple_expression
);
1226 a_field_component
= g_string_new("");
1227 lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_NE
);
1230 t1
= (LttvFilterTree
*)g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1231 while(t1
->right
!= LTTV_TREE_IDLE
) {
1232 g_assert(t1
->right
== LTTV_TREE_NODE
);
1235 t2
= lttv_filter_tree_new();
1236 t2
->node
= LTTV_LOGICAL_NOT
;
1237 t1
->right
= LTTV_TREE_NODE
;
1242 case '(': /* start of parenthesis */
1246 p_nesting
++; /* incrementing parenthesis nesting value */
1247 t1
= lttv_filter_tree_new();
1248 g_ptr_array_add( tree_stack
,(gpointer
) t1
);
1251 case ')': /* end of parenthesis */
1255 p_nesting
--; /* decrementing parenthesis nesting value */
1256 if(p_nesting
<0 || tree_stack
->len
<2) {
1257 g_warning("Wrong filtering options, the string\n\"%s\"\n\
1258 is not valid due to parenthesis incorrect use",filter
->expression
);
1262 /* there must at least be the root tree left in the array */
1263 g_assert(tree_stack
->len
>0);
1265 if(subtree
!= NULL
) { /* append subtree to current tree */
1266 t1
= g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1267 while(t1
->right
!= LTTV_TREE_IDLE
) {
1268 g_assert(t1
->right
== LTTV_TREE_NODE
);
1271 t1
->right
= LTTV_TREE_NODE
;
1272 t1
->r_child
.t
= subtree
;
1273 subtree
= g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1274 g_ptr_array_remove_index(tree_stack
,tree_stack
->len
-1);
1275 } else { /* assign subtree as current tree */
1276 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1277 //a_simple_expression->value = g_string_free(a_field_component,FALSE);
1278 a_field_component
= g_string_new("");
1279 t1
= g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1280 while(t1
->right
!= LTTV_TREE_IDLE
) {
1281 g_print("while right:%i %p->child:%p\n",t1
->right
,t1
,t1
->r_child
.t
);
1282 g_assert(t1
->right
== LTTV_TREE_NODE
);
1283 g_assert(t1
->r_child
.t
!= NULL
);
1286 t1
->right
= LTTV_TREE_LEAF
;
1287 t1
->r_child
.leaf
= a_simple_expression
;
1288 a_simple_expression
= lttv_simple_expression_new();
1289 subtree
= g_ptr_array_remove_index(tree_stack
,tree_stack
->len
-1);
1294 * mathematic operators
1296 case '<': /* lower, lower or equal */
1298 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1299 lttv_simple_expression_assign_field(a_field_path
,a_simple_expression
);
1300 a_field_component
= g_string_new("");
1301 if(filter
->expression
[i
+1] == '=') { /* <= */
1303 lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_LE
);
1304 } else lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_LT
);
1307 case '>': /* higher, higher or equal */
1309 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1310 lttv_simple_expression_assign_field(a_field_path
,a_simple_expression
);
1311 a_field_component
= g_string_new("");
1312 if(filter
->expression
[i
+1] == '=') { /* >= */
1314 lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_GE
);
1315 } else lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_GT
);
1318 case '=': /* equal */
1320 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1321 lttv_simple_expression_assign_field(a_field_path
,a_simple_expression
);
1322 a_field_component
= g_string_new("");
1323 lttv_simple_expression_assign_operator(a_simple_expression
,LTTV_FIELD_EQ
);
1327 * Field concatening caracter
1332 * divide field expression into elements
1333 * in a_field_path array.
1335 /* FIXME: check for double values */
1336 if(a_simple_expression
->field
== LTTV_FILTER_UNDEFINED
) {
1337 g_ptr_array_add( a_field_path
,(gpointer
) a_field_component
);
1338 a_field_component
= g_string_new("");
1344 default: /* concatening current string */
1345 g_string_append_c(a_field_component
,filter
->expression
[i
]);
1349 // g_print("subtree:%p, tree:%p, t1:%p, t2:%p\n",subtree,tree,t1,t2);
1350 // g_print("stack size: %i\n",tree_stack->len);
1353 * Preliminary check to see
1354 * if tree was constructed correctly
1357 g_warning("Wrong filtering options, the string\n\"%s\"\n\
1358 is not valid due to parenthesis incorrect use",filter
->expression
);
1362 if(tree_stack
->len
!= 1) /* only root tree should remain */
1365 /* processing last element of expression */
1366 t1
= g_ptr_array_index(tree_stack
,tree_stack
->len
-1);
1367 while(t1
->right
!= LTTV_TREE_IDLE
) {
1368 g_assert(t1
->right
== LTTV_TREE_NODE
);
1371 if(subtree
!= NULL
) { /* add the subtree */
1372 t1
->right
= LTTV_TREE_NODE
;
1373 t1
->r_child
.t
= subtree
;
1375 } else { /* add a leaf */
1376 lttv_simple_expression_assign_value(a_simple_expression
,g_string_free(a_field_component
,FALSE
));
1377 //a_simple_expression->value = g_string_free(a_field_component,FALSE);
1378 a_field_component
= NULL
;
1379 t1
->right
= LTTV_TREE_LEAF
;
1380 t1
->r_child
.leaf
= a_simple_expression
;
1381 a_simple_expression
= NULL
;
1385 /* free the pointer array */
1386 g_assert(a_field_path
->len
== 0);
1387 g_ptr_array_free(a_field_path
,TRUE
);
1389 /* free the tree stack -- but keep the root tree */
1390 // g_ptr_array_free(tree_stack,FALSE);
1391 filter
->head
= g_ptr_array_remove_index(tree_stack
,0);
1392 g_ptr_array_free(tree_stack
,TRUE
);
1394 /* free the field buffer if allocated */
1395 if(a_field_component
!= NULL
) g_string_free(a_field_component
,TRUE
);
1397 /* free the simple expression buffer if allocated */
1398 if(a_simple_expression
!= NULL
) lttv_simple_expression_destroy(a_simple_expression
);
1400 g_assert(filter
->head
!= NULL
); /* tree should exist */
1401 g_assert(subtree
== NULL
); /* remaining subtree should be included in main tree */
1404 g_print("+++++++++++++++ BEGIN PRINT ++++++++++++++++\n");
1405 lttv_print_tree(filter
->head
) ;
1406 g_print("+++++++++++++++ END PRINT ++++++++++++++++++\n");
1414 * @fn void lttv_filter_destroy(LttvFilter*)
1416 * Destroy the current LttvFilter
1417 * @param filter pointer to the current LttvFilter
1420 lttv_filter_destroy(LttvFilter
* filter
) {
1422 g_free(filter
->expression
);
1423 lttv_filter_tree_destroy(filter
->head
);
1429 * @fn LttvFilterTree* lttv_filter_tree_new()
1431 * Assign a new tree for the current expression
1433 * @return pointer of LttvFilterTree
1436 lttv_filter_tree_new() {
1437 LttvFilterTree
* tree
;
1439 tree
= g_new(LttvFilterTree
,1);
1440 tree
->node
= 0; //g_new(lttv_expression,1);
1441 tree
->left
= LTTV_TREE_IDLE
;
1442 tree
->right
= LTTV_TREE_IDLE
;
1443 tree
->r_child
.t
= NULL
;
1444 tree
->l_child
.t
= NULL
;
1450 * @fn void lttv_filter_append_expression(LttvFilter*,char*)
1452 * Append a new expression to the expression
1453 * defined in the current filter
1454 * @param filter pointer to the current LttvFilter
1455 * @param expression string that must be appended
1456 * @return Success/Failure of operation
1458 gboolean
lttv_filter_append_expression(LttvFilter
* filter
, char *expression
) {
1460 if(expression
== NULL
) return FALSE
;
1461 if(filter
== NULL
) {
1462 filter
= lttv_filter_new();
1463 filter
->expression
= expression
;
1464 } else if(filter
->expression
== NULL
) {
1465 filter
->expression
= expression
;
1467 filter
->expression
= g_strconcat(filter
->expression
,"&",expression
);
1470 return lttv_filter_update(filter
);
1475 * @fn void lttv_filter_clear_expression(LttvFilter*)
1477 * Clear the filter expression from the
1478 * current filter and sets its pointer to NULL
1479 * @param filter pointer to the current LttvFilter
1481 void lttv_filter_clear_expression(LttvFilter
* filter
) {
1483 if(filter
->expression
!= NULL
) {
1484 g_free(filter
->expression
);
1485 filter
->expression
= NULL
;
1491 * @fn void lttv_filter_tree_destroy(LttvFilterTree*)
1493 * Destroys the tree and his sub-trees
1494 * @param tree Tree which must be destroyed
1497 lttv_filter_tree_destroy(LttvFilterTree
* tree
) {
1499 if(tree
== NULL
) return;
1501 if(tree
->left
== LTTV_TREE_LEAF
) lttv_simple_expression_destroy(tree
->l_child
.leaf
);
1502 else if(tree
->left
== LTTV_TREE_NODE
) lttv_filter_tree_destroy(tree
->l_child
.t
);
1504 if(tree
->right
== LTTV_TREE_LEAF
) lttv_simple_expression_destroy(tree
->r_child
.leaf
);
1505 else if(tree
->right
== LTTV_TREE_NODE
) lttv_filter_tree_destroy(tree
->r_child
.t
);
1507 // g_free(tree->node);
1512 * @fn gboolean lttv_filter_tree_parse(LttvFilterTree*,LttEvent,LttTracefile,LttTrace,LttvProcessState)
1514 * Global parsing function for the current
1516 * @param tree pointer to the current LttvFilterTree
1517 * @param event current LttEvent, NULL if not used
1518 * @param tracefile current LttTracefile, NULL if not used
1519 * @param trace current LttTrace, NULL if not used
1520 * @param state current LttvProcessState, NULL if not used
1523 lttv_filter_tree_parse(
1526 LttTracefile
* tracefile
,
1528 LttvProcessState
* state
1533 * Each tree is parsed in inorder.
1534 * This way, it's possible to apply the left filter of the
1535 * tree, then decide whether or not the right branch should
1536 * be parsed depending on the linking logical operator
1538 * Each node consists in a
1539 * 1. logical operator
1540 * 2. left child ( node or simple expression )
1541 * 3. right child ( node or simple expression )
1543 * When the child is a simple expression, we must
1544 * before all determine if the expression refers to
1545 * a structure which is whithin observation ( not NULL ).
1546 * -If so, the expression is evaluated.
1547 * -If not, the result is set to TRUE since this particular
1548 * operation does not interfere with the lttv structure
1550 * The result of each simple expression will directly
1551 * affect the next branch. This way, depending on
1552 * the linking logical operator, the parser will decide
1553 * to explore or not the next branch.
1555 * -If result of left branch is 0 / FALSE
1556 * then don't explore right branch and return 0;
1557 * -If result of left branch is 1 / TRUE then explore
1559 * -If result of left branch is 1 / TRUE
1560 * then don't explore right branch and return 1;
1561 * -If result of left branch is 0 / FALSE then explore
1563 * -Result of left branch will not affect exploration of
1566 g_print("filter::lttv_parse_tree(...)\n");
1568 gboolean lresult
= FALSE
, rresult
= FALSE
;
1573 if(t
->left
== LTTV_TREE_NODE
) lresult
= lttv_filter_tree_parse(t
->l_child
.t
,event
,tracefile
,trace
,state
);
1574 else if(t
->left
== LTTV_TREE_LEAF
) {
1575 //g_print("%p: left is %i %p %s\n",t,t->l_child.leaf->field,t->l_child.leaf->op,t->l_child.leaf->value);
1577 v
= t
->l_child
.leaf
->value
;
1578 switch(t
->l_child
.leaf
->field
) {
1580 case LTTV_FILTER_TRACE_NAME
:
1581 if(trace
== NULL
) lresult
= TRUE
;
1582 else lresult
= t
->l_child
.leaf
->op((gpointer
)ltt_trace_name(trace
),v
);
1584 case LTTV_FILTER_TRACEFILE_NAME
:
1585 if(tracefile
== NULL
) lresult
= TRUE
;
1586 else lresult
= t
->l_child
.leaf
->op((gpointer
)ltt_tracefile_name(tracefile
),v
);
1588 case LTTV_FILTER_STATE_PID
:
1589 if(state
== NULL
) lresult
= TRUE
;
1590 else lresult
= t
->l_child
.leaf
->op((gpointer
)&state
->pid
,v
);
1592 case LTTV_FILTER_STATE_PPID
:
1593 if(state
== NULL
) lresult
= TRUE
;
1594 else lresult
= t
->l_child
.leaf
->op((gpointer
)&state
->ppid
,v
);
1596 case LTTV_FILTER_STATE_CT
:
1597 if(state
== NULL
) lresult
= TRUE
;
1599 // double val = ltt_time_to_double(state->creation_time);
1600 lresult
= t
->l_child
.leaf
->op((gpointer
)&state
->creation_time
,v
);
1603 case LTTV_FILTER_STATE_IT
:
1604 if(state
== NULL
) lresult
= TRUE
;
1606 // double val = ltt_time_to_double(state->insertion_time);
1607 lresult
= t
->l_child
.leaf
->op((gpointer
)&state
->insertion_time
,v
);
1610 case LTTV_FILTER_STATE_P_NAME
:
1612 * FIXME: Yet to be done ( I think ? )
1616 case LTTV_FILTER_STATE_EX_MODE
:
1617 if(state
== NULL
) lresult
= TRUE
;
1618 else lresult
= t
->l_child
.leaf
->op((gpointer
)&state
->state
->t
,v
);
1620 case LTTV_FILTER_STATE_EX_SUBMODE
:
1621 if(state
== NULL
) lresult
= TRUE
;
1622 else lresult
= t
->l_child
.leaf
->op((gpointer
)&state
->state
->n
,v
);
1624 case LTTV_FILTER_STATE_P_STATUS
:
1625 if(state
== NULL
) lresult
= TRUE
;
1626 else lresult
= t
->l_child
.leaf
->op((gpointer
)&state
->state
->s
,v
);
1628 case LTTV_FILTER_STATE_CPU
:
1630 * FIXME: What is the comparison value ?
1634 case LTTV_FILTER_EVENT_NAME
:
1635 if(event
== NULL
) lresult
= TRUE
;
1636 else lresult
= t
->l_child
.leaf
->op((gpointer
)ltt_event_eventtype(event
),v
);
1639 case LTTV_FILTER_EVENT_CATEGORY
:
1641 * FIXME: Not yet implemented
1645 case LTTV_FILTER_EVENT_TIME
:
1646 // if(event == NULL) lresult = TRUE;
1648 // double val = ltt_time_to_double(event->event_time);
1649 // lresult = t->l_child.leaf->op((gpointer)&val,v);
1653 case LTTV_FILTER_EVENT_TSC
:
1654 // if(event == NULL) lresult = TRUE;
1656 // double val = ltt_time_to_double(event->event_time);
1657 // lresult = t->l_child.leaf->op((gpointer)&val,v);
1660 * FIXME: Where is event.tsc
1664 case LTTV_FILTER_EVENT_FIELD
:
1666 * TODO: Use the offset to
1667 * find the dynamic field
1668 * in the event struct
1673 * This case should never be
1674 * parsed, if so, the whole
1675 * filtering is cancelled
1677 g_warning("Error while parsing the filter tree");
1683 * Parse linking operator
1684 * make a cutoff if possible
1686 if((t
->node
& LTTV_LOGICAL_OR
) && lresult
== TRUE
) return TRUE
;
1687 if((t
->node
& LTTV_LOGICAL_AND
) && lresult
== FALSE
) return FALSE
;
1690 * Parse right branch
1692 if(t
->right
== LTTV_TREE_NODE
) rresult
= lttv_filter_tree_parse(t
->r_child
.t
,event
,tracefile
,trace
,state
);
1693 else if(t
->right
== LTTV_TREE_LEAF
) {
1694 //g_print("%p: right is %i %p %s\n",t,t->r_child.leaf->field,t->r_child.leaf->op,t->r_child.leaf->value);
1696 v
= t
->r_child
.leaf
->value
;
1697 switch(t
->r_child
.leaf
->field
) {
1699 case LTTV_FILTER_TRACE_NAME
:
1700 if(trace
== NULL
) rresult
= TRUE
;
1701 else rresult
= t
->r_child
.leaf
->op((gpointer
)ltt_trace_name(trace
),v
);
1703 case LTTV_FILTER_TRACEFILE_NAME
:
1704 if(tracefile
== NULL
) rresult
= TRUE
;
1705 else rresult
= t
->r_child
.leaf
->op((gpointer
)ltt_tracefile_name(tracefile
),v
);
1707 case LTTV_FILTER_STATE_PID
:
1708 if(state
== NULL
) rresult
= TRUE
;
1709 else rresult
= t
->r_child
.leaf
->op((gpointer
)&state
->pid
,v
);
1711 case LTTV_FILTER_STATE_PPID
:
1712 if(state
== NULL
) rresult
= TRUE
;
1713 else rresult
= t
->r_child
.leaf
->op((gpointer
)&state
->ppid
,v
);
1715 case LTTV_FILTER_STATE_CT
:
1716 if(state
== NULL
) rresult
= TRUE
;
1718 // double val = ltt_time_to_double(state->creation_time);
1719 rresult
= t
->r_child
.leaf
->op((gpointer
)&state
->creation_time
,v
);
1722 case LTTV_FILTER_STATE_IT
:
1723 if(state
== NULL
) rresult
= TRUE
;
1725 // double val = ltt_time_to_double(state->insertion_time);
1726 rresult
= t
->r_child
.leaf
->op((gpointer
)&state
->insertion_time
,v
);
1729 case LTTV_FILTER_STATE_P_NAME
:
1731 * FIXME: Yet to be done ( I think ? )
1735 case LTTV_FILTER_STATE_EX_MODE
:
1736 if(state
== NULL
) rresult
= TRUE
;
1737 else rresult
= t
->r_child
.leaf
->op((gpointer
)&state
->state
->t
,v
);
1739 case LTTV_FILTER_STATE_EX_SUBMODE
:
1740 if(state
== NULL
) rresult
= TRUE
;
1741 else rresult
= t
->r_child
.leaf
->op((gpointer
)&state
->state
->n
,v
);
1743 case LTTV_FILTER_STATE_P_STATUS
:
1744 if(state
== NULL
) rresult
= TRUE
;
1745 else rresult
= t
->r_child
.leaf
->op((gpointer
)&state
->state
->s
,v
);
1747 case LTTV_FILTER_STATE_CPU
:
1749 * FIXME: What is the comparison value ?
1753 case LTTV_FILTER_EVENT_NAME
:
1754 if(event
== NULL
) rresult
= TRUE
;
1755 else rresult
= t
->r_child
.leaf
->op((gpointer
)ltt_event_eventtype(event
),v
);
1758 case LTTV_FILTER_EVENT_CATEGORY
:
1760 * FIXME: Not yet implemented
1764 case LTTV_FILTER_EVENT_TIME
:
1765 // if(event == NULL) rresult = TRUE;
1767 // double val = ltt_time_to_double(event->event_time);
1768 // rresult = t->r_child.leaf->op((gpointer)&event->event_time,v);
1772 case LTTV_FILTER_EVENT_TSC
:
1773 // if(event == NULL) rresult = TRUE;
1775 // double val = ltt_time_to_double(event->event_time);
1776 // rresult = t->r_child.leaf->op((gpointer)&val,v);
1779 * FIXME: Where is event.tsc
1783 case LTTV_FILTER_EVENT_FIELD
:
1785 * TODO: Use the offset to
1786 * find the dynamic field
1787 * in the event struct
1792 * This case should never be
1793 * parsed, if so, this subtree
1796 g_warning("Error while parsing the filter tree");
1802 * Apply and return the
1803 * logical link between the
1807 case LTTV_LOGICAL_OR
: return (lresult
| rresult
);
1808 case LTTV_LOGICAL_AND
: return (lresult
& rresult
);
1809 case LTTV_LOGICAL_NOT
: return (!rresult
);
1810 case LTTV_LOGICAL_XOR
: return (lresult
^ rresult
);
1811 case 0: return (rresult
);
1814 * This case should never be
1815 * parsed, if so, this subtree
1824 * @fn void lttv_print_tree(LttvFilterTree*)
1827 * @param t the pointer to the current LttvFilterTree
1830 lttv_print_tree(LttvFilterTree
* t
) {
1832 g_print("node:%p lchild:%p rchild:%p\n",t
, //t->l_child.t,t->r_child.t);
1833 (t
->left
==LTTV_TREE_NODE
)?t
->l_child
.t
:NULL
,
1834 (t
->right
==LTTV_TREE_NODE
)?t
->r_child
.t
:NULL
);
1835 g_print("node type: %i / [left] %i / [right] %i\n",t
->node
,t
->left
,t
->right
);
1836 if(t
->left
== LTTV_TREE_NODE
) lttv_print_tree(t
->l_child
.t
);
1837 else if(t
->left
== LTTV_TREE_LEAF
) {
1838 // g_assert(t->l_child.leaf->value != NULL);
1839 g_print("%p: left is %i %p value\n",t
,t
->l_child
.leaf
->field
,t
->l_child
.leaf
->op
);
1841 if(t
->right
== LTTV_TREE_NODE
) lttv_print_tree(t
->r_child
.t
);
1842 else if(t
->right
== LTTV_TREE_LEAF
) {
1843 // g_assert(t->r_child.leaf->value != NULL);
1844 g_print("%p: right is %i %p value\n",t
,t
->r_child
.leaf
->field
,t
->r_child
.leaf
->op
);
1850 * @fn gboolean lttv_filter_tracefile(LttvFilter*, LttTracefile*)
1852 * Apply the filter to a specific trace
1853 * @param filter the current filter applied
1854 * @param tracefile the trace to apply the filter to
1855 * @return success/failure of operation
1858 lttv_filter_tracefile(LttvFilter
*filter
, LttTracefile
*tracefile
) {
1860 return lttv_filter_tree_parse(filter
->head
,NULL
,tracefile
,NULL
,NULL
);
1865 * @fn gboolean lttv_filter_tracestate(LttvFilter*,LttvTraceState*)
1867 * Parse the current tracestate
1868 * @param filter pointer to the current LttvFilter
1869 * @param tracestate pointer to the current tracestate
1872 lttv_filter_tracestate(LttvFilter
*filter
, LttvTraceState
*tracestate
) {
1877 * @fn gboolean lttv_filter_event(LttvFilter*,LttEvent*)
1879 * Apply the filter to a specific event
1880 * @param filter the current filter applied
1881 * @param event the event to apply the filter to
1882 * @return success/failure of operation
1885 lttv_filter_event(LttvFilter
*filter
, LttEvent
*event
) {
1890 * @fn static void module_init()
1892 * Initializes the filter module and specific values
1894 static void module_init()
1900 * @fn Destroys the filter module and specific values
1902 static void module_destroy()
1908 LTTV_MODULE("filter", "Filters traceset and events", \
1909 "Filters traceset and events specifically to user input", \
1910 module_init
, module_destroy
)