Filter: index array, sequences, implement bitwise binary operators
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 4 Jul 2017 20:28:54 +0000 (16:28 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 6 Jun 2018 19:54:43 +0000 (15:54 -0400)
Add load expressions, and produce bytecode allowing indexing of array
and sequence of integers, as well as bitwise binary operators &, |, ^.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
18 files changed:
src/lib/lttng-ctl/filter/Makefile.am
src/lib/lttng-ctl/filter/filter-ast.h
src/lib/lttng-ctl/filter/filter-bytecode.h
src/lib/lttng-ctl/filter/filter-grammar-test.c
src/lib/lttng-ctl/filter/filter-ir.h
src/lib/lttng-ctl/filter/filter-lexer.l
src/lib/lttng-ctl/filter/filter-parser.y
src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c
src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c
src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-op-nesting.c
src/lib/lttng-ctl/filter/filter-visitor-set-parent.c [deleted file]
src/lib/lttng-ctl/filter/filter-visitor-xml.c
src/lib/lttng-ctl/lttng-ctl.c
tests/regression/tools/filtering/gen-ust-events.c
tests/regression/tools/filtering/test_invalid_filter
tests/regression/tools/filtering/test_unsupported_op
tests/regression/tools/filtering/test_valid_filter
tests/regression/tools/filtering/tp.h

index e338eee6e40d9cf4f79ba06f3c7dfa7454cd0604..35feee9a7926dfb45b6b9debd0a5b4fedef899cf 100644 (file)
@@ -9,7 +9,6 @@ BUILT_SOURCES = filter-parser.h
 
 libfilter_la_SOURCES = \
        filter-parser.y filter-lexer.l \
-       filter-visitor-set-parent.c \
        filter-visitor-xml.c \
        filter-visitor-generate-ir.c \
        filter-visitor-ir-check-binary-op-nesting.c \
index 067624906d7ad5cd1fa8cc382c095dcd7e1f5387..4bf42fd3fa915f0abf93a7c083a6c15c8fff9183 100644 (file)
@@ -71,9 +71,9 @@ enum op_type {
        AST_OP_LSHIFT,
        AST_OP_AND,
        AST_OP_OR,
-       AST_OP_BIN_AND,
-       AST_OP_BIN_OR,
-       AST_OP_BIN_XOR,
+       AST_OP_BIT_AND,
+       AST_OP_BIT_OR,
+       AST_OP_BIT_XOR,
 
        AST_OP_EQ,
        AST_OP_NE,
@@ -88,7 +88,7 @@ enum unary_op_type {
        AST_UNARY_PLUS,
        AST_UNARY_MINUS,
        AST_UNARY_NOT,
-       AST_UNARY_BIN_NOT,
+       AST_UNARY_BIT_NOT,
 };
 
 enum ast_link_type {
@@ -134,10 +134,12 @@ struct filter_node {
                                 */
                                struct filter_node *child;
                        } u;
-                       /* prev: linked dot/arrow chain (postfix expression) */
+                       /* prev: backward dot/arrow chain (postfix expression) */
                        struct filter_node *prev;
-                       /* next: linked bracket chain (prefix expression) */
+                       /* next: forward dot/arrow chain, generated by a visitor. */
                        struct filter_node *next;
+                       /* next_bracket: linked bracket chain (prefix expression) */
+                       struct filter_node *next_bracket;
                } expression;
                struct {
                        enum op_type type;
@@ -179,7 +181,6 @@ struct filter_ast *filter_parser_get_ast(struct filter_parser_ctx *parser_ctx)
        return parser_ctx->ast;
 }
 
-int filter_visitor_set_parent(struct filter_parser_ctx *ctx);
 int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream,
                        int indent);
 int filter_visitor_ir_generate(struct filter_parser_ctx *ctx);
index b7b71ad538ad7de884bddf284b2532e09670851a..a86963f73274dcb94ed3e26277dee940d9417b0f 100644 (file)
@@ -35,10 +35,17 @@ struct field_ref {
        uint16_t offset;
 } LTTNG_PACKED;
 
-struct field_ref_index {
-       /* Initially, symbol offset. After link, field offset. */
+struct get_symbol {
+       /* Symbol offset. */
        uint16_t offset;
-       uint64_t index;         /* array index */
+} LTTNG_PACKED;
+
+struct get_index_u16 {
+       uint16_t index;
+} LTTNG_PACKED;
+
+struct get_index_u64 {
+       uint64_t index;
 } LTTNG_PACKED;
 
 struct literal_numeric {
@@ -66,9 +73,9 @@ enum filter_op {
        FILTER_OP_MINUS                         = 6,
        FILTER_OP_RSHIFT                        = 7,
        FILTER_OP_LSHIFT                        = 8,
-       FILTER_OP_BIN_AND                       = 9,
-       FILTER_OP_BIN_OR                        = 10,
-       FILTER_OP_BIN_XOR                       = 11,
+       FILTER_OP_BIT_AND                       = 9,
+       FILTER_OP_BIT_OR                        = 10,
+       FILTER_OP_BIT_XOR                       = 11,
 
        /* binary comparators */
        FILTER_OP_EQ                            = 12,
@@ -169,13 +176,30 @@ enum filter_op {
        FILTER_OP_EQ_STAR_GLOB_STRING           = 77,
        FILTER_OP_NE_STAR_GLOB_STRING           = 78,
 
-       /* load field ref with index */
-       FILTER_OP_LOAD_FIELD_REF_INDEX                  = 79,
-       FILTER_OP_LOAD_FIELD_REF_INDEX_S64              = 80,
-
-       /* get context ref with index */
-       FILTER_OP_GET_CONTEXT_REF_INDEX                 = 81,
-       FILTER_OP_GET_CONTEXT_REF_INDEX_S64             = 82,
+       /*
+        * Instructions for recursive traversal through composed types.
+        */
+       FILTER_OP_GET_CONTEXT_ROOT              = 79,
+       FILTER_OP_GET_APP_CONTEXT_ROOT          = 80,
+       FILTER_OP_GET_PAYLOAD_ROOT              = 81,
+
+       FILTER_OP_GET_SYMBOL                    = 82,
+       FILTER_OP_GET_SYMBOL_FIELD              = 83,
+       FILTER_OP_GET_INDEX_U16                 = 84,
+       FILTER_OP_GET_INDEX_U64                 = 85,
+
+       FILTER_OP_LOAD_FIELD                    = 86,
+       FILTER_OP_LOAD_FIELD_S8                 = 87,
+       FILTER_OP_LOAD_FIELD_S16                = 88,
+       FILTER_OP_LOAD_FIELD_S32                = 89,
+       FILTER_OP_LOAD_FIELD_S64                = 90,
+       FILTER_OP_LOAD_FIELD_U8                 = 91,
+       FILTER_OP_LOAD_FIELD_U16                = 92,
+       FILTER_OP_LOAD_FIELD_U32                = 93,
+       FILTER_OP_LOAD_FIELD_U64                = 94,
+       FILTER_OP_LOAD_FIELD_STRING             = 95,
+       FILTER_OP_LOAD_FIELD_SEQUENCE           = 96,
+       FILTER_OP_LOAD_FIELD_DOUBLE             = 97,
 
        NR_FILTER_OPS,
 };
index 782154306768f944b3869cec77483efd625d08fe..b5e6616f5e871bdf01fe706cb3375f3418bdec18 100644 (file)
@@ -61,11 +61,6 @@ int main(int argc, char **argv)
                fprintf(stderr, "Parse error\n");
                goto parse_error;
        }
-       ret = filter_visitor_set_parent(ctx);
-       if (ret) {
-               fprintf(stderr, "Set parent error\n");
-               goto parse_error;
-       }
        if (print_xml) {
                ret = filter_visitor_print_xml(ctx, stdout, 0);
                if (ret) {
index c07050df58d666e9736e9095b1a74c847aa81c96..9d2079393c9d0913768b184225805a508f8782d5 100644 (file)
@@ -38,8 +38,7 @@ enum ir_data_type {
        IR_DATA_FLOAT,
        IR_DATA_FIELD_REF,
        IR_DATA_GET_CONTEXT_REF,
-       IR_DATA_FIELD_REF_INDEX,
-       IR_DATA_GET_CONTEXT_REF_INDEX,
+       IR_DATA_EXPRESSION,
 };
 
 enum ir_op_type {
@@ -73,6 +72,28 @@ struct ir_op_root {
        struct ir_op *child;
 };
 
+enum ir_load_expression_type {
+       IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT,
+       IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT,
+       IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT,
+       IR_LOAD_EXPRESSION_GET_SYMBOL,
+       IR_LOAD_EXPRESSION_GET_INDEX,
+       IR_LOAD_EXPRESSION_LOAD_FIELD,
+};
+
+struct ir_load_expression_op {
+       struct ir_load_expression_op *next;
+       enum ir_load_expression_type type;
+       union {
+               char *symbol;
+               uint64_t index;
+       } u;
+};
+
+struct ir_load_expression {
+       struct ir_load_expression_op *child;
+};
+
 struct ir_op_load {
        union {
                struct {
@@ -82,10 +103,7 @@ struct ir_op_load {
                int64_t num;
                double flt;
                char *ref;
-               struct {
-                       char *symbol;
-                       uint64_t index;
-               } ref_index;
+               struct ir_load_expression *expression;
        } u;
 };
 
index a45b6e8387c9d0d2ace601b41963bec41221a30b..8a6afff065151b0c41d75d21b53f4ce20bf3ef83 100644 (file)
@@ -49,7 +49,7 @@ HEXDIGIT                      [0-9A-Fa-f]
 OCTALDIGIT                     [0-7]
 UCHARLOWERCASE                 \\u{HEXDIGIT}{4}
 UCHARUPPERCASE                 \\U{HEXDIGIT}{8}
-ID_EXTRA_CHAR                  (":"|".")
+ID_EXTRA_CHAR                  (":")
 ID_NONDIGIT                    {NONDIGIT}|{UCHARLOWERCASE}|{UCHARUPPERCASE}|{ID_EXTRA_CHAR}
 IDENTIFIER                     {ID_NONDIGIT}({ID_NONDIGIT}|{DIGIT})*
 ESCSEQ                         \\(\'|\"|\?|\\|a|b|f|n|r|t|v|{OCTALDIGIT}{1,3}|u{HEXDIGIT}{4}|U{HEXDIGIT}{8}|x{HEXDIGIT}+)
index 12605cd382b8af4d65c3d59b7076b3d982870af5..7c4aebe8db3807ed4a2034bbccd95da625e0544d 100644 (file)
@@ -336,6 +336,8 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx)
 %type <gs> s_char s_char_sequence c_char c_char_sequence
 
 %type <n> primary_expression
+%type <n> prefix_expression
+%type <n> prefix_expression_rec
 %type <n> postfix_expression
 %type <n> unary_expression
 %type <n> unary_operator
@@ -350,6 +352,7 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx)
 %type <n> logical_and_expression
 %type <n> logical_or_expression
 %type <n> expression
+%type <n> identifiers
 
 %%
 
@@ -390,21 +393,8 @@ s_char:
                }
        ;
 
-primary_expression
-       :       IDENTIFIER
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_IDENTIFIER;
-                       $$->u.expression.u.identifier = yylval.gs->s;
-               }
-       |       GLOBAL_IDENTIFIER
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_GLOBAL_IDENTIFIER;
-                       $$->u.expression.u.identifier = yylval.gs->s;
-               }
-
-       |       DECIMAL_CONSTANT
+primary_expression:
+               DECIMAL_CONSTANT
                {
                        $$ = make_node(parser_ctx, NODE_EXPRESSION);
                        $$->u.expression.type = AST_EXP_CONSTANT;
@@ -468,29 +458,62 @@ primary_expression
                }
        ;
 
-postfix_expression
-       : primary_expression
-               {       $$ = $1;                                        }
-       | postfix_expression LSBRAC unary_expression RSBRAC
+identifiers
+       :       IDENTIFIER
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_IDENTIFIER;
+                       $$->u.expression.u.identifier = yylval.gs->s;
+               }
+       |       GLOBAL_IDENTIFIER
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_GLOBAL_IDENTIFIER;
+                       $$->u.expression.u.identifier = yylval.gs->s;
+               }
+       ;
+
+prefix_expression_rec
+       : LSBRAC unary_expression RSBRAC
+               {
+                       $$ = $2;
+               }
+       | LSBRAC unary_expression RSBRAC prefix_expression_rec
+               {
+                       $$ = $2;
+                       $$->u.expression.pre_op = AST_LINK_BRACKET;
+                       $$->u.expression.prev = $4;
+               }
+       ;
+
+prefix_expression
+       : identifiers
+               {
+                       $$ = $1;
+               }
+       | identifiers prefix_expression_rec
                {
                        $$ = $1;
                        $$->u.expression.pre_op = AST_LINK_BRACKET;
-                       $$->u.expression.next = $3;
+                       $$->u.expression.next_bracket = $2;
                }
-       | postfix_expression DOT IDENTIFIER
+       ;
+
+postfix_expression
+       : prefix_expression
                {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_IDENTIFIER;
+                       $$ = $1;
+               }
+       | postfix_expression DOT prefix_expression
+               {
+                       $$ = $3;
                        $$->u.expression.post_op = AST_LINK_DOT;
-                       $$->u.expression.u.identifier = $3->s;
                        $$->u.expression.prev = $1;
                }
-       | postfix_expression RARROW IDENTIFIER
+       | postfix_expression RARROW prefix_expression
                {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_IDENTIFIER;
+                       $$ = $3;
                        $$->u.expression.post_op = AST_LINK_RARROW;
-                       $$->u.expression.u.identifier = $3->s;
                        $$->u.expression.prev = $1;
                }
        ;
@@ -498,6 +521,8 @@ postfix_expression
 unary_expression
        : postfix_expression
                {       $$ = $1;                                        }
+       | primary_expression
+               {       $$ = $1;                                        }
        | unary_operator unary_expression
                {
                        $$ = $1;
@@ -524,7 +549,7 @@ unary_operator
        | NOT_BIN
                {
                        $$ = make_node(parser_ctx, NODE_UNARY_OP);
-                       $$->u.unary_op.type = AST_UNARY_BIN_NOT;
+                       $$->u.unary_op.type = AST_UNARY_BIT_NOT;
                }
        ;
 
@@ -610,7 +635,7 @@ and_expression
                {       $$ = $1;                                        }
        | and_expression AND_BIN equality_expression
                {
-                       $$ = make_op_node(parser_ctx, AST_OP_BIN_AND, $1, $3);
+                       $$ = make_op_node(parser_ctx, AST_OP_BIT_AND, $1, $3);
                }
        ;
 
@@ -619,7 +644,7 @@ exclusive_or_expression
                {       $$ = $1;                                        }
        | exclusive_or_expression XOR_BIN and_expression
                {
-                       $$ = make_op_node(parser_ctx, AST_OP_BIN_XOR, $1, $3);
+                       $$ = make_op_node(parser_ctx, AST_OP_BIT_XOR, $1, $3);
                }
        ;
 
@@ -628,7 +653,7 @@ inclusive_or_expression
                {       $$ = $1;                                        }
        | inclusive_or_expression OR_BIN exclusive_or_expression
                {
-                       $$ = make_op_node(parser_ctx, AST_OP_BIN_OR, $1, $3);
+                       $$ = make_op_node(parser_ctx, AST_OP_BIT_OR, $1, $3);
                }
        ;
 
index 74cef91dc3c0c35acb9ce7b167afc05b3a71286a..34183ed2edf4f79a46ff5624f4ce4e60a593fdfc 100644 (file)
@@ -157,6 +157,167 @@ int visit_node_root(struct filter_parser_ctx *ctx, struct ir_op *node)
        return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
 }
 
+static
+int visit_node_load_expression(struct filter_parser_ctx *ctx,
+               const struct ir_op *node)
+{
+       struct ir_load_expression *exp;
+       struct ir_load_expression_op *op;
+
+       exp = node->u.load.u.expression;
+       if (!exp) {
+               return -EINVAL;
+       }
+       op = exp->child;
+       if (!op) {
+               return -EINVAL;
+       }
+       for (; op != NULL; op = op->next) {
+               switch (op->type) {
+               case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
+               {
+                       struct load_op *insn;
+                       uint32_t insn_len = sizeof(struct load_op);
+                       int ret;
+
+                       insn = calloc(insn_len, 1);
+                       if (!insn)
+                               return -ENOMEM;
+                       insn->op = FILTER_OP_GET_CONTEXT_ROOT;
+                       ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+                       free(insn);
+                       if (ret) {
+                               return ret;
+                       }
+                       break;
+               }
+               case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
+               {
+                       struct load_op *insn;
+                       uint32_t insn_len = sizeof(struct load_op);
+                       int ret;
+
+                       insn = calloc(insn_len, 1);
+                       if (!insn)
+                               return -ENOMEM;
+                       insn->op = FILTER_OP_GET_APP_CONTEXT_ROOT;
+                       ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+                       free(insn);
+                       if (ret) {
+                               return ret;
+                       }
+                       break;
+               }
+               case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
+               {
+                       struct load_op *insn;
+                       uint32_t insn_len = sizeof(struct load_op);
+                       int ret;
+
+                       insn = calloc(insn_len, 1);
+                       if (!insn)
+                               return -ENOMEM;
+                       insn->op = FILTER_OP_GET_PAYLOAD_ROOT;
+                       ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+                       free(insn);
+                       if (ret) {
+                               return ret;
+                       }
+                       break;
+               }
+               case IR_LOAD_EXPRESSION_GET_SYMBOL:
+               {
+                       struct load_op *insn;
+                       uint32_t insn_len = sizeof(struct load_op)
+                               + sizeof(struct get_symbol);
+                       struct get_symbol symbol_offset;
+                       uint32_t reloc_offset_u32;
+                       uint16_t reloc_offset;
+                       uint32_t bytecode_reloc_offset_u32;
+                       int ret;
+
+                       insn = calloc(insn_len, 1);
+                       if (!insn)
+                               return -ENOMEM;
+                       insn->op = FILTER_OP_GET_SYMBOL;
+                       bytecode_reloc_offset_u32 =
+                                       bytecode_get_len(&ctx->bytecode_reloc->b)
+                                       + sizeof(reloc_offset);
+                       symbol_offset.offset =
+                                       (uint16_t) bytecode_reloc_offset_u32;
+                       memcpy(insn->data, &symbol_offset,
+                                       sizeof(symbol_offset));
+                       /* reloc_offset points to struct load_op */
+                       reloc_offset_u32 = bytecode_get_len(&ctx->bytecode->b);
+                       if (reloc_offset_u32 > LTTNG_FILTER_MAX_LEN - 1) {
+                               free(insn);
+                               return -EINVAL;
+                       }
+                       reloc_offset = (uint16_t) reloc_offset_u32;
+                       ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+                       if (ret) {
+                               free(insn);
+                               return ret;
+                       }
+                       /* append reloc */
+                       ret = bytecode_push(&ctx->bytecode_reloc, &reloc_offset,
+                                       1, sizeof(reloc_offset));
+                       if (ret) {
+                               free(insn);
+                               return ret;
+                       }
+                       ret = bytecode_push(&ctx->bytecode_reloc,
+                                       op->u.symbol,
+                                       1, strlen(op->u.symbol) + 1);
+                       free(insn);
+                       if (ret) {
+                               return ret;
+                       }
+                       break;
+               }
+               case IR_LOAD_EXPRESSION_GET_INDEX:
+               {
+                       struct load_op *insn;
+                       uint32_t insn_len = sizeof(struct load_op)
+                               + sizeof(struct get_index_u64);
+                       struct get_index_u64 index;
+                       int ret;
+
+                       insn = calloc(insn_len, 1);
+                       if (!insn)
+                               return -ENOMEM;
+                       insn->op = FILTER_OP_GET_INDEX_U64;
+                       index.index = op->u.index;
+                       memcpy(insn->data, &index, sizeof(index));
+                       ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+                       free(insn);
+                       if (ret) {
+                               return ret;
+                       }
+                       break;
+               }
+               case IR_LOAD_EXPRESSION_LOAD_FIELD:
+               {
+                       struct load_op *insn;
+                       uint32_t insn_len = sizeof(struct load_op);
+                       int ret;
+
+                       insn = calloc(insn_len, 1);
+                       if (!insn)
+                               return -ENOMEM;
+                       insn->op = FILTER_OP_LOAD_FIELD;
+                       ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+                       free(insn);
+                       if (ret) {
+                               return ret;
+                       }
+                       break;
+               }
+               }
+       }
+       return 0;
+}
+
 static
 int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
 {
@@ -239,107 +400,8 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
                free(insn);
                return ret;
        }
-       case IR_DATA_FIELD_REF: /* fall-through */
-       case IR_DATA_GET_CONTEXT_REF:
-       {
-               struct load_op *insn;
-               uint32_t insn_len = sizeof(struct load_op)
-                       + sizeof(struct field_ref);
-               struct field_ref ref_offset;
-               uint32_t reloc_offset_u32;
-               uint16_t reloc_offset;
-
-               insn = calloc(insn_len, 1);
-               if (!insn)
-                       return -ENOMEM;
-               switch (node->data_type) {
-               case IR_DATA_FIELD_REF:
-                       insn->op = FILTER_OP_LOAD_FIELD_REF;
-                       break;
-               case IR_DATA_GET_CONTEXT_REF:
-                       insn->op = FILTER_OP_GET_CONTEXT_REF;
-                       break;
-               default:
-                       free(insn);
-                       return -EINVAL;
-               }
-               ref_offset.offset = (uint16_t) -1U;
-               memcpy(insn->data, &ref_offset, sizeof(ref_offset));
-               /* reloc_offset points to struct load_op */
-               reloc_offset_u32 = bytecode_get_len(&ctx->bytecode->b);
-               if (reloc_offset_u32 > LTTNG_FILTER_MAX_LEN - 1) {
-                       free(insn);
-                       return -EINVAL;
-               }
-               reloc_offset = (uint16_t) reloc_offset_u32;
-               ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
-               if (ret) {
-                       free(insn);
-                       return ret;
-               }
-               /* append reloc */
-               ret = bytecode_push(&ctx->bytecode_reloc, &reloc_offset,
-                                       1, sizeof(reloc_offset));
-               if (ret) {
-                       free(insn);
-                       return ret;
-               }
-               ret = bytecode_push(&ctx->bytecode_reloc, node->u.load.u.ref,
-                                       1, strlen(node->u.load.u.ref) + 1);
-               free(insn);
-               return ret;
-       }
-       case IR_DATA_FIELD_REF_INDEX:   /* fall-through */
-       case IR_DATA_GET_CONTEXT_REF_INDEX:
-       {
-               struct load_op *insn;
-               uint32_t insn_len = sizeof(struct load_op)
-                       + sizeof(struct field_ref_index);
-               struct field_ref_index ref_index_offset;
-               uint32_t reloc_offset_u32;
-               uint16_t reloc_offset;
-
-               insn = calloc(insn_len, 1);
-               if (!insn)
-                       return -ENOMEM;
-               switch (node->data_type) {
-               case IR_DATA_FIELD_REF_INDEX:
-                       insn->op = FILTER_OP_LOAD_FIELD_REF_INDEX;
-                       break;
-               case IR_DATA_GET_CONTEXT_REF_INDEX:
-                       insn->op = FILTER_OP_GET_CONTEXT_REF_INDEX;
-                       break;
-               default:
-                       free(insn);
-                       return -EINVAL;
-               }
-               ref_index_offset.offset = (uint16_t) -1U;
-               ref_index_offset.index = node->u.load.u.ref_index.index;
-               memcpy(insn->data, &ref_index_offset, sizeof(ref_index_offset));
-               /* reloc_offset points to struct load_op */
-               reloc_offset_u32 = bytecode_get_len(&ctx->bytecode->b);
-               if (reloc_offset_u32 > LTTNG_FILTER_MAX_LEN - 1) {
-                       free(insn);
-                       return -EINVAL;
-               }
-               reloc_offset = (uint16_t) reloc_offset_u32;
-               ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
-               if (ret) {
-                       free(insn);
-                       return ret;
-               }
-               /* append reloc */
-               ret = bytecode_push(&ctx->bytecode_reloc, &reloc_offset,
-                                       1, sizeof(reloc_offset));
-               if (ret) {
-                       free(insn);
-                       return ret;
-               }
-               ret = bytecode_push(&ctx->bytecode_reloc, node->u.load.u.ref_index.symbol,
-                                       1, strlen(node->u.load.u.ref_index.symbol) + 1);
-               free(insn);
-               return ret;
-       }
+       case IR_DATA_EXPRESSION:
+               return visit_node_load_expression(ctx, node);
        }
 }
 
@@ -425,14 +487,14 @@ int visit_node_binary(struct filter_parser_ctx *ctx, struct ir_op *node)
        case AST_OP_LSHIFT:
                insn.op = FILTER_OP_LSHIFT;
                break;
-       case AST_OP_BIN_AND:
-               insn.op = FILTER_OP_BIN_AND;
+       case AST_OP_BIT_AND:
+               insn.op = FILTER_OP_BIT_AND;
                break;
-       case AST_OP_BIN_OR:
-               insn.op = FILTER_OP_BIN_OR;
+       case AST_OP_BIT_OR:
+               insn.op = FILTER_OP_BIT_OR;
                break;
-       case AST_OP_BIN_XOR:
-               insn.op = FILTER_OP_BIN_XOR;
+       case AST_OP_BIT_XOR:
+               insn.op = FILTER_OP_BIT_XOR;
                break;
 
        case AST_OP_EQ:
@@ -475,15 +537,13 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node)
        /* Cast to s64 if float or field ref */
        if ((node->u.binary.left->data_type == IR_DATA_FIELD_REF
                                || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF
-                               || node->u.binary.left->data_type == IR_DATA_FIELD_REF_INDEX
-                               || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF_INDEX)
+                               || node->u.binary.left->data_type == IR_DATA_EXPRESSION)
                        || node->u.binary.left->data_type == IR_DATA_FLOAT) {
                struct cast_op cast_insn;
 
                if (node->u.binary.left->data_type == IR_DATA_FIELD_REF
                                || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF
-                               || node->u.binary.left->data_type == IR_DATA_FIELD_REF_INDEX
-                               || node->u.binary.left->data_type == IR_DATA_GET_CONTEXT_REF_INDEX) {
+                               || node->u.binary.left->data_type == IR_DATA_EXPRESSION) {
                        cast_insn.op = FILTER_OP_CAST_TO_S64;
                } else {
                        cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
@@ -518,15 +578,13 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node)
        /* Cast to s64 if float or field ref */
        if ((node->u.binary.right->data_type == IR_DATA_FIELD_REF
                                || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF
-                               || node->u.binary.right->data_type == IR_DATA_FIELD_REF_INDEX
-                               || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF_INDEX)
+                               || node->u.binary.right->data_type == IR_DATA_EXPRESSION)
                        || node->u.binary.right->data_type == IR_DATA_FLOAT) {
                struct cast_op cast_insn;
 
                if (node->u.binary.right->data_type == IR_DATA_FIELD_REF
                                || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF
-                               || node->u.binary.right->data_type == IR_DATA_FIELD_REF_INDEX
-                               || node->u.binary.right->data_type == IR_DATA_GET_CONTEXT_REF_INDEX) {
+                               || node->u.binary.right->data_type == IR_DATA_EXPRESSION) {
                        cast_insn.op = FILTER_OP_CAST_TO_S64;
                } else {
                        cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
index 85aadcae6fe7baedec1b30d8d34960c65c5b43fd..cd7930ad5476cb36e62f949d7a9ae818b4cf3723 100644 (file)
@@ -58,6 +58,7 @@ struct ir_op *make_op_root(struct ir_op *child, enum ir_side side)
        case IR_DATA_NUMERIC:
        case IR_DATA_FIELD_REF:
        case IR_DATA_GET_CONTEXT_REF:
+       case IR_DATA_EXPRESSION:
                /* ok */
                break;
        }
@@ -140,99 +141,148 @@ struct ir_op *make_op_load_float(double v, enum ir_side side)
 }
 
 static
-struct ir_op *make_op_load_field_ref(char *string,
-               enum ir_side side)
+void free_load_expression(struct ir_load_expression *load_expression)
 {
-       struct ir_op *op;
+       struct ir_load_expression_op *exp_op;
 
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
-               return NULL;
-       op->op = IR_OP_LOAD;
-       op->data_type = IR_DATA_FIELD_REF;
-       op->signedness = IR_SIGN_DYN;
-       op->side = side;
-       op->u.load.u.ref = strdup(string);
-       if (!op->u.load.u.ref) {
-               goto error;
-       }
-       return op;
+       if (!load_expression)
+               return;
+       exp_op = load_expression->child;
+       for (;;) {
+               struct ir_load_expression_op *prev_exp_op;
 
-error:
-       free(op);
-       return NULL;
+               if (!exp_op)
+                       break;
+               switch (exp_op->type) {
+               case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
+               case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
+               case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
+               case IR_LOAD_EXPRESSION_GET_INDEX:
+               case IR_LOAD_EXPRESSION_LOAD_FIELD:
+                       break;
+               case IR_LOAD_EXPRESSION_GET_SYMBOL:
+                       free(exp_op->u.symbol);
+                       break;
+               }
+               prev_exp_op = exp_op;
+               exp_op = exp_op->next;
+               free(prev_exp_op);
+       }
+       free(load_expression);
 }
 
+/*
+ * Returns the first node of the chain, after initializing the next
+ * pointers.
+ */
 static
-struct ir_op *make_op_load_field_ref_index(char *string,
-               struct filter_node *next,
-               enum ir_side side)
+struct filter_node *load_expression_get_forward_chain(struct filter_node *node)
 {
-       struct ir_op *op;
+       struct filter_node *prev_node;
 
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
-               return NULL;
-       op->op = IR_OP_LOAD;
-       op->data_type = IR_DATA_FIELD_REF_INDEX;
-       op->signedness = IR_SIGN_DYN;
-       op->side = side;
-       op->u.load.u.ref_index.symbol = strdup(string);
-       if (!op->u.load.u.ref_index.symbol) {
-               goto error;
-       }
-       /* Only positive integer literals accepted as index. */
-       if (next->type == NODE_UNARY_OP) {
-               fprintf(stderr, "[error] Unexpected unary operator as index\n");
-               goto error;
-       }
-       if (next->type != NODE_EXPRESSION) {
-               fprintf(stderr, "[error] Expecting expression as index\n");
-               goto error;
-       }
-       if (next->u.expression.type != AST_EXP_CONSTANT) {
-               fprintf(stderr, "[error] Expecting constant index\n");
-               goto error;
-       }
-       if (next->u.expression.u.constant < 0) {
-               fprintf(stderr, "[error] Expecting positive constant index\n");
-               goto error;
+       for (;;) {
+               assert(node->type == NODE_EXPRESSION);
+               prev_node = node;
+               node = node->u.expression.prev;
+               if (!node) {
+                       break;
+               }
+               node->u.expression.next = prev_node;
        }
-       op->u.load.u.ref_index.index = next->u.expression.u.constant;
-       return op;
-
-error:
-       free(op);
-       return NULL;
+       return prev_node;
 }
 
 static
-struct ir_op *make_op_load_get_context_ref(char *string,
-               enum ir_side side)
+struct ir_load_expression *create_load_expression(struct filter_node *node)
 {
-       struct ir_op *op;
+       struct ir_load_expression *load_exp;
+       struct ir_load_expression_op *load_exp_op, *prev_op;
+       char *str;
 
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
+       /* Get forward chain. */
+       node = load_expression_get_forward_chain(node);
+       if (!node)
                return NULL;
-       op->op = IR_OP_LOAD;
-       op->data_type = IR_DATA_GET_CONTEXT_REF;
-       op->signedness = IR_SIGN_DYN;
-       op->side = side;
-       op->u.load.u.ref = strdup(string);
-       if (!op->u.load.u.ref) {
+       load_exp = calloc(sizeof(struct ir_load_expression), 1);
+       if (!load_exp)
+               return NULL;
+
+       /* Root */
+       load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
+       if (!load_exp_op)
+               goto error;
+       load_exp->child = load_exp_op;
+       str = node->u.expression.u.string;
+       if (!strcmp(str, "$ctx")) {
+               load_exp_op->type = IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT;
+               node = node->u.expression.next;
+               if (!node) {
+                       fprintf(stderr, "[error] Expecting identifier after \'%s\'\n", str);
+                       goto error;
+               }
+               str = node->u.expression.u.string;
+       } else if (!strcmp(str, "$app")) {
+               load_exp_op->type = IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT;
+               node = node->u.expression.next;
+               if (!node) {
+                       fprintf(stderr, "[error] Expecting identifier after \'%s\'\n", str);
+                       goto error;
+               }
+               str = node->u.expression.u.string;
+       } else if (str[0] == '$') {
+               fprintf(stderr, "[error] Unexpected identifier \'%s\'\n", str);
                goto error;
+       } else {
+               load_exp_op->type = IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT;
+       }
+
+       for (;;) {
+               struct filter_node *bracket_node;
+
+               prev_op = load_exp_op;
+               load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
+               if (!load_exp_op)
+                       goto error;
+               prev_op->next = load_exp_op;
+               load_exp_op->type = IR_LOAD_EXPRESSION_GET_SYMBOL;
+               load_exp_op->u.symbol = strdup(str);
+               if (!load_exp_op->u.symbol)
+                       goto error;
+
+               /* Explore brackets from current node. */
+               for (bracket_node = node->u.expression.next_bracket;
+                               bracket_node != NULL;
+                               bracket_node = bracket_node->u.expression.next_bracket) {
+                       prev_op = load_exp_op;
+                       load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
+                       if (!load_exp_op)
+                               goto error;
+                       prev_op->next = load_exp_op;
+                       load_exp_op->type = IR_LOAD_EXPRESSION_GET_INDEX;
+                       load_exp_op->u.index = bracket_node->u.expression.u.constant;
+               }
+               /* Go to next chain element. */
+               node = node->u.expression.next;
+               if (!node)
+                       break;
+               str = node->u.expression.u.string;
        }
-       return op;
+       /* Add final load field */
+       prev_op = load_exp_op;
+       load_exp_op = calloc(sizeof(struct ir_load_expression_op), 1);
+       if (!load_exp_op)
+               goto error;
+       prev_op->next = load_exp_op;
+       load_exp_op->type = IR_LOAD_EXPRESSION_LOAD_FIELD;
+       return load_exp;
 
 error:
-       free(op);
+       free_load_expression(load_exp);
        return NULL;
 }
 
 static
-struct ir_op *make_op_load_get_context_ref_index(char *string,
-               struct filter_node *next,
+struct ir_op *make_op_load_expression(struct filter_node *node,
                enum ir_side side)
 {
        struct ir_op *op;
@@ -241,34 +291,17 @@ struct ir_op *make_op_load_get_context_ref_index(char *string,
        if (!op)
                return NULL;
        op->op = IR_OP_LOAD;
-       op->data_type = IR_DATA_GET_CONTEXT_REF_INDEX;
+       op->data_type = IR_DATA_EXPRESSION;
        op->signedness = IR_SIGN_DYN;
        op->side = side;
-       op->u.load.u.ref_index.symbol = strdup(string);
-       if (!op->u.load.u.ref_index.symbol) {
-               goto error;
-       }
-       /* Only positive integer literals accepted as offset. */
-       if (next->type == NODE_UNARY_OP) {
-               fprintf(stderr, "[error] Unexpected unary operator as index\n");
-               goto error;
-       }
-       if (next->type != NODE_EXPRESSION) {
-               fprintf(stderr, "[error] Expecting expression as index\n");
-               goto error;
-       }
-       if (next->u.expression.type != AST_EXP_CONSTANT) {
-               fprintf(stderr, "[error] Expecting constant index\n");
-               goto error;
-       }
-       if (next->u.expression.u.constant < 0) {
-               fprintf(stderr, "[error] Expecting positive constant index\n");
+       op->u.load.u.expression = create_load_expression(node);
+       if (!op->u.load.u.expression) {
                goto error;
        }
-       op->u.load.u.ref_index.index = next->u.expression.u.constant;
        return op;
 
 error:
+       free_load_expression(op->u.load.u.expression);
        free(op);
        return NULL;
 }
@@ -447,6 +480,50 @@ error:
        return NULL;
 }
 
+static
+struct ir_op *make_op_binary_bitwise(enum op_type bin_op_type,
+               const char *op_str, struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       struct ir_op *op = NULL;
+
+       if (left->data_type == IR_DATA_UNKNOWN
+               || right->data_type == IR_DATA_UNKNOWN) {
+               fprintf(stderr, "[error] bitwise binary operation '%s' has unknown operand type\n", op_str);
+               goto error;
+
+       }
+       if (left->data_type == IR_DATA_STRING
+               || right->data_type == IR_DATA_STRING) {
+               fprintf(stderr, "[error] bitwise binary operation '%s' cannot have string operand\n", op_str);
+               goto error;
+       }
+       if (left->data_type == IR_DATA_FLOAT
+               || right->data_type == IR_DATA_FLOAT) {
+               fprintf(stderr, "[error] bitwise binary operation '%s' cannot have floating point operand\n", op_str);
+               goto error;
+       }
+
+       op = calloc(sizeof(struct ir_op), 1);
+       if (!op)
+               return NULL;
+       op->op = IR_OP_BINARY;
+       op->u.binary.type = bin_op_type;
+       op->u.binary.left = left;
+       op->u.binary.right = right;
+
+       /* we return a signed numeric */
+       op->data_type = IR_DATA_NUMERIC;
+       op->signedness = IR_SIGNED;
+       op->side = side;
+
+       return op;
+
+error:
+       free(op);
+       return NULL;
+}
+
 static
 struct ir_op *make_op_binary_logical_and(struct ir_op *left, struct ir_op *right,
                enum ir_side side)
@@ -461,6 +538,27 @@ struct ir_op *make_op_binary_logical_or(struct ir_op *left, struct ir_op *right,
        return make_op_binary_logical(AST_OP_OR, "||", left, right, side);
 }
 
+static
+struct ir_op *make_op_binary_bitwise_and(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_bitwise(AST_OP_BIT_AND, "&", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_bitwise_or(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_bitwise(AST_OP_BIT_OR, "|", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_bitwise_xor(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_bitwise(AST_OP_BIT_XOR, "^", left, right, side);
+}
+
 static
 void filter_free_ir_recursive(struct ir_op *op)
 {
@@ -484,10 +582,8 @@ void filter_free_ir_recursive(struct ir_op *op)
                case IR_DATA_GET_CONTEXT_REF:
                        free(op->u.load.u.ref);
                        break;
-               case IR_DATA_FIELD_REF_INDEX:   /* fall-through */
-               case IR_DATA_GET_CONTEXT_REF_INDEX:
-                       free(op->u.load.u.ref_index.symbol);
-                       break;
+               case IR_DATA_EXPRESSION:
+                       free_load_expression(op->u.load.u.expression);
                default:
                        break;
                }
@@ -526,57 +622,8 @@ struct ir_op *make_expression(struct filter_parser_ctx *ctx,
                return make_op_load_float(node->u.expression.u.float_constant,
                                        side);
        case AST_EXP_IDENTIFIER:
-               switch (node->u.expression.pre_op) {
-               case AST_LINK_UNKNOWN:
-                       return make_op_load_field_ref(node->u.expression.u.identifier,
-                                       side);
-               case AST_LINK_BRACKET:
-                       return make_op_load_field_ref_index(node->u.expression.u.identifier,
-                                       node->u.expression.next,
-                                       side);
-               default:
-                       fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
-                       return NULL;
-               }
        case AST_EXP_GLOBAL_IDENTIFIER:
-       {
-               const char *name;
-
-               /*
-                * We currently only support $ctx (context) and $app
-                * identifiers.
-                */
-               if (strncmp(node->u.expression.u.identifier,
-                               "$ctx.", strlen("$ctx.")) != 0
-                       && strncmp(node->u.expression.u.identifier,
-                               "$app.", strlen("$app.")) != 0) {
-                       fprintf(stderr, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" and \"$app\" are currently implemented.\n", __func__, node->u.expression.u.identifier);
-                       return NULL;
-               }
-               name = strchr(node->u.expression.u.identifier, '.');
-               if (!name) {
-                       fprintf(stderr, "[error] %s: Expecting '.'\n", __func__);
-                       return NULL;
-               }
-               name++; /* Skip . */
-               if (!strlen(name)) {
-                       fprintf(stderr, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__);
-                       return NULL;
-               }
-               switch (node->u.expression.pre_op) {
-               case AST_LINK_UNKNOWN:
-                       return make_op_load_get_context_ref(node->u.expression.u.identifier,
-                                       side);
-               case AST_LINK_BRACKET:
-                       return make_op_load_get_context_ref_index(node->u.expression.u.identifier,
-                                       node->u.expression.next,
-                                       side);
-               default:
-                       fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
-                       return NULL;
-               }
-
-       }
+               return make_op_load_expression(node, side);
        case AST_EXP_NESTED:
                return generate_ir_recursive(ctx, node->u.expression.u.child,
                                        side);
@@ -597,10 +644,8 @@ struct ir_op *make_op(struct filter_parser_ctx *ctx,
                return NULL;
 
        /*
-        * Binary operators other than comparators and logical and/or
-        * are not supported. If we ever want to support those, we will
-        * need a stack for the general case rather than just 2
-        * registers (see bytecode).
+        * The following binary operators other than comparators and
+        * logical and/or are not supported yet.
         */
        case AST_OP_MUL:
                op_str = "*";
@@ -623,15 +668,19 @@ struct ir_op *make_op(struct filter_parser_ctx *ctx,
        case AST_OP_LSHIFT:
                op_str = "<<";
                goto error_not_supported;
-       case AST_OP_BIN_AND:
-               op_str = "&";
-               goto error_not_supported;
-       case AST_OP_BIN_OR:
-               op_str = "|";
-               goto error_not_supported;
-       case AST_OP_BIN_XOR:
-               op_str = "^";
-               goto error_not_supported;
+
+       case AST_OP_BIT_AND:
+       case AST_OP_BIT_OR:
+       case AST_OP_BIT_XOR:
+               lchild = generate_ir_recursive(ctx, node->u.op.lchild, IR_LEFT);
+               if (!lchild)
+                       return NULL;
+               rchild = generate_ir_recursive(ctx, node->u.op.rchild, IR_RIGHT);
+               if (!rchild) {
+                       filter_free_ir_recursive(lchild);
+                       return NULL;
+               }
+               break;
 
        case AST_OP_EQ:
        case AST_OP_NE:
@@ -691,6 +740,15 @@ struct ir_op *make_op(struct filter_parser_ctx *ctx,
        case AST_OP_LE:
                op = make_op_binary_le(lchild, rchild, side);
                break;
+       case AST_OP_BIT_AND:
+               op = make_op_binary_bitwise_and(lchild, rchild, side);
+               break;
+       case AST_OP_BIT_OR:
+               op = make_op_binary_bitwise_or(lchild, rchild, side);
+               break;
+       case AST_OP_BIT_XOR:
+               op = make_op_binary_bitwise_xor(lchild, rchild, side);
+               break;
        default:
                break;
        }
@@ -764,7 +822,7 @@ struct ir_op *make_unary_op(struct filter_parser_ctx *ctx,
                }
                return op;
        }
-       case AST_UNARY_BIN_NOT:
+       case AST_UNARY_BIT_NOT:
        {
                op_str = "~";
                goto error_not_supported;
index e093957c270422a0ee19221cbaffa755148c5f9c..aa3edd592378ea60c5df4af7895ee6d7e267d805 100644 (file)
@@ -53,10 +53,6 @@ int check_bin_op_nesting_recursive(struct ir_op *node, int nesting)
        {
                int ret;
 
-               if (nesting > 0) {
-                       fprintf(stderr, "[error] Nesting of binary operators is not allowed, except for logical operators.\n");
-                       return -EINVAL;
-               }
                ret = check_bin_op_nesting_recursive(node->u.binary.left,
                                nesting + 1);
                if (ret)
diff --git a/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c b/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c
deleted file mode 100644 (file)
index 458688d..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * filter-visitor-set-parent.c
- *
- * LTTng filter set parent visitor
- *
- * Copyright 2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <inttypes.h>
-#include "filter-ast.h"
-#include "filter-parser.h"
-
-#include <common/macros.h>
-
-static
-int update_child(struct filter_node *parent,
-               struct filter_node *old_child,
-               struct filter_node *new_child)
-{
-       if (!parent) {
-               fprintf(stderr, "[error] %s: NULL parent\n", __func__);
-               return -EINVAL;
-       }
-
-       switch (parent->type) {
-       case NODE_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown node type\n", __func__);
-               return -EINVAL;
-       case NODE_ROOT:
-               assert(parent->u.root.child == old_child);
-               parent->u.root.child = new_child;
-               break;
-       case NODE_EXPRESSION:
-               assert(parent->u.expression.type == AST_EXP_NESTED);
-               assert(parent->u.expression.u.child == old_child);
-               parent->u.expression.u.child = new_child;
-               break;
-       case NODE_OP:
-               assert(parent->u.op.lchild == old_child ||
-                       parent->u.op.rchild == old_child);
-               if (parent->u.op.lchild == old_child)
-                       parent->u.op.lchild = new_child;
-               else
-                       parent->u.op.rchild = new_child;
-               break;
-       case NODE_UNARY_OP:
-               assert(parent->u.unary_op.child == old_child);
-               parent->u.unary_op.child = new_child;
-               break;
-       }
-       return 0;
-}
-
-static
-int recursive_visit_set_parent(struct filter_node *node,
-                       struct filter_node *parent)
-{
-       int ret;
-
-       if (!node) {
-               fprintf(stderr, "[error] %s: NULL child\n", __func__);
-               return -EINVAL;
-       }
-       node->parent = parent;
-       switch (node->type) {
-       case NODE_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown node type\n", __func__);
-               return -EINVAL;
-       case NODE_ROOT:
-               assert(parent == NULL);
-               return recursive_visit_set_parent(node->u.root.child, node);
-       case NODE_EXPRESSION:
-               switch (node->u.expression.type) {
-               case AST_EXP_UNKNOWN:
-               default:
-                       fprintf(stderr, "[error] %s: unknown expression type\n", __func__);
-                       return -EINVAL;
-               case AST_EXP_NESTED:
-                       return recursive_visit_set_parent(node->u.expression.u.child, node);
-               case AST_EXP_IDENTIFIER:        /* fall-through */
-               case AST_EXP_GLOBAL_IDENTIFIER:
-                       {
-                               struct filter_node *orig_node = node;
-
-                               while (node->u.expression.prev) {
-                                       struct filter_node *prev;
-
-                                       prev = node->u.expression.prev;
-                                       if (prev->type != NODE_EXPRESSION ||
-                                               (prev->u.expression.type != AST_EXP_IDENTIFIER
-                                               && prev->u.expression.type != AST_EXP_GLOBAL_IDENTIFIER)) {
-                                               fprintf(stderr, "[error] %s: expecting identifier before link\n", __func__);
-                                               return -EINVAL;
-                                       }
-
-                                       prev->u.expression.next = node;
-                                       prev->u.expression.pre_op =
-                                               node->u.expression.post_op;
-                                       prev->parent = node->parent;
-                                       node = prev;
-                               }
-                               /* Set first child as forward */
-                               ret = update_child(parent, orig_node, node);
-                               if (ret)
-                                       return ret;
-                       }
-               case AST_EXP_CONSTANT:
-               case AST_EXP_FLOAT_CONSTANT:
-               case AST_EXP_STRING:
-                       break;
-               }
-               break;
-       case NODE_OP:
-               ret = recursive_visit_set_parent(node->u.op.lchild, node);
-               if (ret)
-                       return ret;
-               return recursive_visit_set_parent(node->u.op.rchild, node);
-       case NODE_UNARY_OP:
-               return recursive_visit_set_parent(node->u.unary_op.child, node);
-       }
-       return 0;
-}
-
-LTTNG_HIDDEN
-int filter_visitor_set_parent(struct filter_parser_ctx *ctx)
-{
-       return recursive_visit_set_parent(&ctx->ast->root, NULL);
-}
index c293ad15ef59617933dc9adb698d2937773d47b3..1e5812015d7237798dd459c09b2a3fb8a9205171 100644 (file)
@@ -169,13 +169,13 @@ int recursive_visit_print(struct filter_node *node, FILE *stream, int indent)
                case AST_OP_OR:
                        fprintf(stream, "\"||\"");
                        break;
-               case AST_OP_BIN_AND:
+               case AST_OP_BIT_AND:
                        fprintf(stream, "\"&\"");
                        break;
-               case AST_OP_BIN_OR:
+               case AST_OP_BIT_OR:
                        fprintf(stream, "\"|\"");
                        break;
-               case AST_OP_BIN_XOR:
+               case AST_OP_BIT_XOR:
                        fprintf(stream, "\"^\"");
                        break;
 
@@ -227,7 +227,7 @@ int recursive_visit_print(struct filter_node *node, FILE *stream, int indent)
                case AST_UNARY_NOT:
                        fprintf(stream, "\"!\"");
                        break;
-               case AST_UNARY_BIN_NOT:
+               case AST_UNARY_BIT_NOT:
                        fprintf(stream, "\"~\"");
                        break;
                }
index 0468b6746f51cdf20e33821cc6cb3d3de9acda9d..8ca8e46effc4e16c4dca3c54fb3697172f47b966 100644 (file)
@@ -887,12 +887,6 @@ static int generate_filter(char *filter_expression,
                ret = -LTTNG_ERR_FILTER_INVAL;
                goto parse_error;
        }
-       ret = filter_visitor_set_parent(ctx);
-       if (ret) {
-               fprintf(stderr, "Set parent error\n");
-               ret = -LTTNG_ERR_FILTER_INVAL;
-               goto parse_error;
-       }
        if (print_xml) {
                ret = filter_visitor_print_xml(ctx, stdout, 0);
                if (ret) {
index c789c89d43312a54aa67fb69e71e02c5b28492c1..91360afb97f06bc98040f2276a6c482d3b78ab61 100644 (file)
@@ -32,6 +32,7 @@ int main(int argc, char **argv)
 {
        int i, netint;
        long values[] = { 1, 2, 3 };
+       uint32_t net_values[] = { 1, 2, 3 };
        char text[10] = "test";
        char escape[10] = "\\*";
        double dbl = 2.0;
@@ -49,9 +50,14 @@ int main(int argc, char **argv)
                nr_usec = atoi(argv[2]);
        }
 
+       for (i = 0; i < 3; i++) {
+               net_values[i] = htonl(net_values[i]);
+       }
+
        for (i = 0; i < nr_iter; i++) {
                netint = htonl(i);
-               tracepoint(tp, tptest, i, netint, values, text, strlen(text), escape, dbl, flt);
+               tracepoint(tp, tptest, i, netint, values, text, strlen(text), escape, dbl, flt,
+                       net_values);
                usleep(nr_usec);
        }
 
index 68bbdc18cef8558020ac1e2151e3de9fa524a76f..2c45ee09e75170b0738bec630cb8d6a8d409f893 100755 (executable)
@@ -25,8 +25,8 @@ EVENT_NAME="bogus"
 ENABLE_EVENT_STDERR="/tmp/invalid-filters-stderr"
 TRACE_PATH=$(mktemp -d)
 NUM_GLOBAL_TESTS=2
-NUM_UST_TESTS=165
-NUM_KERNEL_TESTS=165
+NUM_UST_TESTS=144
+NUM_KERNEL_TESTS=144
 NUM_TESTS=$(($NUM_UST_TESTS+$NUM_KERNEL_TESTS+$NUM_GLOBAL_TESTS))
 
 source $TESTDIR/utils/utils.sh
@@ -103,9 +103,6 @@ INVALID_FILTERS=(
                "intfield-1"
                "intfield>>1"
                "intfield<<1"
-               "intfield&1"
-               "intfield|1"
-               "intfield^1"
                "~intfield"
                "1+11111-3333+1"
                "(1+2)*(55*666)"
@@ -120,9 +117,7 @@ INVALID_FILTERS=(
                '0 || ("abc" != "def")) && (3 < 4)'
                "a->"
                "a-->a"
-               "a->a"
                "a.b.c->d.e.f+1"
-               "asdfasdf->asdfasdf < 2"
                # String can\'t be root node
                "\"somestring\""
                # Unary op on string not allowed
@@ -135,9 +130,6 @@ INVALID_FILTERS=(
                # Logical operator with string type not allowed
                "\"somestring\" || 1"
                "1 || \"somestring\""
-               # Nesting of binary operator not allowed
-               "1 | (1 | (1 | 1))"
-               "1 > (1 > (1 > 1))"
                "\$ctx == 0"
                "0 == \$ctx"
                # Only \$ctx is supported for now
index 985f14e14d106299b894d4faa37f19b75b53d5e4..7395da0dd8043a9a679c5e6b827ba001982ef4e7 100755 (executable)
@@ -25,8 +25,8 @@ EVENT_NAME="bogus"
 ENABLE_EVENT_STDERR="/tmp/unsupported-ops-enable"
 TRACE_PATH=$(mktemp -d)
 NUM_GLOBAL_TESTS=2
-NUM_UST_TESTS=44
-NUM_KERNEL_TESTS=44
+NUM_UST_TESTS=32
+NUM_KERNEL_TESTS=32
 NUM_TESTS=$(($NUM_UST_TESTS+$NUM_KERNEL_TESTS+$NUM_GLOBAL_TESTS))
 
 source $TESTDIR/utils/utils.sh
@@ -94,9 +94,9 @@ print_test_banner "$TEST_DESC"
 
 # Unsupported operators
 OP_STR=("MUL" "DIV" "MOD" "PLUS" "MINUS" "LSHIFT" "RSHIFT"
-       "BIN_AND" "BIN_OR" "BIN_XOR" "UNARY_BIN_NOT")
+       "UNARY_BIN_NOT")
 
-OP_TKN=("*" "/" "%" "+" "-" "<<" ">>" "&" "|" "^" "~")
+OP_TKN=("*" "/" "%" "+" "-" "<<" ">>" "~")
 
 OP_COUNT=${#OP_STR[@]}
 
index a425a297259efc612acd3a47f97040dadada2237..a916b188441b8f97eaae026d085fc532227488d1 100755 (executable)
@@ -24,8 +24,8 @@ STATS_BIN="$TESTDIR/utils/babelstats.pl"
 SESSION_NAME="valid_filter"
 NR_ITER=100
 NUM_GLOBAL_TESTS=2
-NUM_UST_TESTS=906
-NUM_KERNEL_TESTS=840
+NUM_UST_TESTS=1002
+NUM_KERNEL_TESTS=936
 NUM_TESTS=$(($NUM_UST_TESTS+$NUM_KERNEL_TESTS+$NUM_GLOBAL_TESTS))
 
 source $TESTDIR/utils/utils.sh
@@ -643,6 +643,60 @@ UST_FILTERS=(
        intfield
        $issue_356_filter
 
+       true_statement
+       "1&1"
+
+       true_statement
+       "0|1"
+
+       true_statement
+       "0^1"
+
+       true_statement
+       "seqfield4[1]==2"
+
+       true_statement
+       "arrfield1[1]==2"
+
+       true_statement
+       "arrfield1[1]==2"
+
+       true_statement
+       "arrfield3[1]==2"
+
+       true_statement
+       "seqfield3[1]==2"
+
+       true_statement
+       "1 | (1 | (1 | 1))"
+
+       true_statement
+       "1 >= (1 >= (1 >= 1))"
+
+       true_statement
+       "0x101 & 0x100 == 0x100"
+
+       true_statement
+       "0x101 | 0x10100 == 0x10101"
+
+       true_statement
+       "0xF00F0F ^ 0xFF0F00 == 0x0F000F"
+
+       true_statement
+       "arrfield1[2] & 1 == 1"
+
+       true_statement
+       "arrfield1[2] | 0x111000 == 0x111003"
+
+       true_statement
+       "(arrfield1[0] | arrfield1[1] | arrfield1[2]) == 0x3"
+
+       true_statement
+       "seqfield4[2] & 1 == 1"
+
+       true_statement
+       "seqfield4[2] | 0x111000 == 0x111003"
+
        true_statement
        "intfield < 0xDEADBEEF"
 
@@ -736,12 +790,6 @@ UST_FILTERS=(
        has_no_event
        "0 == \$ctx.vtid.blah"
 
-       has_no_event
-       "\$ctx.44 == 0"
-
-       has_no_event
-       "0 == \$ctx.44"
-
        END
 )
 
@@ -1020,6 +1068,60 @@ KERNEL_FILTERS=(
        intfield
        $issue_356_filter
 
+       true_statement
+       "1&1"
+
+       true_statement
+       "0|1"
+
+       true_statement
+       "0^1"
+
+       true_statement
+       "seqfield4[1]==2"
+
+       true_statement
+       "arrfield1[1]==2"
+
+       true_statement
+       "arrfield1[1]==2"
+
+       true_statement
+       "arrfield3[1]==2"
+
+       true_statement
+       "seqfield3[1]==2"
+
+       true_statement
+       "1 | (1 | (1 | 1))"
+
+       true_statement
+       "1 >= (1 >= (1 >= 1))"
+
+       true_statement
+       "0x101 & 0x100 == 0x100"
+
+       true_statement
+       "0x101 | 0x10100 == 0x10101"
+
+       true_statement
+       "0xF00F0F ^ 0xFF0F00 == 0x0F000F"
+
+       true_statement
+       "arrfield1[2] & 1 == 1"
+
+       true_statement
+       "arrfield1[2] | 0x111000 == 0x111003"
+
+       true_statement
+       "(arrfield1[0] | arrfield1[1] | arrfield1[2]) == 0x3"
+
+       true_statement
+       "seqfield4[2] & 1 == 1"
+
+       true_statement
+       "seqfield4[2] | 0x111000 == 0x111003"
+
        true_statement
        "intfield < 0xDEADBEEF"
 
@@ -1113,12 +1215,6 @@ KERNEL_FILTERS=(
        has_no_event
        "0 == \$ctx.vtid.blah"
 
-       has_no_event
-       "\$ctx.44 == 0"
-
-       has_no_event
-       "0 == \$ctx.44"
-
        stringfield_has_events
        'stringfield == "test"'
 
index dde56afbb71f130c81f47f81d6ede2afd85e0feb..2872601893e72d4009a7270be97a5662156ff3b8 100644 (file)
@@ -22,7 +22,8 @@
 TRACEPOINT_EVENT(tp, tptest,
        TP_ARGS(int, anint, int, netint, long *, values,
                char *, text, size_t, textlen,
-               char *, etext, double, doublearg, float, floatarg),
+               char *, etext, double, doublearg, float, floatarg,
+               uint32_t *, net_values),
        TP_FIELDS(
                ctf_integer(int, intfield, anint)
                ctf_integer_hex(int, intfield2, anint)
@@ -31,8 +32,11 @@ TRACEPOINT_EVENT(tp, tptest,
                ctf_integer_network_hex(int, netintfieldhex, netint)
                ctf_array(long, arrfield1, values, 3)
                ctf_array_text(char, arrfield2, text, 10)
+               ctf_array_network(uint32_t, arrfield3, net_values, 3)
                ctf_sequence(char, seqfield1, text, size_t, textlen)
                ctf_sequence_text(char, seqfield2, text, size_t, textlen)
+               ctf_sequence_network(uint32_t, seqfield3, net_values, size_t, 3)
+               ctf_sequence(long, seqfield4, values, size_t, 3)
                ctf_string(stringfield, text)
                ctf_string(stringfield2, etext)
                ctf_float(float, floatfield, floatarg)
This page took 0.049342 seconds and 4 git commands to generate.