Librarify filter in liblttng-ctl and hide symbols
authorDavid Goulet <dgoulet@efficios.com>
Fri, 24 Aug 2012 19:13:34 +0000 (15:13 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Fri, 24 Aug 2012 19:16:14 +0000 (15:16 -0400)
Create the libfilter.la inside the liblttng-ctl directory so we can
statically link with lttng-ctl and the tests.

Also hide the dynamic symbol of libfilter used in liblttng-ctl.

Signed-off-by: David Goulet <dgoulet@efficios.com>
37 files changed:
.gitignore
configure.ac
src/lib/lttng-ctl/Makefile.am
src/lib/lttng-ctl/align.h [deleted file]
src/lib/lttng-ctl/bug.h [deleted file]
src/lib/lttng-ctl/filter-ast.h [deleted file]
src/lib/lttng-ctl/filter-bytecode.h [deleted file]
src/lib/lttng-ctl/filter-grammar-test.c [deleted file]
src/lib/lttng-ctl/filter-ir.h [deleted file]
src/lib/lttng-ctl/filter-lexer.l [deleted file]
src/lib/lttng-ctl/filter-parser.y [deleted file]
src/lib/lttng-ctl/filter-visitor-generate-bytecode.c [deleted file]
src/lib/lttng-ctl/filter-visitor-generate-ir.c [deleted file]
src/lib/lttng-ctl/filter-visitor-ir-check-binary-comparator.c [deleted file]
src/lib/lttng-ctl/filter-visitor-ir-check-binary-op-nesting.c [deleted file]
src/lib/lttng-ctl/filter-visitor-set-parent.c [deleted file]
src/lib/lttng-ctl/filter-visitor-xml.c [deleted file]
src/lib/lttng-ctl/filter/Makefile.am [new file with mode: 0644]
src/lib/lttng-ctl/filter/align.h [new file with mode: 0644]
src/lib/lttng-ctl/filter/bug.h [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-ast.h [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-bytecode.h [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-grammar-test.c [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-ir.h [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-lexer.l [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-parser.y [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-comparator.c [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-op-nesting.c [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-visitor-set-parent.c [new file with mode: 0644]
src/lib/lttng-ctl/filter/filter-visitor-xml.c [new file with mode: 0644]
src/lib/lttng-ctl/filter/memstream.h [new file with mode: 0644]
src/lib/lttng-ctl/filter/tests.txt [new file with mode: 0644]
src/lib/lttng-ctl/lttng-ctl.c
src/lib/lttng-ctl/memstream.h [deleted file]
src/lib/lttng-ctl/tests.txt [deleted file]

index 6d04272c4c962d43f10ce3ff7d959dfd8b27a810..2c1df01ac466726dc2096e55572690ae1ff61335 100644 (file)
@@ -36,11 +36,11 @@ src/bin/lttng/lttng
 src/bin/lttng-consumerd/lttng-consumerd
 src/bin/lttng-relayd/lttng-relayd
 
-src/lib/lttng-ctl/filter-grammar-test
-src/lib/lttng-ctl/filter-lexer.c
-src/lib/lttng-ctl/filter-parser.c
-src/lib/lttng-ctl/filter-parser.h
-src/lib/lttng-ctl/filter-parser.output
+src/lib/lttng-ctl/filter/filter-grammar-test
+src/lib/lttng-ctl/filter/filter-lexer.c
+src/lib/lttng-ctl/filter/filter-parser.c
+src/lib/lttng-ctl/filter/filter-parser.h
+src/lib/lttng-ctl/filter/filter-parser.output
 
 # Tests
 test_sessions
index 94f571be38b23d6d0de911f6af9464857a895787..1603d569a45f3bc64bef8e9c20e3b8e1a0f259f1 100644 (file)
@@ -237,6 +237,7 @@ AC_CONFIG_FILES([
        src/common/relayd/Makefile
        src/lib/Makefile
        src/lib/lttng-ctl/Makefile
+       src/lib/lttng-ctl/filter/Makefile
        src/bin/Makefile
        src/bin/lttng-consumerd/Makefile
        src/bin/lttng-sessiond/Makefile
index e00a880263adba798a93474b387b9f2cbd4f29b8..f1b4b500c27deedfd4018bd4b1eb348396c6a723 100644 (file)
@@ -1,28 +1,11 @@
-lib_LTLIBRARIES = liblttng-ctl.la
-noinst_PROGRAMS = filter-grammar-test
-
-BUILT_SOURCES = filter-parser.h
-AM_YFLAGS = -t -d -v
+SUBDIRS = filter
 
-noinst_HEADERS = filter-ast.h
-liblttng_ctl_la_SOURCES = lttng-ctl.c \
-       filter-lexer.l filter-parser.y \
-       filter-visitor-set-parent.c \
-       filter-visitor-xml.c \
-       filter-visitor-generate-ir.c \
-       filter-visitor-ir-check-binary-op-nesting.c \
-       filter-visitor-generate-bytecode.c \
-       align.h \
-       bug.h \
-       filter-ast.h \
-       filter-bytecode.h \
-       filter-ir.h \
-       memstream.h
+lib_LTLIBRARIES = liblttng-ctl.la
 
-filter_grammar_test_SOURCES = filter-grammar-test.c
-filter_grammar_test_LDADD = liblttng-ctl.la
+liblttng_ctl_la_SOURCES = lttng-ctl.c
 
 liblttng_ctl_la_LIBADD = \
                $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \
                $(top_builddir)/src/common/libcommon.la \
-               $(top_builddir)/src/common/hashtable/libhashtable.la
+               $(top_builddir)/src/common/hashtable/libhashtable.la \
+               $(top_builddir)/src/lib/lttng-ctl/filter/libfilter.la
diff --git a/src/lib/lttng-ctl/align.h b/src/lib/lttng-ctl/align.h
deleted file mode 100644 (file)
index fe32673..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef _LTTNG_ALIGN_H
-#define _LTTNG_ALIGN_H
-
-/*
- * align.h
- *
- * (C) Copyright 2010-2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- */
-
-#include "bug.h"
-#include <unistd.h>
-#include <limits.h>
-
-#ifndef PAGE_SIZE      /* Cygwin limits.h defines its own PAGE_SIZE */
-#define PAGE_SIZE              sysconf(_SC_PAGE_SIZE)
-#endif
-
-#define PAGE_MASK              (~(PAGE_SIZE - 1))
-#define __ALIGN_MASK(v, mask)  (((v) + (mask)) & ~(mask))
-#define ALIGN(v, align)                __ALIGN_MASK(v, (__typeof__(v)) (align) - 1)
-#define PAGE_ALIGN(addr)       ALIGN(addr, PAGE_SIZE)
-
-/**
- * offset_align - Calculate the offset needed to align an object on its natural
- *                alignment towards higher addresses.
- * @align_drift:  object offset from an "alignment"-aligned address.
- * @alignment:    natural object alignment. Must be non-zero, power of 2.
- *
- * Returns the offset that must be added to align towards higher
- * addresses.
- */
-#define offset_align(align_drift, alignment)                                  \
-       ({                                                                     \
-               LTTNG_BUILD_RUNTIME_BUG_ON((alignment) == 0                    \
-                                  || ((alignment) & ((alignment) - 1)));      \
-               (((alignment) - (align_drift)) & ((alignment) - 1));           \
-       })
-
-/**
- * offset_align_floor - Calculate the offset needed to align an object
- *                      on its natural alignment towards lower addresses.
- * @align_drift:  object offset from an "alignment"-aligned address.
- * @alignment:    natural object alignment. Must be non-zero, power of 2.
- *
- * Returns the offset that must be substracted to align towards lower addresses.
- */
-#define offset_align_floor(align_drift, alignment)                            \
-       ({                                                                     \
-               LTTNG_BUILD_RUNTIME_BUG_ON((alignment) == 0                    \
-                                  || ((alignment) & ((alignment) - 1)));      \
-               (((align_drift) - (alignment)) & ((alignment) - 1);            \
-       })
-
-#endif /* _LTTNG_ALIGN_H */
diff --git a/src/lib/lttng-ctl/bug.h b/src/lib/lttng-ctl/bug.h
deleted file mode 100644 (file)
index 9368c08..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef _LTTNG_BUG_H
-#define _LTTNG_BUG_H
-
-/*
- * lttng/bug.h
- *
- * (C) Copyright 2010-2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- */
-
-#include <urcu/compiler.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define LTTNG_BUG_ON(condition)                                                \
-       do {                                                            \
-               if (caa_unlikely(condition)) {                          \
-                       fprintf(stderr,                                 \
-                               "LTTng BUG in file %s, line %d.\n",     \
-                               __FILE__, __LINE__);                    \
-                       exit(EXIT_FAILURE);                             \
-               }                                                       \
-       } while (0)
-
-#define LTTNG_BUILD_BUG_ON(condition)                                  \
-       ((void) sizeof(char[-!!(condition)]))
-
-/**
- * LTTNG_BUILD_RUNTIME_BUG_ON - check condition at build (if constant) or runtime
- * @condition: the condition which should be false.
- *
- * If the condition is a constant and true, the compiler will generate a build
- * error. If the condition is not constant, a BUG will be triggered at runtime
- * if the condition is ever true. If the condition is constant and false, no
- * code is emitted.
- */
-#define LTTNG_BUILD_RUNTIME_BUG_ON(condition)                  \
-       do {                                                    \
-               if (__builtin_constant_p(condition))            \
-                       LTTNG_BUILD_BUG_ON(condition);          \
-               else                                            \
-                       LTTNG_BUG_ON(condition);                \
-       } while (0)
-
-#endif
diff --git a/src/lib/lttng-ctl/filter-ast.h b/src/lib/lttng-ctl/filter-ast.h
deleted file mode 100644 (file)
index 1767164..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef _FILTER_AST_H
-#define _FILTER_AST_H
-
-/*
- * filter-ast.h
- *
- * LTTng filter AST
- *
- * 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
- */
-
-/*
- * Note: filter-ast.h should be included before filter-parser.h.
- */
-
-#include <urcu/list.h>
-#include <stdint.h>
-
-#define printf_debug(fmt, args...)                                     \
-       do {                                                            \
-               if (filter_parser_debug)                                \
-                       fprintf(stdout, "[debug] " fmt, ## args);       \
-       } while (0)
-
-// the parameter name (of the reentrant 'yyparse' function)
-// data is a pointer to a 'SParserParam' structure
-//#define YYPARSE_PARAM        parser_ctx
-
-// the argument for the 'yylex' function
-#define YYLEX_PARAM    ((struct filter_parser_ctx *) parser_ctx)->scanner
-
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-extern int filter_parser_debug;
-
-struct filter_node;
-struct filter_parser;
-
-enum node_type {
-       NODE_UNKNOWN = 0,
-       NODE_ROOT,
-
-       NODE_EXPRESSION,
-       NODE_OP,
-       NODE_UNARY_OP,
-
-       NR_NODE_TYPES,
-};
-
-enum op_type {
-       AST_OP_UNKNOWN = 0,
-       AST_OP_MUL,
-       AST_OP_DIV,
-       AST_OP_MOD,
-       AST_OP_PLUS,
-       AST_OP_MINUS,
-       AST_OP_RSHIFT,
-       AST_OP_LSHIFT,
-       AST_OP_AND,
-       AST_OP_OR,
-       AST_OP_BIN_AND,
-       AST_OP_BIN_OR,
-       AST_OP_BIN_XOR,
-
-       AST_OP_EQ,
-       AST_OP_NE,
-       AST_OP_GT,
-       AST_OP_LT,
-       AST_OP_GE,
-       AST_OP_LE,
-};
-
-enum unary_op_type {
-       AST_UNARY_UNKNOWN = 0,
-       AST_UNARY_PLUS,
-       AST_UNARY_MINUS,
-       AST_UNARY_NOT,
-       AST_UNARY_BIN_NOT,
-};
-
-enum ast_link_type {
-       AST_LINK_UNKNOWN = 0,
-       AST_LINK_DOT,
-       AST_LINK_RARROW,
-};
-
-struct filter_node {
-       /*
-        * Parent node is only set on demand by specific visitor.
-        */
-       struct filter_node *parent;
-       struct cds_list_head gc;
-
-       enum node_type type;
-       union {
-               struct {
-               } unknown;
-               struct {
-                       struct filter_node *child;
-               } root;
-               struct {
-                       enum {
-                               AST_EXP_UNKNOWN = 0,
-                               AST_EXP_STRING,
-                               AST_EXP_CONSTANT,
-                               AST_EXP_FLOAT_CONSTANT,
-                               AST_EXP_IDENTIFIER,
-                               AST_EXP_NESTED,
-                       } type;
-                       enum ast_link_type post_op;     /* reverse */
-                       enum ast_link_type pre_op;      /* forward */
-                       union {
-                               char *string;
-                               uint64_t constant;
-                               double float_constant;
-                               char *identifier;
-                               /*
-                                * child can be nested.
-                                */
-                               struct filter_node *child;
-                       } u;
-                       /* linked dot/arrow chain */
-                       struct filter_node *prev;
-                       struct filter_node *next;
-               } expression;
-               struct {
-                       enum op_type type;
-                       struct filter_node *lchild;
-                       struct filter_node *rchild;
-               } op;
-               struct {
-                       enum unary_op_type type;
-                       struct filter_node *child;
-               } unary_op;
-       } u;
-};
-
-struct filter_ast {
-       struct filter_node root;
-       struct cds_list_head allocated_nodes;
-};
-
-const char *node_type(struct filter_node *node);
-
-struct ir_op;
-
-struct filter_parser_ctx {
-       yyscan_t scanner;
-       struct filter_ast *ast;
-       struct cds_list_head allocated_strings;
-       struct ir_op *ir_root;
-       struct lttng_filter_bytecode_alloc *bytecode;
-       struct lttng_filter_bytecode_alloc *bytecode_reloc;
-};
-
-struct filter_parser_ctx *filter_parser_ctx_alloc(FILE *input);
-void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx);
-int filter_parser_ctx_append_ast(struct filter_parser_ctx *parser_ctx);
-
-static inline
-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);
-void filter_ir_free(struct filter_parser_ctx *ctx);
-int filter_visitor_bytecode_generate(struct filter_parser_ctx *ctx);
-void filter_bytecode_free(struct filter_parser_ctx *ctx);
-int filter_visitor_ir_check_binary_op_nesting(struct filter_parser_ctx *ctx);
-int filter_visitor_ir_check_binary_comparator(struct filter_parser_ctx *ctx);
-
-#endif /* _FILTER_AST_H */
diff --git a/src/lib/lttng-ctl/filter-bytecode.h b/src/lib/lttng-ctl/filter-bytecode.h
deleted file mode 100644 (file)
index 7c76e32..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-#ifndef _FILTER_BYTECODE_H
-#define _FILTER_BYTECODE_H
-
-/*
- * filter-bytecode.h
- *
- * LTTng filter bytecode
- *
- * 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 "filter-ast.h"
-#include "../../common/sessiond-comm/sessiond-comm.h"
-
-/*
- * offsets are absolute from start of bytecode.
- */
-
-struct field_ref {
-       /* Initially, symbol offset. After link, field offset. */
-       uint16_t offset;
-} __attribute__((packed));
-
-struct literal_numeric {
-       int64_t v;
-} __attribute__((packed));
-
-struct literal_double {
-       double v;
-} __attribute__((packed));
-
-struct literal_string {
-       char string[0];
-} __attribute__((packed));
-
-enum filter_op {
-       FILTER_OP_UNKNOWN = 0,
-
-       FILTER_OP_RETURN,
-
-       /* binary */
-       FILTER_OP_MUL,
-       FILTER_OP_DIV,
-       FILTER_OP_MOD,
-       FILTER_OP_PLUS,
-       FILTER_OP_MINUS,
-       FILTER_OP_RSHIFT,
-       FILTER_OP_LSHIFT,
-       FILTER_OP_BIN_AND,
-       FILTER_OP_BIN_OR,
-       FILTER_OP_BIN_XOR,
-
-       /* binary comparators */
-       FILTER_OP_EQ,
-       FILTER_OP_NE,
-       FILTER_OP_GT,
-       FILTER_OP_LT,
-       FILTER_OP_GE,
-       FILTER_OP_LE,
-
-       /* string binary comparator */
-       FILTER_OP_EQ_STRING,
-       FILTER_OP_NE_STRING,
-       FILTER_OP_GT_STRING,
-       FILTER_OP_LT_STRING,
-       FILTER_OP_GE_STRING,
-       FILTER_OP_LE_STRING,
-
-       /* s64 binary comparator */
-       FILTER_OP_EQ_S64,
-       FILTER_OP_NE_S64,
-       FILTER_OP_GT_S64,
-       FILTER_OP_LT_S64,
-       FILTER_OP_GE_S64,
-       FILTER_OP_LE_S64,
-
-       /* double binary comparator */
-       FILTER_OP_EQ_DOUBLE,
-       FILTER_OP_NE_DOUBLE,
-       FILTER_OP_GT_DOUBLE,
-       FILTER_OP_LT_DOUBLE,
-       FILTER_OP_GE_DOUBLE,
-       FILTER_OP_LE_DOUBLE,
-
-       /* Mixed S64-double binary comparators */
-       FILTER_OP_EQ_DOUBLE_S64,
-       FILTER_OP_NE_DOUBLE_S64,
-       FILTER_OP_GT_DOUBLE_S64,
-       FILTER_OP_LT_DOUBLE_S64,
-       FILTER_OP_GE_DOUBLE_S64,
-       FILTER_OP_LE_DOUBLE_S64,
-
-       FILTER_OP_EQ_S64_DOUBLE,
-       FILTER_OP_NE_S64_DOUBLE,
-       FILTER_OP_GT_S64_DOUBLE,
-       FILTER_OP_LT_S64_DOUBLE,
-       FILTER_OP_GE_S64_DOUBLE,
-       FILTER_OP_LE_S64_DOUBLE,
-
-       /* unary */
-       FILTER_OP_UNARY_PLUS,
-       FILTER_OP_UNARY_MINUS,
-       FILTER_OP_UNARY_NOT,
-       FILTER_OP_UNARY_PLUS_S64,
-       FILTER_OP_UNARY_MINUS_S64,
-       FILTER_OP_UNARY_NOT_S64,
-       FILTER_OP_UNARY_PLUS_DOUBLE,
-       FILTER_OP_UNARY_MINUS_DOUBLE,
-       FILTER_OP_UNARY_NOT_DOUBLE,
-
-       /* logical */
-       FILTER_OP_AND,
-       FILTER_OP_OR,
-
-       /* load */
-       FILTER_OP_LOAD_FIELD_REF,
-       FILTER_OP_LOAD_FIELD_REF_STRING,
-       FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
-       FILTER_OP_LOAD_FIELD_REF_S64,
-       FILTER_OP_LOAD_FIELD_REF_DOUBLE,
-
-       FILTER_OP_LOAD_STRING,
-       FILTER_OP_LOAD_S64,
-       FILTER_OP_LOAD_DOUBLE,
-
-       /* cast */
-       FILTER_OP_CAST_TO_S64,
-       FILTER_OP_CAST_DOUBLE_TO_S64,
-       FILTER_OP_CAST_NOP,
-
-       NR_FILTER_OPS,
-};
-
-typedef uint8_t filter_opcode_t;
-
-struct load_op {
-       filter_opcode_t op;
-       char data[0];
-       /* data to load. Size known by enum filter_opcode and null-term char. */
-} __attribute__((packed));
-
-struct binary_op {
-       filter_opcode_t op;
-} __attribute__((packed));
-
-struct unary_op {
-       filter_opcode_t op;
-} __attribute__((packed));
-
-/* skip_offset is absolute from start of bytecode */
-struct logical_op {
-       filter_opcode_t op;
-       uint16_t skip_offset;   /* bytecode insn, if skip second test */
-} __attribute__((packed));
-
-struct cast_op {
-       filter_opcode_t op;
-} __attribute__((packed));
-
-struct return_op {
-       filter_opcode_t op;
-} __attribute__((packed));
-
-struct lttng_filter_bytecode_alloc {
-       uint16_t alloc_len;
-       struct lttng_filter_bytecode b;
-};
-
-static inline
-unsigned int bytecode_get_len(struct lttng_filter_bytecode *bytecode)
-{
-       return bytecode->len;
-}
-
-#endif /* _FILTER_BYTECODE_H */
diff --git a/src/lib/lttng-ctl/filter-grammar-test.c b/src/lib/lttng-ctl/filter-grammar-test.c
deleted file mode 100644 (file)
index 2b9a27d..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * filter-grammar-test.c
- *
- * LTTng filter grammar test
- *
- * 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 "filter-bytecode.h"
-
-int main(int argc, char **argv)
-{
-       struct filter_parser_ctx *ctx;
-       int ret;
-       int print_xml = 0, generate_ir = 0, generate_bytecode = 0;
-       int i;
-
-       for (i = 1; i < argc; i++) {
-               if (strcmp(argv[i], "-p") == 0)
-                       print_xml = 1;
-               else if (strcmp(argv[i], "-i") == 0)
-                       generate_ir = 1;
-               else if (strcmp(argv[i], "-b") == 0)
-                       generate_bytecode = 1;
-               else if (strcmp(argv[i], "-d") == 0)
-                       filter_parser_debug = 1;
-       }
-
-       ctx = filter_parser_ctx_alloc(stdin);
-       if (!ctx) {
-               fprintf(stderr, "Error allocating parser\n");
-               goto alloc_error;
-       }
-       ret = filter_parser_ctx_append_ast(ctx);
-       if (ret) {
-               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) {
-                       fflush(stdout);
-                       fprintf(stderr, "XML print error\n");
-                       goto parse_error;
-               }
-       }
-       if (generate_ir) {
-               printf("Generating IR... ");
-               fflush(stdout);
-               ret = filter_visitor_ir_generate(ctx);
-               if (ret) {
-                       fprintf(stderr, "Generate IR error\n");
-                       goto parse_error;
-               }
-               printf("done\n");
-
-               printf("Validating IR... ");
-               fflush(stdout);
-               ret = filter_visitor_ir_check_binary_op_nesting(ctx);
-               if (ret) {
-                       goto parse_error;
-               }
-               printf("done\n");
-       }
-       if (generate_bytecode) {
-               printf("Generating bytecode... ");
-               fflush(stdout);
-               ret = filter_visitor_bytecode_generate(ctx);
-               if (ret) {
-                       fprintf(stderr, "Generate bytecode error\n");
-                       goto parse_error;
-               }
-               printf("done\n");
-               printf("Size of bytecode generated: %u bytes.\n",
-                       bytecode_get_len(&ctx->bytecode->b));
-       }
-#if 0
-       if (run_bytecode) {
-               int64_t retval;
-
-               printf("Interpreting bytecode... ");
-               fflush(stdout);
-               ret = bytecode_interpret(&ctx->bytecode->b, &retval, NULL);
-               if (ret) {
-                       fprintf(stderr, "Error interpreting bytecode\n");
-                       goto parse_error;
-               } else {
-                       printf("Bytecode interpret result: %" PRIi64 "\n",
-                               retval);
-               }
-               printf("done\n");
-       }
-#endif //0
-
-       filter_bytecode_free(ctx);
-       filter_ir_free(ctx);
-       filter_parser_ctx_free(ctx);
-       return 0;
-
-parse_error:
-       filter_bytecode_free(ctx);
-       filter_ir_free(ctx);
-       filter_parser_ctx_free(ctx);
-alloc_error:
-       exit(EXIT_FAILURE);
-}
diff --git a/src/lib/lttng-ctl/filter-ir.h b/src/lib/lttng-ctl/filter-ir.h
deleted file mode 100644 (file)
index 39ac76c..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef _FILTER_IR_H
-#define _FILTER_IR_H
-
-/*
- * filter-ir.h
- *
- * LTTng filter ir
- *
- * 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 "filter-ast.h"
-
-enum ir_op_signedness {
-       IR_SIGN_UNKNOWN = 0,
-       IR_SIGNED,
-       IR_UNSIGNED,
-       IR_SIGN_DYN,            /* signedness determined dynamically */
-};
-
-enum ir_data_type {
-       IR_DATA_UNKNOWN = 0,
-       IR_DATA_STRING,
-       IR_DATA_NUMERIC,        /* numeric and boolean */
-       IR_DATA_FLOAT,
-       IR_DATA_FIELD_REF,
-};
-
-enum ir_op_type {
-       IR_OP_UNKNOWN = 0,
-       IR_OP_ROOT,
-       IR_OP_LOAD,
-       IR_OP_UNARY,
-       IR_OP_BINARY,
-       IR_OP_LOGICAL,
-};
-
-/* left or right child */
-enum ir_side {
-       IR_SIDE_UNKNOWN = 0,
-       IR_LEFT,
-       IR_RIGHT,
-};
-
-struct ir_op_root {
-       struct ir_op *child;
-};
-
-struct ir_op_load {
-       union {
-               char *string;
-               int64_t num;
-               double flt;
-               char *ref;
-       } u;
-};
-
-struct ir_op_unary {
-       enum unary_op_type type;
-       struct ir_op *child;
-};
-
-struct ir_op_binary {
-       enum op_type type;
-       struct ir_op *left;
-       struct ir_op *right;
-};
-
-struct ir_op_logical {
-       enum op_type type;
-       struct ir_op *left;
-       struct ir_op *right;
-};
-
-struct ir_op {
-       /* common to all ops */
-       enum ir_op_type op;
-       enum ir_data_type data_type;
-       enum ir_op_signedness signedness;
-       enum ir_side side;
-
-       union {
-               struct ir_op_root root;
-               struct ir_op_load load;
-               struct ir_op_unary unary;
-               struct ir_op_binary binary;
-               struct ir_op_logical logical;
-       } u;
-};
-
-#endif /* _FILTER_IR_H */
diff --git a/src/lib/lttng-ctl/filter-lexer.l b/src/lib/lttng-ctl/filter-lexer.l
deleted file mode 100644 (file)
index de74e7a..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-%{
-/*
- * filter-lexer.l
- *
- * LTTng filter lexer
- *
- * 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.
- */
-
-#include <stdio.h>
-#include "filter-ast.h"
-#include "filter-parser.h"
-
-extern
-void setstring(struct filter_parser_ctx *parser_ctx, YYSTYPE *lvalp, const char *src);
-
-static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
-       __attribute__((unused));
-static int input (yyscan_t yyscanner) __attribute__((unused));
-
-%}
-
-%x comment_ml comment_sl string_lit char_const
-%option reentrant yylineno noyywrap bison-bridge
-%option extra-type="struct filter_parser_ctx *"
-       /* bison-locations */
-
-D                              [0-9]
-L                              [a-zA-Z_]
-H                              [a-fA-F0-9]
-E                              ([Ee][+-]?{D}+)
-P                              ([Pp][+-]?{D}+)
-FS                             (f|F|l|L)
-IS                             ((u|U)|(u|U)?(l|L|ll|LL)|(l|L|ll|LL)(u|U))
-
-INTEGER_SUFFIX                 [ \n\t]*(U|UL|ULL|LU|LLU|Ul|Ull|lU|llU|u|uL|uLL|Lu|LLu|ul|ull|lu|llu)
-DIGIT                          [0-9]
-NONDIGIT                       [a-zA-Z_]
-HEXDIGIT                       [0-9A-Fa-f]
-OCTALDIGIT                     [0-7]
-UCHARLOWERCASE                 \\u{HEXDIGIT}{4}
-UCHARUPPERCASE                 \\U{HEXDIGIT}{8}
-ID_NONDIGIT                    {NONDIGIT}|{UCHARLOWERCASE}|{UCHARUPPERCASE}
-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}+)
-%%
-
-                               /*
-                                * Using start conditions to deal with comments
-                                * and strings.
-                                */ 
-
-"/*"                           BEGIN(comment_ml);
-<comment_ml>[^*\n]*            /* eat anything that's not a '*' */
-<comment_ml>"*"+[^*/\n]*       /* eat up '*'s not followed by '/'s */
-<comment_ml>\n                 ++yylineno;
-<comment_ml>"*"+"/"            BEGIN(INITIAL);
-
-"//"                           BEGIN(comment_sl);
-<comment_sl>[^\n]*\n           ++yylineno; BEGIN(INITIAL);
-
-L\'                            BEGIN(char_const); return CHARACTER_CONSTANT_START;
-\'                             BEGIN(char_const); return CHARACTER_CONSTANT_START;
-<char_const>\'                 BEGIN(INITIAL); return SQUOTE;
-
-L\"                            BEGIN(string_lit); return STRING_LITERAL_START;
-\"                             BEGIN(string_lit); return STRING_LITERAL_START;
-<string_lit>\"                 BEGIN(INITIAL); return DQUOTE;
-
-<char_const,string_lit>ESCSEQ  return ESCSEQ;
-<char_const,string_lit>\n      ; /* ignore */
-<char_const,string_lit>.       setstring(yyextra, yylval, yytext); return CHAR_STRING_TOKEN;
-
-
-0[xX]{H}+{IS}?                 setstring(yyextra, yylval, yytext); return HEXADECIMAL_CONSTANT;
-0[0-7]*{IS}?                   setstring(yyextra, yylval, yytext); return OCTAL_CONSTANT;
-[1-9]{D}*{IS}?                 setstring(yyextra, yylval, yytext); return DECIMAL_CONSTANT;
-
-{D}+{E}{FS}?                   setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
-{D}*"."{D}+{E}?{FS}?           setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
-{D}+"."{D}*{E}?{FS}?           setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
-0[xX]{H}+{P}{FS}?              setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
-0[xX]{H}*"."{H}+{P}?{FS}?      setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
-0[xX]{H}+"."{H}*{P}?{FS}?      setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
-
-"["                            return LSBRAC;
-"]"                            return RSBRAC;
-"("                            return LPAREN;
-")"                            return RPAREN;
-"{"                            return LBRAC;
-"}"                            return RBRAC;
-"->"                           return RARROW;
-
-"*"                            return STAR;
-"+"                            return PLUS;
-"-"                            return MINUS;
-
-"%"                            return MOD_OP;
-"/"                            return DIV_OP;
-">>"                           return RIGHT_OP;
-"<<"                           return LEFT_OP;
-
-"=="                           return EQ_OP;
-"!="                           return NE_OP;
-"<="                           return LE_OP;
-">="                           return GE_OP;
-"<"                            return LT_OP;
-">"                            return GT_OP;
-"&&"                           return AND_OP;
-"||"                           return OR_OP;
-"!"                            return NOT_OP;
-
-":="                           return ASSIGN;
-":"                            return COLON;
-";"                            return SEMICOLON;
-"..."                          return DOTDOTDOT;
-"."                            return DOT;
-"="                            return EQUAL;
-","                            return COMMA;
-"^"                            return XOR_BIN;
-"&"                            return AND_BIN;
-"|"                            return OR_BIN;
-"~"                            return NOT_BIN;
-{IDENTIFIER}                   printf_debug("<IDENTIFIER %s>\n", yytext); setstring(yyextra, yylval, yytext); return IDENTIFIER;
-[ \t\n]+                       ; /* ignore */
-.                              return ERROR;
-%%
diff --git a/src/lib/lttng-ctl/filter-parser.y b/src/lib/lttng-ctl/filter-parser.y
deleted file mode 100644 (file)
index d3be4be..0000000
+++ /dev/null
@@ -1,623 +0,0 @@
-%{
-/*
- * filter-parser.y
- *
- * LTTng filter expression parser
- *
- * 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
- *
- * Grammar inspired from http://www.quut.com/c/ANSI-C-grammar-y.html
- */
-
-#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"
-
-__attribute__((visibility("hidden")))
-int yydebug;
-int filter_parser_debug = 0;
-
-__attribute__((visibility("hidden")))
-int yyparse(struct filter_parser_ctx *parser_ctx);
-__attribute__((visibility("hidden")))
-int yylex(union YYSTYPE *yyval, struct filter_parser_ctx *parser_ctx);
-__attribute__((visibility("hidden")))
-int yylex_init_extra(struct filter_parser_ctx *parser_ctx, yyscan_t * ptr_yy_globals);
-__attribute__((visibility("hidden")))
-int yylex_destroy(yyscan_t yyparser_ctx);
-__attribute__((visibility("hidden")))
-void yyrestart(FILE * in_str, yyscan_t parser_ctx);
-
-struct gc_string {
-       struct cds_list_head gc;
-       size_t alloclen;
-       char s[];
-};
-
-static const char *node_type_to_str[] = {
-       [ NODE_UNKNOWN ] = "NODE_UNKNOWN",
-       [ NODE_ROOT ] = "NODE_ROOT",
-       [ NODE_EXPRESSION ] = "NODE_EXPRESSION",
-       [ NODE_OP ] = "NODE_OP",
-       [ NODE_UNARY_OP ] = "NODE_UNARY_OP",
-};
-
-__attribute__((visibility("hidden")))
-const char *node_type(struct filter_node *node)
-{
-       if (node->type < NR_NODE_TYPES)
-               return node_type_to_str[node->type];
-       else
-               return NULL;
-}
-
-static struct gc_string *gc_string_alloc(struct filter_parser_ctx *parser_ctx,
-                                        size_t len)
-{
-       struct gc_string *gstr;
-       size_t alloclen;
-
-       /* TODO: could be faster with find first bit or glib Gstring */
-       /* sizeof long to account for malloc header (int or long ?) */
-       for (alloclen = 8; alloclen < sizeof(long) + sizeof(*gstr) + len;
-            alloclen *= 2);
-
-       gstr = malloc(alloclen);
-       cds_list_add(&gstr->gc, &parser_ctx->allocated_strings);
-       gstr->alloclen = alloclen;
-       return gstr;
-}
-
-/*
- * note: never use gc_string_append on a string that has external references.
- * gsrc will be garbage collected immediately, and gstr might be.
- * Should only be used to append characters to a string literal or constant.
- */
-__attribute__((visibility("hidden")))
-struct gc_string *gc_string_append(struct filter_parser_ctx *parser_ctx,
-                                  struct gc_string *gstr,
-                                  struct gc_string *gsrc)
-{
-       size_t newlen = strlen(gsrc->s) + strlen(gstr->s) + 1;
-       size_t alloclen;
-
-       /* TODO: could be faster with find first bit or glib Gstring */
-       /* sizeof long to account for malloc header (int or long ?) */
-       for (alloclen = 8; alloclen < sizeof(long) + sizeof(*gstr) + newlen;
-            alloclen *= 2);
-
-       if (alloclen > gstr->alloclen) {
-               struct gc_string *newgstr;
-
-               newgstr = gc_string_alloc(parser_ctx, newlen);
-               strcpy(newgstr->s, gstr->s);
-               strcat(newgstr->s, gsrc->s);
-               cds_list_del(&gstr->gc);
-               free(gstr);
-               gstr = newgstr;
-       } else {
-               strcat(gstr->s, gsrc->s);
-       }
-       cds_list_del(&gsrc->gc);
-       free(gsrc);
-       return gstr;
-}
-
-__attribute__((visibility("hidden")))
-void setstring(struct filter_parser_ctx *parser_ctx, YYSTYPE *lvalp, const char *src)
-{
-       lvalp->gs = gc_string_alloc(parser_ctx, strlen(src) + 1);
-       strcpy(lvalp->gs->s, src);
-}
-
-static struct filter_node *make_node(struct filter_parser_ctx *scanner,
-                                 enum node_type type)
-{
-       struct filter_ast *ast = filter_parser_get_ast(scanner);
-       struct filter_node *node;
-
-       node = malloc(sizeof(*node));
-       if (!node)
-               return NULL;
-       memset(node, 0, sizeof(*node));
-       node->type = type;
-       cds_list_add(&node->gc, &ast->allocated_nodes);
-
-       switch (type) {
-       case NODE_ROOT:
-               fprintf(stderr, "[error] %s: trying to create root node\n", __func__);
-               break;
-
-       case NODE_EXPRESSION:
-               break;
-       case NODE_OP:
-               break;
-       case NODE_UNARY_OP:
-               break;
-
-       case NODE_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) type);
-               break;
-       }
-
-       return node;
-}
-
-static struct filter_node *make_op_node(struct filter_parser_ctx *scanner,
-                       enum op_type type,
-                       struct filter_node *lchild,
-                       struct filter_node *rchild)
-{
-       struct filter_ast *ast = filter_parser_get_ast(scanner);
-       struct filter_node *node;
-
-       node = malloc(sizeof(*node));
-       if (!node)
-               return NULL;
-       memset(node, 0, sizeof(*node));
-       node->type = NODE_OP;
-       cds_list_add(&node->gc, &ast->allocated_nodes);
-       node->u.op.type = type;
-       node->u.op.lchild = lchild;
-       node->u.op.rchild = rchild;
-       return node;
-}
-
-__attribute__((visibility("hidden")))
-void yyerror(struct filter_parser_ctx *parser_ctx, const char *str)
-{
-       fprintf(stderr, "error %s\n", str);
-}
-__attribute__((visibility("hidden")))
-int yywrap(void)
-{
-       return 1;
-} 
-
-#define parse_error(parser_ctx, str)                           \
-do {                                                           \
-       yyerror(parser_ctx, YY_("parse error: " str "\n"));     \
-       YYERROR;                                                \
-} while (0)
-
-static void free_strings(struct cds_list_head *list)
-{
-       struct gc_string *gstr, *tmp;
-
-       cds_list_for_each_entry_safe(gstr, tmp, list, gc)
-               free(gstr);
-}
-
-static struct filter_ast *filter_ast_alloc(void)
-{
-       struct filter_ast *ast;
-
-       ast = malloc(sizeof(*ast));
-       if (!ast)
-               return NULL;
-       memset(ast, 0, sizeof(*ast));
-       CDS_INIT_LIST_HEAD(&ast->allocated_nodes);
-       ast->root.type = NODE_ROOT;
-       return ast;
-}
-
-static void filter_ast_free(struct filter_ast *ast)
-{
-       struct filter_node *node, *tmp;
-
-       cds_list_for_each_entry_safe(node, tmp, &ast->allocated_nodes, gc)
-               free(node);
-}
-
-int filter_parser_ctx_append_ast(struct filter_parser_ctx *parser_ctx)
-{
-       return yyparse(parser_ctx);
-}
-
-struct filter_parser_ctx *filter_parser_ctx_alloc(FILE *input)
-{
-       struct filter_parser_ctx *parser_ctx;
-       int ret;
-
-       yydebug = filter_parser_debug;
-
-       parser_ctx = malloc(sizeof(*parser_ctx));
-       if (!parser_ctx)
-               return NULL;
-       memset(parser_ctx, 0, sizeof(*parser_ctx));
-
-       ret = yylex_init_extra(parser_ctx, &parser_ctx->scanner);
-       if (ret) {
-               fprintf(stderr, "yylex_init error\n");
-               goto cleanup_parser_ctx;
-       }
-       /* Start processing new stream */
-       yyrestart(input, parser_ctx->scanner);
-
-       parser_ctx->ast = filter_ast_alloc();
-       if (!parser_ctx->ast)
-               goto cleanup_lexer;
-       CDS_INIT_LIST_HEAD(&parser_ctx->allocated_strings);
-
-       if (yydebug)
-               fprintf(stdout, "parser_ctx input is a%s.\n",
-                       isatty(fileno(input)) ? "n interactive tty" :
-                                               " noninteractive file");
-
-       return parser_ctx;
-
-cleanup_lexer:
-       ret = yylex_destroy(parser_ctx->scanner);
-       if (!ret)
-               fprintf(stderr, "yylex_destroy error\n");
-cleanup_parser_ctx:
-       free(parser_ctx);
-       return NULL;
-}
-
-void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx)
-{
-       int ret;
-
-       free_strings(&parser_ctx->allocated_strings);
-       filter_ast_free(parser_ctx->ast);
-       ret = yylex_destroy(parser_ctx->scanner);
-       if (ret)
-               fprintf(stderr, "yylex_destroy error\n");
-       free(parser_ctx);
-}
-
-%}
-
-%define api.pure
-       /* %locations */
-%parse-param {struct filter_parser_ctx *parser_ctx}
-%lex-param {struct filter_parser_ctx *parser_ctx}
-%start translation_unit
-%token CHARACTER_CONSTANT_START SQUOTE STRING_LITERAL_START DQUOTE
-%token ESCSEQ CHAR_STRING_TOKEN
-%token DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT FLOAT_CONSTANT
-%token LSBRAC RSBRAC LPAREN RPAREN LBRAC RBRAC RARROW
-%token STAR PLUS MINUS
-%token MOD_OP DIV_OP RIGHT_OP LEFT_OP
-%token EQ_OP NE_OP LE_OP GE_OP LT_OP GT_OP AND_OP OR_OP NOT_OP
-%token ASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA
-%token XOR_BIN AND_BIN OR_BIN NOT_BIN
-
-%token <gs> IDENTIFIER
-%token ERROR
-%union
-{
-       long long ll;
-       char c;
-       struct gc_string *gs;
-       struct filter_node *n;
-}
-
-%type <gs> s_char s_char_sequence c_char c_char_sequence
-
-%type <n> primary_expression
-%type <n> postfix_expression
-%type <n> unary_expression
-%type <n> unary_operator
-%type <n> multiplicative_expression
-%type <n> additive_expression
-%type <n> shift_expression
-%type <n> relational_expression
-%type <n> equality_expression
-%type <n> and_expression
-%type <n> exclusive_or_expression
-%type <n> inclusive_or_expression
-%type <n> logical_and_expression
-%type <n> logical_or_expression
-%type <n> expression
-
-%%
-
-
-/* 1.5 Constants */
-
-c_char_sequence:
-               c_char
-               {       $$ = $1;                                        }
-       |       c_char_sequence c_char
-               {       $$ = gc_string_append(parser_ctx, $1, $2);              }
-       ;
-
-c_char:
-               CHAR_STRING_TOKEN
-               {       $$ = yylval.gs;                                 }
-       |       ESCSEQ
-               {
-                       parse_error(parser_ctx, "escape sequences not supported yet");
-               }
-       ;
-
-/* 1.6 String literals */
-
-s_char_sequence:
-               s_char
-               {       $$ = $1;                                        }
-       |       s_char_sequence s_char
-               {       $$ = gc_string_append(parser_ctx, $1, $2);              }
-       ;
-
-s_char:
-               CHAR_STRING_TOKEN
-               {       $$ = yylval.gs;                                 }
-       |       ESCSEQ
-               {
-                       parse_error(parser_ctx, "escape sequences not supported yet");
-               }
-       ;
-
-primary_expression
-       :       IDENTIFIER
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_IDENTIFIER;
-                       $$->u.expression.u.identifier = yylval.gs->s;
-               }
-       |       DECIMAL_CONSTANT
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_CONSTANT;
-                       sscanf(yylval.gs->s, "%" PRIu64,
-                              &$$->u.expression.u.constant);
-               }
-       |       OCTAL_CONSTANT
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_CONSTANT;
-                       sscanf(yylval.gs->s, "0%" PRIo64,
-                              &$$->u.expression.u.constant);
-               }
-       |       HEXADECIMAL_CONSTANT
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_CONSTANT;
-                       sscanf(yylval.gs->s, "0x%" PRIx64,
-                              &$$->u.expression.u.constant);
-               }
-       |       FLOAT_CONSTANT
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_FLOAT_CONSTANT;
-                       sscanf(yylval.gs->s, "%lg",
-                              &$$->u.expression.u.float_constant);
-               }
-       |       STRING_LITERAL_START DQUOTE
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_STRING;
-                       $$->u.expression.u.string = "";
-               }
-       |       STRING_LITERAL_START s_char_sequence DQUOTE
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_STRING;
-                       $$->u.expression.u.string = $2->s;
-               }
-       |       CHARACTER_CONSTANT_START c_char_sequence SQUOTE
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_STRING;
-                       $$->u.expression.u.string = $2->s;
-               }
-       |       LPAREN expression RPAREN
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_NESTED;
-                       $$->u.expression.u.child = $2;
-               }
-       ;
-
-postfix_expression
-       : primary_expression
-               {       $$ = $1;                                        }
-       | postfix_expression DOT IDENTIFIER
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_IDENTIFIER;
-                       $$->u.expression.post_op = AST_LINK_DOT;
-                       $$->u.expression.u.identifier = $3->s;
-                       $$->u.expression.prev = $1;
-               }
-       | postfix_expression RARROW IDENTIFIER
-               {
-                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
-                       $$->u.expression.type = AST_EXP_IDENTIFIER;
-                       $$->u.expression.post_op = AST_LINK_RARROW;
-                       $$->u.expression.u.identifier = $3->s;
-                       $$->u.expression.prev = $1;
-               }
-       ;
-
-unary_expression
-       : postfix_expression
-               {       $$ = $1;                                        }
-       | unary_operator unary_expression
-               {
-                       $$ = $1;
-                       $$->u.unary_op.child = $2;
-               }
-       ;
-
-unary_operator
-       : PLUS
-               {
-                       $$ = make_node(parser_ctx, NODE_UNARY_OP);
-                       $$->u.unary_op.type = AST_UNARY_PLUS;
-               }
-       | MINUS
-               {
-                       $$ = make_node(parser_ctx, NODE_UNARY_OP);
-                       $$->u.unary_op.type = AST_UNARY_MINUS;
-               }
-       | NOT_OP
-               {
-                       $$ = make_node(parser_ctx, NODE_UNARY_OP);
-                       $$->u.unary_op.type = AST_UNARY_NOT;
-               }
-       | NOT_BIN
-               {
-                       $$ = make_node(parser_ctx, NODE_UNARY_OP);
-                       $$->u.unary_op.type = AST_UNARY_BIN_NOT;
-               }
-       ;
-
-multiplicative_expression
-       : unary_expression
-               {       $$ = $1;                                        }
-       | multiplicative_expression STAR unary_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_MUL, $1, $3);
-               }
-       | multiplicative_expression DIV_OP unary_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_DIV, $1, $3);
-               }
-       | multiplicative_expression MOD_OP unary_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_MOD, $1, $3);
-               }
-       ;
-
-additive_expression
-       : multiplicative_expression
-               {       $$ = $1;                                        }
-       | additive_expression PLUS multiplicative_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_PLUS, $1, $3);
-               }
-       | additive_expression MINUS multiplicative_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_MINUS, $1, $3);
-               }
-       ;
-
-shift_expression
-       : additive_expression
-               {       $$ = $1;                                        }
-       | shift_expression LEFT_OP additive_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_LSHIFT, $1, $3);
-               }
-       | shift_expression RIGHT_OP additive_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_RSHIFT, $1, $3);
-               }
-       ;
-
-relational_expression
-       : shift_expression
-               {       $$ = $1;                                        }
-       | relational_expression LT_OP shift_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_LT, $1, $3);
-               }
-       | relational_expression GT_OP shift_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_GT, $1, $3);
-               }
-       | relational_expression LE_OP shift_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_LE, $1, $3);
-               }
-       | relational_expression GE_OP shift_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_GE, $1, $3);
-               }
-       ;
-
-equality_expression
-       : relational_expression
-               {       $$ = $1;                                        }
-       | equality_expression EQ_OP relational_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_EQ, $1, $3);
-               }
-       | equality_expression NE_OP relational_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_NE, $1, $3);
-               }
-       ;
-
-and_expression
-       : equality_expression
-               {       $$ = $1;                                        }
-       | and_expression AND_BIN equality_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_BIN_AND, $1, $3);
-               }
-       ;
-
-exclusive_or_expression
-       : and_expression
-               {       $$ = $1;                                        }
-       | exclusive_or_expression XOR_BIN and_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_BIN_XOR, $1, $3);
-               }
-       ;
-
-inclusive_or_expression
-       : exclusive_or_expression
-               {       $$ = $1;                                        }
-       | inclusive_or_expression OR_BIN exclusive_or_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_BIN_OR, $1, $3);
-               }
-       ;
-
-logical_and_expression
-       : inclusive_or_expression
-               {       $$ = $1;                                        }
-       | logical_and_expression AND_OP inclusive_or_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_AND, $1, $3);
-               }
-       ;
-
-logical_or_expression
-       : logical_and_expression
-               {       $$ = $1;                                        }
-       | logical_or_expression OR_OP logical_and_expression
-               {
-                       $$ = make_op_node(parser_ctx, AST_OP_OR, $1, $3);
-               }
-       ;
-
-expression
-       : logical_or_expression
-               {       $$ = $1;                                        }
-       ;
-
-translation_unit
-       : expression
-               {
-                       parser_ctx->ast->root.u.root.child = $1;
-               }
-       ;
diff --git a/src/lib/lttng-ctl/filter-visitor-generate-bytecode.c b/src/lib/lttng-ctl/filter-visitor-generate-bytecode.c
deleted file mode 100644 (file)
index 9877a86..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * filter-visitor-generate-bytecode.c
- *
- * LTTng filter bytecode generation
- *
- * 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 <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include "align.h"
-#include "filter-bytecode.h"
-#include "filter-ir.h"
-#include "filter-ast.h"
-
-#ifndef max_t
-#define max_t(type, a, b)      ((type) ((a) > (b) ? (a) : (b)))
-#endif
-
-//#define INIT_ALLOC_SIZE              PAGE_SIZE
-#define INIT_ALLOC_SIZE                4
-
-static
-int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx,
-               struct ir_op *node);
-
-static
-int bytecode_init(struct lttng_filter_bytecode_alloc **fb)
-{
-       *fb = calloc(sizeof(struct lttng_filter_bytecode_alloc) + INIT_ALLOC_SIZE, 1);
-       if (!*fb) {
-               return -ENOMEM;
-       } else {
-               (*fb)->alloc_len = INIT_ALLOC_SIZE;
-               return 0;
-       }
-}
-
-static
-int32_t bytecode_reserve(struct lttng_filter_bytecode_alloc **fb, uint32_t align, uint32_t len)
-{
-       int32_t ret;
-       uint32_t padding = offset_align((*fb)->b.len, align);
-
-       if ((*fb)->b.len + padding + len > (*fb)->alloc_len) {
-               uint32_t new_len =
-                       max_t(uint32_t, (*fb)->b.len + padding + len,
-                               (*fb)->alloc_len << 1);
-               uint32_t old_len = (*fb)->alloc_len;
-
-               if (new_len > 0xFFFF)
-                       return -EINVAL;
-               *fb = realloc(*fb, sizeof(struct lttng_filter_bytecode_alloc) + new_len);
-               if (!*fb)
-                       return -ENOMEM;
-               memset(&(*fb)->b.data[old_len], 0, new_len - old_len);
-               (*fb)->alloc_len = new_len;
-       }
-       (*fb)->b.len += padding;
-       ret = (*fb)->b.len;
-       (*fb)->b.len += len;
-       return ret;
-}
-
-static
-int bytecode_push(struct lttng_filter_bytecode_alloc **fb, const void *data,
-               uint32_t align, uint32_t len)
-{
-       int32_t offset;
-
-       offset = bytecode_reserve(fb, align, len);
-       if (offset < 0)
-               return offset;
-       memcpy(&(*fb)->b.data[offset], data, len);
-       return 0;
-}
-
-static
-int bytecode_push_logical(struct lttng_filter_bytecode_alloc **fb,
-               struct logical_op *data,
-               uint32_t align, uint32_t len,
-               uint16_t *skip_offset)
-{
-       int32_t offset;
-
-       offset = bytecode_reserve(fb, align, len);
-       if (offset < 0)
-               return offset;
-       memcpy(&(*fb)->b.data[offset], data, len);
-       *skip_offset =
-               (void *) &((struct logical_op *) &(*fb)->b.data[offset])->skip_offset
-                       - (void *) &(*fb)->b.data[0];
-       return 0;
-}
-
-static
-int bytecode_patch(struct lttng_filter_bytecode_alloc **fb,
-               const void *data,
-               uint16_t offset,
-               uint32_t len)
-{
-       if (offset >= (*fb)->b.len) {
-               return -EINVAL;
-       }
-       memcpy(&(*fb)->b.data[offset], data, len);
-       return 0;
-}
-
-static
-int visit_node_root(struct filter_parser_ctx *ctx, struct ir_op *node)
-{
-       int ret;
-       struct return_op insn;
-
-       /* Visit child */
-       ret = recursive_visit_gen_bytecode(ctx, node->u.root.child);
-       if (ret)
-               return ret;
-
-       /* Generate end of bytecode instruction */
-       insn.op = FILTER_OP_RETURN;
-       return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
-}
-
-static
-int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
-{
-       int ret;
-
-       switch (node->data_type) {
-       case IR_DATA_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] Unknown data type in %s\n",
-                       __func__);
-               return -EINVAL;
-
-       case IR_DATA_STRING:
-       {
-               struct load_op *insn;
-               uint32_t insn_len = sizeof(struct load_op)
-                       + strlen(node->u.load.u.string) + 1;
-
-               insn = calloc(insn_len, 1);
-               if (!insn)
-                       return -ENOMEM;
-               insn->op = FILTER_OP_LOAD_STRING;
-               strcpy(insn->data, node->u.load.u.string);
-               ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
-               free(insn);
-               return ret;
-       }
-       case IR_DATA_NUMERIC:
-       {
-               struct load_op *insn;
-               uint32_t insn_len = sizeof(struct load_op)
-                       + sizeof(struct literal_numeric);
-
-               insn = calloc(insn_len, 1);
-               if (!insn)
-                       return -ENOMEM;
-               insn->op = FILTER_OP_LOAD_S64;
-               *(int64_t *) insn->data = node->u.load.u.num;
-               ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
-               free(insn);
-               return ret;
-       }
-       case IR_DATA_FLOAT:
-       {
-               struct load_op *insn;
-               uint32_t insn_len = sizeof(struct load_op)
-                       + sizeof(struct literal_double);
-
-               insn = calloc(insn_len, 1);
-               if (!insn)
-                       return -ENOMEM;
-               insn->op = FILTER_OP_LOAD_DOUBLE;
-               *(double *) insn->data = node->u.load.u.flt;
-               ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
-               free(insn);
-               return ret;
-       }
-       case IR_DATA_FIELD_REF:
-       {
-               struct load_op *insn;
-               uint32_t insn_len = sizeof(struct load_op)
-                       + sizeof(struct field_ref);
-               struct field_ref ref_offset;
-               uint16_t reloc_offset;
-
-               insn = calloc(insn_len, 1);
-               if (!insn)
-                       return -ENOMEM;
-               insn->op = FILTER_OP_LOAD_FIELD_REF;
-               ref_offset.offset = (uint16_t) -1U;
-               memcpy(insn->data, &ref_offset, sizeof(ref_offset));
-               /* reloc_offset points to struct load_op */
-               reloc_offset = bytecode_get_len(&ctx->bytecode->b);
-               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;
-       }
-       }
-}
-
-static
-int visit_node_unary(struct filter_parser_ctx *ctx, struct ir_op *node)
-{
-       int ret;
-       struct unary_op insn;
-
-       /* Visit child */
-       ret = recursive_visit_gen_bytecode(ctx, node->u.unary.child);
-       if (ret)
-               return ret;
-
-       /* Generate end of bytecode instruction */
-       switch (node->u.unary.type) {
-       case AST_UNARY_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] Unknown unary node type in %s\n",
-                       __func__);
-               return -EINVAL;
-       case AST_UNARY_PLUS:
-               /* Nothing to do. */
-               return 0;
-       case AST_UNARY_MINUS:
-               insn.op = FILTER_OP_UNARY_MINUS;
-               return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
-       case AST_UNARY_NOT:
-               insn.op = FILTER_OP_UNARY_NOT;
-               return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
-       }
-}
-
-/*
- * Binary comparator nesting is disallowed. This allows fitting into
- * only 2 registers.
- */
-static
-int visit_node_binary(struct filter_parser_ctx *ctx, struct ir_op *node)
-{
-       int ret;
-       struct binary_op insn;
-
-       /* Visit child */
-       ret = recursive_visit_gen_bytecode(ctx, node->u.binary.left);
-       if (ret)
-               return ret;
-       ret = recursive_visit_gen_bytecode(ctx, node->u.binary.right);
-       if (ret)
-               return ret;
-
-       switch (node->u.binary.type) {
-       case AST_OP_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] Unknown unary node type in %s\n",
-                       __func__);
-               return -EINVAL;
-
-       case AST_OP_AND:
-       case AST_OP_OR:
-               fprintf(stderr, "[error] Unexpected logical node type in %s\n",
-                       __func__);
-               return -EINVAL;
-
-       case AST_OP_MUL:
-               insn.op = FILTER_OP_MUL;
-               break;
-       case AST_OP_DIV:
-               insn.op = FILTER_OP_DIV;
-               break;
-       case AST_OP_MOD:
-               insn.op = FILTER_OP_MOD;
-               break;
-       case AST_OP_PLUS:
-               insn.op = FILTER_OP_PLUS;
-               break;
-       case AST_OP_MINUS:
-               insn.op = FILTER_OP_MINUS;
-               break;
-       case AST_OP_RSHIFT:
-               insn.op = FILTER_OP_RSHIFT;
-               break;
-       case AST_OP_LSHIFT:
-               insn.op = FILTER_OP_LSHIFT;
-               break;
-       case AST_OP_BIN_AND:
-               insn.op = FILTER_OP_BIN_AND;
-               break;
-       case AST_OP_BIN_OR:
-               insn.op = FILTER_OP_BIN_OR;
-               break;
-       case AST_OP_BIN_XOR:
-               insn.op = FILTER_OP_BIN_XOR;
-               break;
-
-       case AST_OP_EQ:
-               insn.op = FILTER_OP_EQ;
-               break;
-       case AST_OP_NE:
-               insn.op = FILTER_OP_NE;
-               break;
-       case AST_OP_GT:
-               insn.op = FILTER_OP_GT;
-               break;
-       case AST_OP_LT:
-               insn.op = FILTER_OP_LT;
-               break;
-       case AST_OP_GE:
-               insn.op = FILTER_OP_GE;
-               break;
-       case AST_OP_LE:
-               insn.op = FILTER_OP_LE;
-               break;
-       }
-       return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
-}
-
-/*
- * A logical op always return a s64 (1 or 0).
- */
-static
-int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node)
-{
-       int ret;
-       struct logical_op insn;
-       uint16_t skip_offset_loc;
-       uint16_t target_loc;
-
-       /* Visit left child */
-       ret = recursive_visit_gen_bytecode(ctx, node->u.binary.left);
-       if (ret)
-               return ret;
-       /* 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_FLOAT) {
-               struct cast_op cast_insn;
-
-               if (node->u.binary.left->data_type == IR_DATA_FIELD_REF) {
-                       cast_insn.op = FILTER_OP_CAST_TO_S64;
-               } else {
-                       cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
-               }
-               ret = bytecode_push(&ctx->bytecode, &cast_insn,
-                                       1, sizeof(cast_insn));
-               if (ret)
-                       return ret;
-       }
-       switch (node->u.logical.type) {
-       default:
-               fprintf(stderr, "[error] Unknown node type in %s\n",
-                       __func__);
-               return -EINVAL;
-
-       case AST_OP_AND:
-               insn.op = FILTER_OP_AND;
-               break;
-       case AST_OP_OR:
-               insn.op = FILTER_OP_OR;
-               break;
-       }
-       insn.skip_offset = (uint16_t) -1UL;     /* Temporary */
-       ret = bytecode_push_logical(&ctx->bytecode, &insn, 1, sizeof(insn),
-                       &skip_offset_loc);
-       if (ret)
-               return ret;
-       /* Visit right child */
-       ret = recursive_visit_gen_bytecode(ctx, node->u.binary.right);
-       if (ret)
-               return ret;
-       /* 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_FLOAT) {
-               struct cast_op cast_insn;
-
-               if (node->u.binary.right->data_type == IR_DATA_FIELD_REF) {
-                       cast_insn.op = FILTER_OP_CAST_TO_S64;
-               } else {
-                       cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
-               }
-               ret = bytecode_push(&ctx->bytecode, &cast_insn,
-                                       1, sizeof(cast_insn));
-               if (ret)
-                       return ret;
-       }
-       /* We now know where the logical op can skip. */
-       target_loc = (uint16_t) bytecode_get_len(&ctx->bytecode->b);
-       ret = bytecode_patch(&ctx->bytecode,
-                       &target_loc,                    /* Offset to jump to */
-                       skip_offset_loc,                /* Where to patch */
-                       sizeof(uint16_t));
-       return ret;
-}
-
-/*
- * Postorder traversal of the tree. We need the children result before
- * we can evaluate the parent.
- */
-static
-int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx,
-               struct ir_op *node)
-{
-       switch (node->op) {
-       case IR_OP_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] Unknown node type in %s\n",
-                       __func__);
-               return -EINVAL;
-
-       case IR_OP_ROOT:
-               return visit_node_root(ctx, node);
-       case IR_OP_LOAD:
-               return visit_node_load(ctx, node);
-       case IR_OP_UNARY:
-               return visit_node_unary(ctx, node);
-       case IR_OP_BINARY:
-               return visit_node_binary(ctx, node);
-       case IR_OP_LOGICAL:
-               return visit_node_logical(ctx, node);
-       }
-}
-
-void filter_bytecode_free(struct filter_parser_ctx *ctx)
-{
-       free(ctx->bytecode);
-       ctx->bytecode = NULL;
-       free(ctx->bytecode_reloc);
-       ctx->bytecode_reloc = NULL;
-}
-
-int filter_visitor_bytecode_generate(struct filter_parser_ctx *ctx)
-{
-       int ret;
-
-       ret = bytecode_init(&ctx->bytecode);
-       if (ret)
-               return ret;
-       ret = bytecode_init(&ctx->bytecode_reloc);
-       if (ret)
-               goto error;
-       ret = recursive_visit_gen_bytecode(ctx, ctx->ir_root);
-       if (ret)
-               goto error;
-
-       /* Finally, append symbol table to bytecode */
-       ctx->bytecode->b.reloc_table_offset = bytecode_get_len(&ctx->bytecode->b);
-       return bytecode_push(&ctx->bytecode, ctx->bytecode_reloc->b.data,
-                       1, bytecode_get_len(&ctx->bytecode_reloc->b));
-
-error:
-       filter_bytecode_free(ctx);
-       return ret;
-}
diff --git a/src/lib/lttng-ctl/filter-visitor-generate-ir.c b/src/lib/lttng-ctl/filter-visitor-generate-ir.c
deleted file mode 100644 (file)
index d23372f..0000000
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * filter-visitor-generate-ir.c
- *
- * LTTng filter generate intermediate representation
- *
- * 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 "filter-ir.h"
-
-static
-struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
-               struct filter_node *node, enum ir_side side);
-
-static
-struct ir_op *make_op_root(struct ir_op *child, enum ir_side side)
-{
-       struct ir_op *op;
-
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
-               return NULL;
-       switch (child->data_type) {
-       case IR_DATA_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] Unknown root child data type\n");
-               return NULL;
-       case IR_DATA_STRING:
-               fprintf(stderr, "[error] String cannot be root data type\n");
-               return NULL;
-       case IR_DATA_NUMERIC:
-       case IR_DATA_FIELD_REF:
-               /* ok */
-               break;
-       }
-       op->op = IR_OP_ROOT;
-       op->side = side;
-       op->data_type = child->data_type;
-       op->signedness = child->signedness;
-       op->u.root.child = child;
-       return op;
-}
-
-static
-struct ir_op *make_op_load_string(char *string, enum ir_side side)
-{
-       struct ir_op *op;
-
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
-               return NULL;
-       op->op = IR_OP_LOAD;
-       op->data_type = IR_DATA_STRING;
-       op->signedness = IR_SIGN_UNKNOWN;
-       op->side = side;
-       op->u.load.u.string = strdup(string);
-       if (!op->u.load.u.string) {
-               free(op);
-               return NULL;
-       }
-       return op;
-}
-
-static
-struct ir_op *make_op_load_numeric(int64_t v, enum ir_side side)
-{
-       struct ir_op *op;
-
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
-               return NULL;
-       op->op = IR_OP_LOAD;
-       op->data_type = IR_DATA_NUMERIC;
-       /* TODO: for now, all numeric values are signed */
-       op->signedness = IR_SIGNED;
-       op->side = side;
-       op->u.load.u.num = v;
-       return op;
-}
-
-static
-struct ir_op *make_op_load_float(double v, enum ir_side side)
-{
-       struct ir_op *op;
-
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
-               return NULL;
-       op->op = IR_OP_LOAD;
-       op->data_type = IR_DATA_FLOAT;
-       op->signedness = IR_SIGN_UNKNOWN;
-       op->side = side;
-       op->u.load.u.flt = v;
-       return op;
-}
-
-static
-struct ir_op *make_op_load_field_ref(char *string, enum ir_side side)
-{
-       struct ir_op *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) {
-               free(op);
-               return NULL;
-       }
-       return op;
-}
-
-static
-struct ir_op *make_op_unary(enum unary_op_type unary_op_type,
-                       const char *op_str, enum ir_op_signedness signedness,
-                       struct ir_op *child, enum ir_side side)
-{
-       struct ir_op *op = NULL;
-
-       if (child->data_type == IR_DATA_STRING) {
-               fprintf(stderr, "[error] unary operation '%s' not allowed on string literal\n", op_str);
-               goto error;
-       }
-
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
-               return NULL;
-       op->op = IR_OP_UNARY;
-       op->data_type = child->data_type;
-       op->signedness = signedness;
-       op->side = side;
-       op->u.unary.type = unary_op_type;
-       op->u.unary.child = child;
-       return op;
-
-error:
-       free(op);
-       return NULL;
-}
-
-/*
- * unary + is pretty much useless.
- */
-static
-struct ir_op *make_op_unary_plus(struct ir_op *child, enum ir_side side)
-{
-       return make_op_unary(AST_UNARY_PLUS, "+", child->signedness,
-                       child, side);
-}
-
-static
-struct ir_op *make_op_unary_minus(struct ir_op *child, enum ir_side side)
-{
-       return make_op_unary(AST_UNARY_MINUS, "-", child->signedness,
-                       child, side);
-}
-
-static
-struct ir_op *make_op_unary_not(struct ir_op *child, enum ir_side side)
-{
-       return make_op_unary(AST_UNARY_NOT, "!", child->signedness,
-                       child, side);
-}
-
-#if 0
-static
-struct ir_op *make_op_binary_numeric(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 (right->data_type == IR_DATA_STRING
-                       || right->data_type == IR_DATA_STRING) {
-               fprintf(stderr, "[error] binary operation '%s' not allowed on string literal\n", op_str);
-               goto error;
-       }
-       if (left->data_type == IR_DATA_UNKNOWN
-               || right->data_type == IR_DATA_UNKNOWN) {
-               fprintf(stderr, "[error] binary operation '%s' has unknown type for both children\n", op_str);
-               goto error;
-
-       }
-
-       op = calloc(sizeof(struct ir_op_binary), 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;
-       op->side = side;
-
-       /*
-        * The field that is not a field ref will select type.
-        */
-       if (left->data_type != IR_DATA_FIELD_REF)
-               op->data_type = left->data_type;
-       else
-               op->data_type = right->data_type;
-
-       if (left->signedness == IR_SIGNED
-                       || right->signedness == IR_SIGNED) {
-               op->signedness = IR_SIGNED;
-       } else if (left->signedness == IR_SIGN_DYN
-                       || right->signedness == IR_SIGN_DYN) {
-               op->signedness = IR_SIGN_DYN;
-       } else if (left->signedness == IR_UNSIGNED
-                       && right->signedness == IR_UNSIGNED) {
-               op->signedness = IR_UNSIGNED;
-       } else {
-               op->signedness = IR_SIGN_UNKNOWN;
-       }
-
-       return op;
-
-error:
-       free(op);
-       return NULL;
-}
-
-static
-struct ir_op *make_op_binary_mul(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_MUL, "*", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_div(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_DIV, "/", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_mod(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_MOD, "%", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_plus(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_PLUS, "+", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_minus(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_MINUS, "-", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_rshift(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_RSHIFT, ">>", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_lshift(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_LSHIFT, "<<", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_and(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_BIN_AND, "&", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_or(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_BIN_OR, "|", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_xor(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_numeric(AST_OP_BIN_XOR, "^", left, right, side);
-}
-#endif //0
-
-static
-struct ir_op *make_op_binary_compare(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] binary operation '%s' has unknown operand type\n", op_str);
-               goto error;
-
-       }
-       if ((left->data_type == IR_DATA_STRING
-               && (right->data_type == IR_DATA_NUMERIC || right->data_type == IR_DATA_FLOAT))
-               || ((left->data_type == IR_DATA_NUMERIC || left->data_type == IR_DATA_FLOAT) &&
-                       right->data_type == IR_DATA_STRING)) {
-               fprintf(stderr, "[error] binary operation '%s' operand type mismatch\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 boolean, represented as 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_eq(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_compare(AST_OP_EQ, "==", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_ne(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_compare(AST_OP_NE, "!=", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_gt(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_compare(AST_OP_GT, ">", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_lt(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_compare(AST_OP_LT, "<", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_ge(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_compare(AST_OP_GE, ">=", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_le(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_compare(AST_OP_LE, "<=", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_logical(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] 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] logical binary operation '%s' cannot have string operand\n", op_str);
-               goto error;
-       }
-
-       op = calloc(sizeof(struct ir_op), 1);
-       if (!op)
-               return NULL;
-       op->op = IR_OP_LOGICAL;
-       op->u.binary.type = bin_op_type;
-       op->u.binary.left = left;
-       op->u.binary.right = right;
-
-       /* we return a boolean, represented as 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)
-{
-       return make_op_binary_logical(AST_OP_AND, "&&", left, right, side);
-}
-
-static
-struct ir_op *make_op_binary_logical_or(struct ir_op *left, struct ir_op *right,
-               enum ir_side side)
-{
-       return make_op_binary_logical(AST_OP_OR, "||", left, right, side);
-}
-
-static
-void filter_free_ir_recursive(struct ir_op *op)
-{
-       if (!op)
-               return;
-       switch (op->op) {
-       case IR_OP_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] Unknown op type in %s\n",
-                       __func__);
-               break;
-       case IR_OP_ROOT:
-               filter_free_ir_recursive(op->u.root.child);
-               break;
-       case IR_OP_LOAD:
-               switch (op->data_type) {
-               case IR_DATA_STRING:
-                       free(op->u.load.u.string);
-                       break;
-               case IR_DATA_FIELD_REF:
-                       free(op->u.load.u.ref);
-                       break;
-               default:
-                       break;
-               }
-               break;
-       case IR_OP_UNARY:
-               filter_free_ir_recursive(op->u.unary.child);
-               break;
-       case IR_OP_BINARY:
-               filter_free_ir_recursive(op->u.binary.left);
-               filter_free_ir_recursive(op->u.binary.right);
-               break;
-       case IR_OP_LOGICAL:
-               filter_free_ir_recursive(op->u.logical.left);
-               filter_free_ir_recursive(op->u.logical.right);
-               break;
-       }
-       free(op);
-}
-
-static
-struct ir_op *make_expression(struct filter_parser_ctx *ctx,
-               struct filter_node *node, enum ir_side side)
-{
-       switch (node->u.expression.type) {
-       case AST_EXP_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown expression type\n", __func__);
-               return NULL;
-
-       case AST_EXP_STRING:
-               return make_op_load_string(node->u.expression.u.string, side);
-       case AST_EXP_CONSTANT:
-               return make_op_load_numeric(node->u.expression.u.constant,
-                                       side);
-       case AST_EXP_FLOAT_CONSTANT:
-               return make_op_load_float(node->u.expression.u.float_constant,
-                                       side);
-       case AST_EXP_IDENTIFIER:
-               if (node->u.expression.pre_op != AST_LINK_UNKNOWN) {
-                       fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
-                       return NULL;
-               }
-               return make_op_load_field_ref(node->u.expression.u.identifier,
-                                       side);
-       case AST_EXP_NESTED:
-               return generate_ir_recursive(ctx, node->u.expression.u.child,
-                                       side);
-       }
-}
-
-static
-struct ir_op *make_op(struct filter_parser_ctx *ctx,
-               struct filter_node *node, enum ir_side side)
-{
-       struct ir_op *op = NULL, *lchild, *rchild;
-       const char *op_str = "?";
-
-       switch (node->u.op.type) {
-       case AST_OP_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown binary op type\n", __func__);
-               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).
-        */
-       case AST_OP_MUL:
-               op_str = "*";
-               goto error_not_supported;
-       case AST_OP_DIV:
-               op_str = "/";
-               goto error_not_supported;
-       case AST_OP_MOD:
-               op_str = "%";
-               goto error_not_supported;
-       case AST_OP_PLUS:
-               op_str = "+";
-               goto error_not_supported;
-       case AST_OP_MINUS:
-               op_str = "-";
-               goto error_not_supported;
-       case AST_OP_RSHIFT:
-               op_str = ">>";
-               goto error_not_supported;
-       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_EQ:
-       case AST_OP_NE:
-       case AST_OP_GT:
-       case AST_OP_LT:
-       case AST_OP_GE:
-       case AST_OP_LE:
-               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_AND:
-       case AST_OP_OR:
-               /*
-                * Both children considered as left, since we need to
-                * populate R0.
-                */
-               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_LEFT);
-               if (!rchild) {
-                       filter_free_ir_recursive(lchild);
-                       return NULL;
-               }
-               break;
-       }
-
-       switch (node->u.op.type) {
-       case AST_OP_AND:
-               op = make_op_binary_logical_and(lchild, rchild, side);
-               break;
-       case AST_OP_OR:
-               op = make_op_binary_logical_or(lchild, rchild, side);
-               break;
-       case AST_OP_EQ:
-               op = make_op_binary_eq(lchild, rchild, side);
-               break;
-       case AST_OP_NE:
-               op = make_op_binary_ne(lchild, rchild, side);
-               break;
-       case AST_OP_GT:
-               op = make_op_binary_gt(lchild, rchild, side);
-               break;
-       case AST_OP_LT:
-               op = make_op_binary_lt(lchild, rchild, side);
-               break;
-       case AST_OP_GE:
-               op = make_op_binary_ge(lchild, rchild, side);
-               break;
-       case AST_OP_LE:
-               op = make_op_binary_le(lchild, rchild, side);
-               break;
-       default:
-               break;
-       }
-
-       if (!op) {
-               filter_free_ir_recursive(rchild);
-               filter_free_ir_recursive(lchild);
-       }
-       return op;
-
-error_not_supported:
-       fprintf(stderr, "[error] %s: binary operation '%s' not supported\n",
-               __func__, op_str);
-       return NULL;
-}
-
-static
-struct ir_op *make_unary_op(struct filter_parser_ctx *ctx,
-               struct filter_node *node, enum ir_side side)
-{
-       const char *op_str = "?";
-
-       switch (node->u.unary_op.type) {
-       case AST_UNARY_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown unary op type\n", __func__);
-               return NULL;
-
-       case AST_UNARY_PLUS:
-       {
-               struct ir_op *op, *child;
-
-               child = generate_ir_recursive(ctx, node->u.unary_op.child,
-                                       side);
-               if (!child)
-                       return NULL;
-               op = make_op_unary_plus(child, side);
-               if (!op) {
-                       filter_free_ir_recursive(child);
-                       return NULL;
-               }
-               return op;
-       }
-       case AST_UNARY_MINUS:
-       {
-               struct ir_op *op, *child;
-
-               child = generate_ir_recursive(ctx, node->u.unary_op.child,
-                                       side);
-               if (!child)
-                       return NULL;
-               op = make_op_unary_minus(child, side);
-               if (!op) {
-                       filter_free_ir_recursive(child);
-                       return NULL;
-               }
-               return op;
-       }
-       case AST_UNARY_NOT:
-       {
-               struct ir_op *op, *child;
-
-               child = generate_ir_recursive(ctx, node->u.unary_op.child,
-                                       side);
-               if (!child)
-                       return NULL;
-               op = make_op_unary_not(child, side);
-               if (!op) {
-                       filter_free_ir_recursive(child);
-                       return NULL;
-               }
-               return op;
-       }
-       case AST_UNARY_BIN_NOT:
-       {
-               op_str = "~";
-               goto error_not_supported;
-       }
-       }
-
-error_not_supported:
-       fprintf(stderr, "[error] %s: unary operation '%s' not supported\n",
-               __func__, op_str);
-       return NULL;
-}
-
-static
-struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
-               struct filter_node *node, enum ir_side side)
-{
-       switch (node->type) {
-       case NODE_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown node type\n", __func__);
-               return NULL;
-
-       case NODE_ROOT:
-       {
-               struct ir_op *op, *child;
-
-               child = generate_ir_recursive(ctx, node->u.root.child,
-                                       side);
-               if (!child)
-                       return NULL;
-               op = make_op_root(child, side);
-               if (!op) {
-                       filter_free_ir_recursive(child);
-                       return NULL;
-               }
-               return op;
-       }
-       case NODE_EXPRESSION:
-               return make_expression(ctx, node, side);
-       case NODE_OP:
-               return make_op(ctx, node, side);
-       case NODE_UNARY_OP:
-               return make_unary_op(ctx, node, side);
-       }
-       return 0;
-}
-
-
-void filter_ir_free(struct filter_parser_ctx *ctx)
-{
-       filter_free_ir_recursive(ctx->ir_root);
-       ctx->ir_root = NULL;
-}
-
-int filter_visitor_ir_generate(struct filter_parser_ctx *ctx)
-{
-       struct ir_op *op;
-
-       op = generate_ir_recursive(ctx, &ctx->ast->root, IR_LEFT);
-       if (!op) {
-               return -EINVAL;
-       }
-       ctx->ir_root = op;
-       return 0;
-}
diff --git a/src/lib/lttng-ctl/filter-visitor-ir-check-binary-comparator.c b/src/lib/lttng-ctl/filter-visitor-ir-check-binary-comparator.c
deleted file mode 100644 (file)
index 13da71e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * filter-visitor-ir-check-binary-comparator.c
- *
- * LTTng filter IR check binary comparator
- *
- * 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 "filter-ir.h"
-
-static
-int check_bin_comparator(struct ir_op *node)
-{
-       switch (node->op) {
-       case IR_OP_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown op type\n", __func__);
-               return -EINVAL;
-
-       case IR_OP_ROOT:
-               return check_bin_comparator(node->u.root.child);
-       case IR_OP_LOAD:
-               return 0;
-       case IR_OP_UNARY:
-               return check_bin_comparator(node->u.unary.child);
-       case IR_OP_BINARY:
-       {
-               int ret;
-
-               if (node->u.binary.left->data_type == IR_DATA_STRING
-                               || node->u.binary.right->data_type
-                                       == IR_DATA_STRING) {
-                       if (node->u.binary.type != AST_OP_EQ
-                                       && node->u.binary.type != AST_OP_NE) {
-                               fprintf(stderr, "[error] Only '==' and '!=' comparators are allowed for strings\n");
-                               return -EINVAL;
-                       }
-               }
-
-               ret = check_bin_comparator(node->u.binary.left);
-               if (ret)
-                       return ret;
-               return check_bin_comparator(node->u.binary.right);
-       }
-       case IR_OP_LOGICAL:
-       {
-               int ret;
-
-               ret = check_bin_comparator(node->u.logical.left);
-               if (ret)
-                       return ret;
-               return check_bin_comparator(node->u.logical.right);
-       }
-       }
-}
-
-int filter_visitor_ir_check_binary_comparator(struct filter_parser_ctx *ctx)
-{
-       return check_bin_comparator(ctx->ir_root);
-}
diff --git a/src/lib/lttng-ctl/filter-visitor-ir-check-binary-op-nesting.c b/src/lib/lttng-ctl/filter-visitor-ir-check-binary-op-nesting.c
deleted file mode 100644 (file)
index 08488de..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * filter-visitor-ir-check-binary-op-nesting.c
- *
- * LTTng filter IR check binary op nesting
- *
- * 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 "filter-ir.h"
-
-static
-int check_bin_op_nesting_recursive(struct ir_op *node, int nesting)
-{
-       switch (node->op) {
-       case IR_OP_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown op type\n", __func__);
-               return -EINVAL;
-
-       case IR_OP_ROOT:
-               return check_bin_op_nesting_recursive(node->u.root.child,
-                               nesting);
-       case IR_OP_LOAD:
-               return 0;
-       case IR_OP_UNARY:
-               return check_bin_op_nesting_recursive(node->u.unary.child,
-                               nesting);
-       case IR_OP_BINARY:
-       {
-               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++);
-               if (ret)
-                       return ret;
-               return check_bin_op_nesting_recursive(node->u.binary.right,
-                               nesting++);
-       }
-       case IR_OP_LOGICAL:
-       {
-               int ret;
-
-               ret = check_bin_op_nesting_recursive(node->u.logical.left,
-                               nesting);
-               if (ret)
-                       return ret;
-               return check_bin_op_nesting_recursive(node->u.logical.right,
-                               nesting);
-       }
-       }
-}
-
-int filter_visitor_ir_check_binary_op_nesting(struct filter_parser_ctx *ctx)
-{
-       return check_bin_op_nesting_recursive(ctx->ir_root, 0);
-}
diff --git a/src/lib/lttng-ctl/filter-visitor-set-parent.c b/src/lib/lttng-ctl/filter-visitor-set-parent.c
deleted file mode 100644 (file)
index 2ad707f..0000000
+++ /dev/null
@@ -1,139 +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"
-
-static
-int update_child(struct filter_node *parent,
-               struct filter_node *old_child,
-               struct filter_node *new_child)
-{
-       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:
-                       {
-                               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) {
-                                               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;
-}
-
-int filter_visitor_set_parent(struct filter_parser_ctx *ctx)
-{
-       return recursive_visit_set_parent(&ctx->ast->root, NULL);
-}
diff --git a/src/lib/lttng-ctl/filter-visitor-xml.c b/src/lib/lttng-ctl/filter-visitor-xml.c
deleted file mode 100644 (file)
index b3a1ac9..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * filter-visitor-xml.c
- *
- * LTTng filter XML pretty printer 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"
-
-#define fprintf_dbg(fd, fmt, args...)  fprintf(fd, "%s: " fmt, __func__, ## args)
-
-static
-int recursive_visit_print(struct filter_node *node, FILE *stream, int indent);
-
-static
-void print_tabs(FILE *fd, int depth)
-{
-       int i;
-
-       for (i = 0; i < depth; i++)
-               fprintf(fd, "\t");
-}
-
-static
-int recursive_visit_print_expression(struct filter_node *node,
-               FILE *stream, int indent)
-{
-       if (!node) {
-               fprintf(stderr, "[error] %s: NULL child\n", __func__);
-               return -EINVAL;
-       }
-       switch (node->u.expression.type) {
-       case AST_EXP_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown expression\n", __func__);
-               return -EINVAL;
-       case AST_EXP_STRING:
-               print_tabs(stream, indent);
-               fprintf(stream, "<string value=\"%s\"/>\n",
-                       node->u.expression.u.string);
-               break;
-       case AST_EXP_CONSTANT:
-               print_tabs(stream, indent);
-               fprintf(stream, "<constant value=\"%" PRIu64 "\"/>\n",
-                       node->u.expression.u.constant);
-               break;
-       case AST_EXP_FLOAT_CONSTANT:
-               print_tabs(stream, indent);
-               fprintf(stream, "<float_constant value=\"%lg\"/>\n",
-                       node->u.expression.u.float_constant);
-               break;
-       case AST_EXP_IDENTIFIER:
-               print_tabs(stream, indent);
-               fprintf(stream, "<identifier value=\"%s\"/>\n",
-                       node->u.expression.u.identifier);
-               while (node->u.expression.next) {
-                       print_tabs(stream, indent);
-                       fprintf(stream, "<link type=\"");
-                       switch (node->u.expression.pre_op) {
-                       case AST_LINK_UNKNOWN:
-                       default:
-                               fprintf(stderr, "[error] %s: unknown link\n", __func__);
-                               return -EINVAL;
-                       case AST_LINK_DOT:
-                               fprintf(stream, ".");
-                               break;
-                       case AST_LINK_RARROW:
-                               fprintf(stream, "->");
-                               break;
-                       }
-                       fprintf(stream, "\"/>\n");
-
-                       node = node->u.expression.next;
-                       if (node->type != NODE_EXPRESSION ||
-                               node->u.expression.type != AST_EXP_IDENTIFIER) {
-                               fprintf(stderr, "[error] %s: expecting identifier before link\n", __func__);
-                               return -EINVAL;
-                       }
-
-                       print_tabs(stream, indent);
-                       fprintf(stream, "<identifier value=\"%s\"/>\n",
-                               node->u.expression.u.identifier);
-               }
-               break;
-       case AST_EXP_NESTED:
-               return recursive_visit_print(node->u.expression.u.child,
-                               stream, indent + 1);
-       }
-       return 0;
-}
-
-
-static
-int recursive_visit_print(struct filter_node *node, FILE *stream, int indent)
-{
-       int ret;
-
-       if (!node) {
-               fprintf(stderr, "[error] %s: NULL child\n", __func__);
-               return -EINVAL;
-       }
-       switch (node->type) {
-       case NODE_UNKNOWN:
-       default:
-               fprintf(stderr, "[error] %s: unknown node type\n", __func__);
-               return -EINVAL;
-       case NODE_ROOT:
-               print_tabs(stream, indent);
-               fprintf(stream, "<root>\n");
-               ret = recursive_visit_print(node->u.root.child, stream,
-                                       indent + 1);
-               print_tabs(stream, indent);
-               fprintf(stream, "</root>\n");
-               return ret;
-       case NODE_EXPRESSION:
-               print_tabs(stream, indent);
-               fprintf(stream, "<expression>\n");
-               ret = recursive_visit_print_expression(node, stream,
-                                       indent + 1);
-               print_tabs(stream, indent);
-               fprintf(stream, "</expression>\n");
-               return ret;
-       case NODE_OP:
-               print_tabs(stream, indent);
-               fprintf(stream, "<op type=");
-               switch (node->u.op.type) {
-               case AST_OP_UNKNOWN:
-               default:
-                       fprintf(stderr, "[error] %s: unknown op\n", __func__);
-                       return -EINVAL;
-               case AST_OP_MUL:
-                       fprintf(stream, "\"*\"");
-                       break;
-               case AST_OP_DIV:
-                       fprintf(stream, "\"/\"");
-                       break;
-               case AST_OP_MOD:
-                       fprintf(stream, "\"%%\"");
-                       break;
-               case AST_OP_PLUS:
-                       fprintf(stream, "\"+\"");
-                       break;
-               case AST_OP_MINUS:
-                       fprintf(stream, "\"-\"");
-                       break;
-               case AST_OP_RSHIFT:
-                       fprintf(stream, "\">>\"");
-                       break;
-               case AST_OP_LSHIFT:
-                       fprintf(stream, "\"<<\"");
-                       break;
-               case AST_OP_AND:
-                       fprintf(stream, "\"&&\"");
-                       break;
-               case AST_OP_OR:
-                       fprintf(stream, "\"||\"");
-                       break;
-               case AST_OP_BIN_AND:
-                       fprintf(stream, "\"&\"");
-                       break;
-               case AST_OP_BIN_OR:
-                       fprintf(stream, "\"|\"");
-                       break;
-               case AST_OP_BIN_XOR:
-                       fprintf(stream, "\"^\"");
-                       break;
-
-               case AST_OP_EQ:
-                       fprintf(stream, "\"==\"");
-                       break;
-               case AST_OP_NE:
-                       fprintf(stream, "\"!=\"");
-                       break;
-               case AST_OP_GT:
-                       fprintf(stream, "\">\"");
-                       break;
-               case AST_OP_LT:
-                       fprintf(stream, "\"<\"");
-                       break;
-               case AST_OP_GE:
-                       fprintf(stream, "\">=\"");
-                       break;
-               case AST_OP_LE:
-                       fprintf(stream, "\"<=\"");
-                       break;
-               }
-               fprintf(stream, ">\n");
-               ret = recursive_visit_print(node->u.op.lchild,
-                                       stream, indent + 1);
-               if (ret)
-                       return ret;
-               ret = recursive_visit_print(node->u.op.rchild,
-                                       stream, indent + 1);
-               if (ret)
-                       return ret;
-               print_tabs(stream, indent);
-               fprintf(stream, "</op>\n");
-               return ret;
-       case NODE_UNARY_OP:
-               print_tabs(stream, indent);
-               fprintf(stream, "<unary_op type=");
-               switch (node->u.unary_op.type) {
-               case AST_UNARY_UNKNOWN:
-               default:
-                       fprintf(stderr, "[error] %s: unknown unary_op\n", __func__);
-                       return -EINVAL;
-               case AST_UNARY_PLUS:
-                       fprintf(stream, "\"+\"");
-                       break;
-               case AST_UNARY_MINUS:
-                       fprintf(stream, "\"-\"");
-                       break;
-               case AST_UNARY_NOT:
-                       fprintf(stream, "\"!\"");
-                       break;
-               }
-               fprintf(stream, ">\n");
-               ret = recursive_visit_print(node->u.unary_op.child,
-                                       stream, indent + 1);
-               print_tabs(stream, indent);
-               fprintf(stream, "</unary_op>\n");
-               return ret;
-       }
-       return 0;
-}
-
-int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream,
-                       int indent)
-{
-       return recursive_visit_print(&ctx->ast->root, stream, indent);
-}
diff --git a/src/lib/lttng-ctl/filter/Makefile.am b/src/lib/lttng-ctl/filter/Makefile.am
new file mode 100644 (file)
index 0000000..45ed418
--- /dev/null
@@ -0,0 +1,24 @@
+noinst_PROGRAMS = filter-grammar-test
+noinst_LTLIBRARIES = libfilter.la
+noinst_HEADERS = filter-ast.h
+
+BUILT_SOURCES = filter-parser.h
+AM_YFLAGS = -t -d -v
+
+libfilter_la_SOURCES = filter-lexer.l filter-parser.y \
+       filter-visitor-set-parent.c \
+       filter-visitor-xml.c \
+       filter-visitor-generate-ir.c \
+       filter-visitor-ir-check-binary-op-nesting.c \
+       filter-visitor-generate-bytecode.c \
+       align.h \
+       bug.h \
+       filter-ast.h \
+       filter-bytecode.h \
+       filter-ir.h \
+       memstream.h
+
+filter_grammar_test_SOURCES = filter-grammar-test.c
+filter_grammar_test_LDADD = libfilter.la
+
+CLEANFILES = filter-lexer.c filter-parser.c filter-parser.h filter-parser.output
diff --git a/src/lib/lttng-ctl/filter/align.h b/src/lib/lttng-ctl/filter/align.h
new file mode 100644 (file)
index 0000000..fe32673
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _LTTNG_ALIGN_H
+#define _LTTNG_ALIGN_H
+
+/*
+ * align.h
+ *
+ * (C) Copyright 2010-2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#include "bug.h"
+#include <unistd.h>
+#include <limits.h>
+
+#ifndef PAGE_SIZE      /* Cygwin limits.h defines its own PAGE_SIZE */
+#define PAGE_SIZE              sysconf(_SC_PAGE_SIZE)
+#endif
+
+#define PAGE_MASK              (~(PAGE_SIZE - 1))
+#define __ALIGN_MASK(v, mask)  (((v) + (mask)) & ~(mask))
+#define ALIGN(v, align)                __ALIGN_MASK(v, (__typeof__(v)) (align) - 1)
+#define PAGE_ALIGN(addr)       ALIGN(addr, PAGE_SIZE)
+
+/**
+ * offset_align - Calculate the offset needed to align an object on its natural
+ *                alignment towards higher addresses.
+ * @align_drift:  object offset from an "alignment"-aligned address.
+ * @alignment:    natural object alignment. Must be non-zero, power of 2.
+ *
+ * Returns the offset that must be added to align towards higher
+ * addresses.
+ */
+#define offset_align(align_drift, alignment)                                  \
+       ({                                                                     \
+               LTTNG_BUILD_RUNTIME_BUG_ON((alignment) == 0                    \
+                                  || ((alignment) & ((alignment) - 1)));      \
+               (((alignment) - (align_drift)) & ((alignment) - 1));           \
+       })
+
+/**
+ * offset_align_floor - Calculate the offset needed to align an object
+ *                      on its natural alignment towards lower addresses.
+ * @align_drift:  object offset from an "alignment"-aligned address.
+ * @alignment:    natural object alignment. Must be non-zero, power of 2.
+ *
+ * Returns the offset that must be substracted to align towards lower addresses.
+ */
+#define offset_align_floor(align_drift, alignment)                            \
+       ({                                                                     \
+               LTTNG_BUILD_RUNTIME_BUG_ON((alignment) == 0                    \
+                                  || ((alignment) & ((alignment) - 1)));      \
+               (((align_drift) - (alignment)) & ((alignment) - 1);            \
+       })
+
+#endif /* _LTTNG_ALIGN_H */
diff --git a/src/lib/lttng-ctl/filter/bug.h b/src/lib/lttng-ctl/filter/bug.h
new file mode 100644 (file)
index 0000000..9368c08
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef _LTTNG_BUG_H
+#define _LTTNG_BUG_H
+
+/*
+ * lttng/bug.h
+ *
+ * (C) Copyright 2010-2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#include <urcu/compiler.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LTTNG_BUG_ON(condition)                                                \
+       do {                                                            \
+               if (caa_unlikely(condition)) {                          \
+                       fprintf(stderr,                                 \
+                               "LTTng BUG in file %s, line %d.\n",     \
+                               __FILE__, __LINE__);                    \
+                       exit(EXIT_FAILURE);                             \
+               }                                                       \
+       } while (0)
+
+#define LTTNG_BUILD_BUG_ON(condition)                                  \
+       ((void) sizeof(char[-!!(condition)]))
+
+/**
+ * LTTNG_BUILD_RUNTIME_BUG_ON - check condition at build (if constant) or runtime
+ * @condition: the condition which should be false.
+ *
+ * If the condition is a constant and true, the compiler will generate a build
+ * error. If the condition is not constant, a BUG will be triggered at runtime
+ * if the condition is ever true. If the condition is constant and false, no
+ * code is emitted.
+ */
+#define LTTNG_BUILD_RUNTIME_BUG_ON(condition)                  \
+       do {                                                    \
+               if (__builtin_constant_p(condition))            \
+                       LTTNG_BUILD_BUG_ON(condition);          \
+               else                                            \
+                       LTTNG_BUG_ON(condition);                \
+       } while (0)
+
+#endif
diff --git a/src/lib/lttng-ctl/filter/filter-ast.h b/src/lib/lttng-ctl/filter/filter-ast.h
new file mode 100644 (file)
index 0000000..1767164
--- /dev/null
@@ -0,0 +1,192 @@
+#ifndef _FILTER_AST_H
+#define _FILTER_AST_H
+
+/*
+ * filter-ast.h
+ *
+ * LTTng filter AST
+ *
+ * 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
+ */
+
+/*
+ * Note: filter-ast.h should be included before filter-parser.h.
+ */
+
+#include <urcu/list.h>
+#include <stdint.h>
+
+#define printf_debug(fmt, args...)                                     \
+       do {                                                            \
+               if (filter_parser_debug)                                \
+                       fprintf(stdout, "[debug] " fmt, ## args);       \
+       } while (0)
+
+// the parameter name (of the reentrant 'yyparse' function)
+// data is a pointer to a 'SParserParam' structure
+//#define YYPARSE_PARAM        parser_ctx
+
+// the argument for the 'yylex' function
+#define YYLEX_PARAM    ((struct filter_parser_ctx *) parser_ctx)->scanner
+
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+extern int filter_parser_debug;
+
+struct filter_node;
+struct filter_parser;
+
+enum node_type {
+       NODE_UNKNOWN = 0,
+       NODE_ROOT,
+
+       NODE_EXPRESSION,
+       NODE_OP,
+       NODE_UNARY_OP,
+
+       NR_NODE_TYPES,
+};
+
+enum op_type {
+       AST_OP_UNKNOWN = 0,
+       AST_OP_MUL,
+       AST_OP_DIV,
+       AST_OP_MOD,
+       AST_OP_PLUS,
+       AST_OP_MINUS,
+       AST_OP_RSHIFT,
+       AST_OP_LSHIFT,
+       AST_OP_AND,
+       AST_OP_OR,
+       AST_OP_BIN_AND,
+       AST_OP_BIN_OR,
+       AST_OP_BIN_XOR,
+
+       AST_OP_EQ,
+       AST_OP_NE,
+       AST_OP_GT,
+       AST_OP_LT,
+       AST_OP_GE,
+       AST_OP_LE,
+};
+
+enum unary_op_type {
+       AST_UNARY_UNKNOWN = 0,
+       AST_UNARY_PLUS,
+       AST_UNARY_MINUS,
+       AST_UNARY_NOT,
+       AST_UNARY_BIN_NOT,
+};
+
+enum ast_link_type {
+       AST_LINK_UNKNOWN = 0,
+       AST_LINK_DOT,
+       AST_LINK_RARROW,
+};
+
+struct filter_node {
+       /*
+        * Parent node is only set on demand by specific visitor.
+        */
+       struct filter_node *parent;
+       struct cds_list_head gc;
+
+       enum node_type type;
+       union {
+               struct {
+               } unknown;
+               struct {
+                       struct filter_node *child;
+               } root;
+               struct {
+                       enum {
+                               AST_EXP_UNKNOWN = 0,
+                               AST_EXP_STRING,
+                               AST_EXP_CONSTANT,
+                               AST_EXP_FLOAT_CONSTANT,
+                               AST_EXP_IDENTIFIER,
+                               AST_EXP_NESTED,
+                       } type;
+                       enum ast_link_type post_op;     /* reverse */
+                       enum ast_link_type pre_op;      /* forward */
+                       union {
+                               char *string;
+                               uint64_t constant;
+                               double float_constant;
+                               char *identifier;
+                               /*
+                                * child can be nested.
+                                */
+                               struct filter_node *child;
+                       } u;
+                       /* linked dot/arrow chain */
+                       struct filter_node *prev;
+                       struct filter_node *next;
+               } expression;
+               struct {
+                       enum op_type type;
+                       struct filter_node *lchild;
+                       struct filter_node *rchild;
+               } op;
+               struct {
+                       enum unary_op_type type;
+                       struct filter_node *child;
+               } unary_op;
+       } u;
+};
+
+struct filter_ast {
+       struct filter_node root;
+       struct cds_list_head allocated_nodes;
+};
+
+const char *node_type(struct filter_node *node);
+
+struct ir_op;
+
+struct filter_parser_ctx {
+       yyscan_t scanner;
+       struct filter_ast *ast;
+       struct cds_list_head allocated_strings;
+       struct ir_op *ir_root;
+       struct lttng_filter_bytecode_alloc *bytecode;
+       struct lttng_filter_bytecode_alloc *bytecode_reloc;
+};
+
+struct filter_parser_ctx *filter_parser_ctx_alloc(FILE *input);
+void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx);
+int filter_parser_ctx_append_ast(struct filter_parser_ctx *parser_ctx);
+
+static inline
+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);
+void filter_ir_free(struct filter_parser_ctx *ctx);
+int filter_visitor_bytecode_generate(struct filter_parser_ctx *ctx);
+void filter_bytecode_free(struct filter_parser_ctx *ctx);
+int filter_visitor_ir_check_binary_op_nesting(struct filter_parser_ctx *ctx);
+int filter_visitor_ir_check_binary_comparator(struct filter_parser_ctx *ctx);
+
+#endif /* _FILTER_AST_H */
diff --git a/src/lib/lttng-ctl/filter/filter-bytecode.h b/src/lib/lttng-ctl/filter/filter-bytecode.h
new file mode 100644 (file)
index 0000000..5d2559d
--- /dev/null
@@ -0,0 +1,189 @@
+#ifndef _FILTER_BYTECODE_H
+#define _FILTER_BYTECODE_H
+
+/*
+ * filter-bytecode.h
+ *
+ * LTTng filter bytecode
+ *
+ * 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 <common/sessiond-comm/sessiond-comm.h>
+
+#include "filter-ast.h"
+
+/*
+ * offsets are absolute from start of bytecode.
+ */
+
+struct field_ref {
+       /* Initially, symbol offset. After link, field offset. */
+       uint16_t offset;
+} __attribute__((packed));
+
+struct literal_numeric {
+       int64_t v;
+} __attribute__((packed));
+
+struct literal_double {
+       double v;
+} __attribute__((packed));
+
+struct literal_string {
+       char string[0];
+} __attribute__((packed));
+
+enum filter_op {
+       FILTER_OP_UNKNOWN = 0,
+
+       FILTER_OP_RETURN,
+
+       /* binary */
+       FILTER_OP_MUL,
+       FILTER_OP_DIV,
+       FILTER_OP_MOD,
+       FILTER_OP_PLUS,
+       FILTER_OP_MINUS,
+       FILTER_OP_RSHIFT,
+       FILTER_OP_LSHIFT,
+       FILTER_OP_BIN_AND,
+       FILTER_OP_BIN_OR,
+       FILTER_OP_BIN_XOR,
+
+       /* binary comparators */
+       FILTER_OP_EQ,
+       FILTER_OP_NE,
+       FILTER_OP_GT,
+       FILTER_OP_LT,
+       FILTER_OP_GE,
+       FILTER_OP_LE,
+
+       /* string binary comparator */
+       FILTER_OP_EQ_STRING,
+       FILTER_OP_NE_STRING,
+       FILTER_OP_GT_STRING,
+       FILTER_OP_LT_STRING,
+       FILTER_OP_GE_STRING,
+       FILTER_OP_LE_STRING,
+
+       /* s64 binary comparator */
+       FILTER_OP_EQ_S64,
+       FILTER_OP_NE_S64,
+       FILTER_OP_GT_S64,
+       FILTER_OP_LT_S64,
+       FILTER_OP_GE_S64,
+       FILTER_OP_LE_S64,
+
+       /* double binary comparator */
+       FILTER_OP_EQ_DOUBLE,
+       FILTER_OP_NE_DOUBLE,
+       FILTER_OP_GT_DOUBLE,
+       FILTER_OP_LT_DOUBLE,
+       FILTER_OP_GE_DOUBLE,
+       FILTER_OP_LE_DOUBLE,
+
+       /* Mixed S64-double binary comparators */
+       FILTER_OP_EQ_DOUBLE_S64,
+       FILTER_OP_NE_DOUBLE_S64,
+       FILTER_OP_GT_DOUBLE_S64,
+       FILTER_OP_LT_DOUBLE_S64,
+       FILTER_OP_GE_DOUBLE_S64,
+       FILTER_OP_LE_DOUBLE_S64,
+
+       FILTER_OP_EQ_S64_DOUBLE,
+       FILTER_OP_NE_S64_DOUBLE,
+       FILTER_OP_GT_S64_DOUBLE,
+       FILTER_OP_LT_S64_DOUBLE,
+       FILTER_OP_GE_S64_DOUBLE,
+       FILTER_OP_LE_S64_DOUBLE,
+
+       /* unary */
+       FILTER_OP_UNARY_PLUS,
+       FILTER_OP_UNARY_MINUS,
+       FILTER_OP_UNARY_NOT,
+       FILTER_OP_UNARY_PLUS_S64,
+       FILTER_OP_UNARY_MINUS_S64,
+       FILTER_OP_UNARY_NOT_S64,
+       FILTER_OP_UNARY_PLUS_DOUBLE,
+       FILTER_OP_UNARY_MINUS_DOUBLE,
+       FILTER_OP_UNARY_NOT_DOUBLE,
+
+       /* logical */
+       FILTER_OP_AND,
+       FILTER_OP_OR,
+
+       /* load */
+       FILTER_OP_LOAD_FIELD_REF,
+       FILTER_OP_LOAD_FIELD_REF_STRING,
+       FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
+       FILTER_OP_LOAD_FIELD_REF_S64,
+       FILTER_OP_LOAD_FIELD_REF_DOUBLE,
+
+       FILTER_OP_LOAD_STRING,
+       FILTER_OP_LOAD_S64,
+       FILTER_OP_LOAD_DOUBLE,
+
+       /* cast */
+       FILTER_OP_CAST_TO_S64,
+       FILTER_OP_CAST_DOUBLE_TO_S64,
+       FILTER_OP_CAST_NOP,
+
+       NR_FILTER_OPS,
+};
+
+typedef uint8_t filter_opcode_t;
+
+struct load_op {
+       filter_opcode_t op;
+       char data[0];
+       /* data to load. Size known by enum filter_opcode and null-term char. */
+} __attribute__((packed));
+
+struct binary_op {
+       filter_opcode_t op;
+} __attribute__((packed));
+
+struct unary_op {
+       filter_opcode_t op;
+} __attribute__((packed));
+
+/* skip_offset is absolute from start of bytecode */
+struct logical_op {
+       filter_opcode_t op;
+       uint16_t skip_offset;   /* bytecode insn, if skip second test */
+} __attribute__((packed));
+
+struct cast_op {
+       filter_opcode_t op;
+} __attribute__((packed));
+
+struct return_op {
+       filter_opcode_t op;
+} __attribute__((packed));
+
+struct lttng_filter_bytecode_alloc {
+       uint16_t alloc_len;
+       struct lttng_filter_bytecode b;
+};
+
+static inline
+unsigned int bytecode_get_len(struct lttng_filter_bytecode *bytecode)
+{
+       return bytecode->len;
+}
+
+#endif /* _FILTER_BYTECODE_H */
diff --git a/src/lib/lttng-ctl/filter/filter-grammar-test.c b/src/lib/lttng-ctl/filter/filter-grammar-test.c
new file mode 100644 (file)
index 0000000..2b9a27d
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * filter-grammar-test.c
+ *
+ * LTTng filter grammar test
+ *
+ * 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 "filter-bytecode.h"
+
+int main(int argc, char **argv)
+{
+       struct filter_parser_ctx *ctx;
+       int ret;
+       int print_xml = 0, generate_ir = 0, generate_bytecode = 0;
+       int i;
+
+       for (i = 1; i < argc; i++) {
+               if (strcmp(argv[i], "-p") == 0)
+                       print_xml = 1;
+               else if (strcmp(argv[i], "-i") == 0)
+                       generate_ir = 1;
+               else if (strcmp(argv[i], "-b") == 0)
+                       generate_bytecode = 1;
+               else if (strcmp(argv[i], "-d") == 0)
+                       filter_parser_debug = 1;
+       }
+
+       ctx = filter_parser_ctx_alloc(stdin);
+       if (!ctx) {
+               fprintf(stderr, "Error allocating parser\n");
+               goto alloc_error;
+       }
+       ret = filter_parser_ctx_append_ast(ctx);
+       if (ret) {
+               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) {
+                       fflush(stdout);
+                       fprintf(stderr, "XML print error\n");
+                       goto parse_error;
+               }
+       }
+       if (generate_ir) {
+               printf("Generating IR... ");
+               fflush(stdout);
+               ret = filter_visitor_ir_generate(ctx);
+               if (ret) {
+                       fprintf(stderr, "Generate IR error\n");
+                       goto parse_error;
+               }
+               printf("done\n");
+
+               printf("Validating IR... ");
+               fflush(stdout);
+               ret = filter_visitor_ir_check_binary_op_nesting(ctx);
+               if (ret) {
+                       goto parse_error;
+               }
+               printf("done\n");
+       }
+       if (generate_bytecode) {
+               printf("Generating bytecode... ");
+               fflush(stdout);
+               ret = filter_visitor_bytecode_generate(ctx);
+               if (ret) {
+                       fprintf(stderr, "Generate bytecode error\n");
+                       goto parse_error;
+               }
+               printf("done\n");
+               printf("Size of bytecode generated: %u bytes.\n",
+                       bytecode_get_len(&ctx->bytecode->b));
+       }
+#if 0
+       if (run_bytecode) {
+               int64_t retval;
+
+               printf("Interpreting bytecode... ");
+               fflush(stdout);
+               ret = bytecode_interpret(&ctx->bytecode->b, &retval, NULL);
+               if (ret) {
+                       fprintf(stderr, "Error interpreting bytecode\n");
+                       goto parse_error;
+               } else {
+                       printf("Bytecode interpret result: %" PRIi64 "\n",
+                               retval);
+               }
+               printf("done\n");
+       }
+#endif //0
+
+       filter_bytecode_free(ctx);
+       filter_ir_free(ctx);
+       filter_parser_ctx_free(ctx);
+       return 0;
+
+parse_error:
+       filter_bytecode_free(ctx);
+       filter_ir_free(ctx);
+       filter_parser_ctx_free(ctx);
+alloc_error:
+       exit(EXIT_FAILURE);
+}
diff --git a/src/lib/lttng-ctl/filter/filter-ir.h b/src/lib/lttng-ctl/filter/filter-ir.h
new file mode 100644 (file)
index 0000000..39ac76c
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef _FILTER_IR_H
+#define _FILTER_IR_H
+
+/*
+ * filter-ir.h
+ *
+ * LTTng filter ir
+ *
+ * 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 "filter-ast.h"
+
+enum ir_op_signedness {
+       IR_SIGN_UNKNOWN = 0,
+       IR_SIGNED,
+       IR_UNSIGNED,
+       IR_SIGN_DYN,            /* signedness determined dynamically */
+};
+
+enum ir_data_type {
+       IR_DATA_UNKNOWN = 0,
+       IR_DATA_STRING,
+       IR_DATA_NUMERIC,        /* numeric and boolean */
+       IR_DATA_FLOAT,
+       IR_DATA_FIELD_REF,
+};
+
+enum ir_op_type {
+       IR_OP_UNKNOWN = 0,
+       IR_OP_ROOT,
+       IR_OP_LOAD,
+       IR_OP_UNARY,
+       IR_OP_BINARY,
+       IR_OP_LOGICAL,
+};
+
+/* left or right child */
+enum ir_side {
+       IR_SIDE_UNKNOWN = 0,
+       IR_LEFT,
+       IR_RIGHT,
+};
+
+struct ir_op_root {
+       struct ir_op *child;
+};
+
+struct ir_op_load {
+       union {
+               char *string;
+               int64_t num;
+               double flt;
+               char *ref;
+       } u;
+};
+
+struct ir_op_unary {
+       enum unary_op_type type;
+       struct ir_op *child;
+};
+
+struct ir_op_binary {
+       enum op_type type;
+       struct ir_op *left;
+       struct ir_op *right;
+};
+
+struct ir_op_logical {
+       enum op_type type;
+       struct ir_op *left;
+       struct ir_op *right;
+};
+
+struct ir_op {
+       /* common to all ops */
+       enum ir_op_type op;
+       enum ir_data_type data_type;
+       enum ir_op_signedness signedness;
+       enum ir_side side;
+
+       union {
+               struct ir_op_root root;
+               struct ir_op_load load;
+               struct ir_op_unary unary;
+               struct ir_op_binary binary;
+               struct ir_op_logical logical;
+       } u;
+};
+
+#endif /* _FILTER_IR_H */
diff --git a/src/lib/lttng-ctl/filter/filter-lexer.l b/src/lib/lttng-ctl/filter/filter-lexer.l
new file mode 100644 (file)
index 0000000..de74e7a
--- /dev/null
@@ -0,0 +1,136 @@
+%{
+/*
+ * filter-lexer.l
+ *
+ * LTTng filter lexer
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include "filter-ast.h"
+#include "filter-parser.h"
+
+extern
+void setstring(struct filter_parser_ctx *parser_ctx, YYSTYPE *lvalp, const char *src);
+
+static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+       __attribute__((unused));
+static int input (yyscan_t yyscanner) __attribute__((unused));
+
+%}
+
+%x comment_ml comment_sl string_lit char_const
+%option reentrant yylineno noyywrap bison-bridge
+%option extra-type="struct filter_parser_ctx *"
+       /* bison-locations */
+
+D                              [0-9]
+L                              [a-zA-Z_]
+H                              [a-fA-F0-9]
+E                              ([Ee][+-]?{D}+)
+P                              ([Pp][+-]?{D}+)
+FS                             (f|F|l|L)
+IS                             ((u|U)|(u|U)?(l|L|ll|LL)|(l|L|ll|LL)(u|U))
+
+INTEGER_SUFFIX                 [ \n\t]*(U|UL|ULL|LU|LLU|Ul|Ull|lU|llU|u|uL|uLL|Lu|LLu|ul|ull|lu|llu)
+DIGIT                          [0-9]
+NONDIGIT                       [a-zA-Z_]
+HEXDIGIT                       [0-9A-Fa-f]
+OCTALDIGIT                     [0-7]
+UCHARLOWERCASE                 \\u{HEXDIGIT}{4}
+UCHARUPPERCASE                 \\U{HEXDIGIT}{8}
+ID_NONDIGIT                    {NONDIGIT}|{UCHARLOWERCASE}|{UCHARUPPERCASE}
+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}+)
+%%
+
+                               /*
+                                * Using start conditions to deal with comments
+                                * and strings.
+                                */ 
+
+"/*"                           BEGIN(comment_ml);
+<comment_ml>[^*\n]*            /* eat anything that's not a '*' */
+<comment_ml>"*"+[^*/\n]*       /* eat up '*'s not followed by '/'s */
+<comment_ml>\n                 ++yylineno;
+<comment_ml>"*"+"/"            BEGIN(INITIAL);
+
+"//"                           BEGIN(comment_sl);
+<comment_sl>[^\n]*\n           ++yylineno; BEGIN(INITIAL);
+
+L\'                            BEGIN(char_const); return CHARACTER_CONSTANT_START;
+\'                             BEGIN(char_const); return CHARACTER_CONSTANT_START;
+<char_const>\'                 BEGIN(INITIAL); return SQUOTE;
+
+L\"                            BEGIN(string_lit); return STRING_LITERAL_START;
+\"                             BEGIN(string_lit); return STRING_LITERAL_START;
+<string_lit>\"                 BEGIN(INITIAL); return DQUOTE;
+
+<char_const,string_lit>ESCSEQ  return ESCSEQ;
+<char_const,string_lit>\n      ; /* ignore */
+<char_const,string_lit>.       setstring(yyextra, yylval, yytext); return CHAR_STRING_TOKEN;
+
+
+0[xX]{H}+{IS}?                 setstring(yyextra, yylval, yytext); return HEXADECIMAL_CONSTANT;
+0[0-7]*{IS}?                   setstring(yyextra, yylval, yytext); return OCTAL_CONSTANT;
+[1-9]{D}*{IS}?                 setstring(yyextra, yylval, yytext); return DECIMAL_CONSTANT;
+
+{D}+{E}{FS}?                   setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+{D}*"."{D}+{E}?{FS}?           setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+{D}+"."{D}*{E}?{FS}?           setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+0[xX]{H}+{P}{FS}?              setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+0[xX]{H}*"."{H}+{P}?{FS}?      setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+0[xX]{H}+"."{H}*{P}?{FS}?      setstring(yyextra, yylval, yytext); return FLOAT_CONSTANT;
+
+"["                            return LSBRAC;
+"]"                            return RSBRAC;
+"("                            return LPAREN;
+")"                            return RPAREN;
+"{"                            return LBRAC;
+"}"                            return RBRAC;
+"->"                           return RARROW;
+
+"*"                            return STAR;
+"+"                            return PLUS;
+"-"                            return MINUS;
+
+"%"                            return MOD_OP;
+"/"                            return DIV_OP;
+">>"                           return RIGHT_OP;
+"<<"                           return LEFT_OP;
+
+"=="                           return EQ_OP;
+"!="                           return NE_OP;
+"<="                           return LE_OP;
+">="                           return GE_OP;
+"<"                            return LT_OP;
+">"                            return GT_OP;
+"&&"                           return AND_OP;
+"||"                           return OR_OP;
+"!"                            return NOT_OP;
+
+":="                           return ASSIGN;
+":"                            return COLON;
+";"                            return SEMICOLON;
+"..."                          return DOTDOTDOT;
+"."                            return DOT;
+"="                            return EQUAL;
+","                            return COMMA;
+"^"                            return XOR_BIN;
+"&"                            return AND_BIN;
+"|"                            return OR_BIN;
+"~"                            return NOT_BIN;
+{IDENTIFIER}                   printf_debug("<IDENTIFIER %s>\n", yytext); setstring(yyextra, yylval, yytext); return IDENTIFIER;
+[ \t\n]+                       ; /* ignore */
+.                              return ERROR;
+%%
diff --git a/src/lib/lttng-ctl/filter/filter-parser.y b/src/lib/lttng-ctl/filter/filter-parser.y
new file mode 100644 (file)
index 0000000..3b77528
--- /dev/null
@@ -0,0 +1,627 @@
+%{
+/*
+ * filter-parser.y
+ *
+ * LTTng filter expression parser
+ *
+ * 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
+ *
+ * Grammar inspired from http://www.quut.com/c/ANSI-C-grammar-y.html
+ */
+
+#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"
+
+__attribute__((visibility("hidden")))
+int yydebug;
+__attribute__((visibility("hidden")))
+int filter_parser_debug = 0;
+
+__attribute__((visibility("hidden")))
+int yyparse(struct filter_parser_ctx *parser_ctx);
+__attribute__((visibility("hidden")))
+int yylex(union YYSTYPE *yyval, struct filter_parser_ctx *parser_ctx);
+__attribute__((visibility("hidden")))
+int yylex_init_extra(struct filter_parser_ctx *parser_ctx, yyscan_t * ptr_yy_globals);
+__attribute__((visibility("hidden")))
+int yylex_destroy(yyscan_t yyparser_ctx);
+__attribute__((visibility("hidden")))
+void yyrestart(FILE * in_str, yyscan_t parser_ctx);
+
+struct gc_string {
+       struct cds_list_head gc;
+       size_t alloclen;
+       char s[];
+};
+
+static const char *node_type_to_str[] = {
+       [ NODE_UNKNOWN ] = "NODE_UNKNOWN",
+       [ NODE_ROOT ] = "NODE_ROOT",
+       [ NODE_EXPRESSION ] = "NODE_EXPRESSION",
+       [ NODE_OP ] = "NODE_OP",
+       [ NODE_UNARY_OP ] = "NODE_UNARY_OP",
+};
+
+__attribute__((visibility("hidden")))
+const char *node_type(struct filter_node *node)
+{
+       if (node->type < NR_NODE_TYPES)
+               return node_type_to_str[node->type];
+       else
+               return NULL;
+}
+
+static struct gc_string *gc_string_alloc(struct filter_parser_ctx *parser_ctx,
+                                        size_t len)
+{
+       struct gc_string *gstr;
+       size_t alloclen;
+
+       /* TODO: could be faster with find first bit or glib Gstring */
+       /* sizeof long to account for malloc header (int or long ?) */
+       for (alloclen = 8; alloclen < sizeof(long) + sizeof(*gstr) + len;
+            alloclen *= 2);
+
+       gstr = malloc(alloclen);
+       cds_list_add(&gstr->gc, &parser_ctx->allocated_strings);
+       gstr->alloclen = alloclen;
+       return gstr;
+}
+
+/*
+ * note: never use gc_string_append on a string that has external references.
+ * gsrc will be garbage collected immediately, and gstr might be.
+ * Should only be used to append characters to a string literal or constant.
+ */
+__attribute__((visibility("hidden")))
+struct gc_string *gc_string_append(struct filter_parser_ctx *parser_ctx,
+                                  struct gc_string *gstr,
+                                  struct gc_string *gsrc)
+{
+       size_t newlen = strlen(gsrc->s) + strlen(gstr->s) + 1;
+       size_t alloclen;
+
+       /* TODO: could be faster with find first bit or glib Gstring */
+       /* sizeof long to account for malloc header (int or long ?) */
+       for (alloclen = 8; alloclen < sizeof(long) + sizeof(*gstr) + newlen;
+            alloclen *= 2);
+
+       if (alloclen > gstr->alloclen) {
+               struct gc_string *newgstr;
+
+               newgstr = gc_string_alloc(parser_ctx, newlen);
+               strcpy(newgstr->s, gstr->s);
+               strcat(newgstr->s, gsrc->s);
+               cds_list_del(&gstr->gc);
+               free(gstr);
+               gstr = newgstr;
+       } else {
+               strcat(gstr->s, gsrc->s);
+       }
+       cds_list_del(&gsrc->gc);
+       free(gsrc);
+       return gstr;
+}
+
+__attribute__((visibility("hidden")))
+void setstring(struct filter_parser_ctx *parser_ctx, YYSTYPE *lvalp, const char *src)
+{
+       lvalp->gs = gc_string_alloc(parser_ctx, strlen(src) + 1);
+       strcpy(lvalp->gs->s, src);
+}
+
+static struct filter_node *make_node(struct filter_parser_ctx *scanner,
+                                 enum node_type type)
+{
+       struct filter_ast *ast = filter_parser_get_ast(scanner);
+       struct filter_node *node;
+
+       node = malloc(sizeof(*node));
+       if (!node)
+               return NULL;
+       memset(node, 0, sizeof(*node));
+       node->type = type;
+       cds_list_add(&node->gc, &ast->allocated_nodes);
+
+       switch (type) {
+       case NODE_ROOT:
+               fprintf(stderr, "[error] %s: trying to create root node\n", __func__);
+               break;
+
+       case NODE_EXPRESSION:
+               break;
+       case NODE_OP:
+               break;
+       case NODE_UNARY_OP:
+               break;
+
+       case NODE_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
+                       (int) type);
+               break;
+       }
+
+       return node;
+}
+
+static struct filter_node *make_op_node(struct filter_parser_ctx *scanner,
+                       enum op_type type,
+                       struct filter_node *lchild,
+                       struct filter_node *rchild)
+{
+       struct filter_ast *ast = filter_parser_get_ast(scanner);
+       struct filter_node *node;
+
+       node = malloc(sizeof(*node));
+       if (!node)
+               return NULL;
+       memset(node, 0, sizeof(*node));
+       node->type = NODE_OP;
+       cds_list_add(&node->gc, &ast->allocated_nodes);
+       node->u.op.type = type;
+       node->u.op.lchild = lchild;
+       node->u.op.rchild = rchild;
+       return node;
+}
+
+__attribute__((visibility("hidden")))
+void yyerror(struct filter_parser_ctx *parser_ctx, const char *str)
+{
+       fprintf(stderr, "error %s\n", str);
+}
+__attribute__((visibility("hidden")))
+int yywrap(void)
+{
+       return 1;
+} 
+
+#define parse_error(parser_ctx, str)                           \
+do {                                                           \
+       yyerror(parser_ctx, YY_("parse error: " str "\n"));     \
+       YYERROR;                                                \
+} while (0)
+
+static void free_strings(struct cds_list_head *list)
+{
+       struct gc_string *gstr, *tmp;
+
+       cds_list_for_each_entry_safe(gstr, tmp, list, gc)
+               free(gstr);
+}
+
+static struct filter_ast *filter_ast_alloc(void)
+{
+       struct filter_ast *ast;
+
+       ast = malloc(sizeof(*ast));
+       if (!ast)
+               return NULL;
+       memset(ast, 0, sizeof(*ast));
+       CDS_INIT_LIST_HEAD(&ast->allocated_nodes);
+       ast->root.type = NODE_ROOT;
+       return ast;
+}
+
+static void filter_ast_free(struct filter_ast *ast)
+{
+       struct filter_node *node, *tmp;
+
+       cds_list_for_each_entry_safe(node, tmp, &ast->allocated_nodes, gc)
+               free(node);
+}
+
+__attribute__((visibility("hidden")))
+int filter_parser_ctx_append_ast(struct filter_parser_ctx *parser_ctx)
+{
+       return yyparse(parser_ctx);
+}
+
+__attribute__((visibility("hidden")))
+struct filter_parser_ctx *filter_parser_ctx_alloc(FILE *input)
+{
+       struct filter_parser_ctx *parser_ctx;
+       int ret;
+
+       yydebug = filter_parser_debug;
+
+       parser_ctx = malloc(sizeof(*parser_ctx));
+       if (!parser_ctx)
+               return NULL;
+       memset(parser_ctx, 0, sizeof(*parser_ctx));
+
+       ret = yylex_init_extra(parser_ctx, &parser_ctx->scanner);
+       if (ret) {
+               fprintf(stderr, "yylex_init error\n");
+               goto cleanup_parser_ctx;
+       }
+       /* Start processing new stream */
+       yyrestart(input, parser_ctx->scanner);
+
+       parser_ctx->ast = filter_ast_alloc();
+       if (!parser_ctx->ast)
+               goto cleanup_lexer;
+       CDS_INIT_LIST_HEAD(&parser_ctx->allocated_strings);
+
+       if (yydebug)
+               fprintf(stdout, "parser_ctx input is a%s.\n",
+                       isatty(fileno(input)) ? "n interactive tty" :
+                                               " noninteractive file");
+
+       return parser_ctx;
+
+cleanup_lexer:
+       ret = yylex_destroy(parser_ctx->scanner);
+       if (!ret)
+               fprintf(stderr, "yylex_destroy error\n");
+cleanup_parser_ctx:
+       free(parser_ctx);
+       return NULL;
+}
+
+__attribute__((visibility("hidden")))
+void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx)
+{
+       int ret;
+
+       free_strings(&parser_ctx->allocated_strings);
+       filter_ast_free(parser_ctx->ast);
+       ret = yylex_destroy(parser_ctx->scanner);
+       if (ret)
+               fprintf(stderr, "yylex_destroy error\n");
+       free(parser_ctx);
+}
+
+%}
+
+%define api.pure
+       /* %locations */
+%parse-param {struct filter_parser_ctx *parser_ctx}
+%lex-param {struct filter_parser_ctx *parser_ctx}
+%start translation_unit
+%token CHARACTER_CONSTANT_START SQUOTE STRING_LITERAL_START DQUOTE
+%token ESCSEQ CHAR_STRING_TOKEN
+%token DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT FLOAT_CONSTANT
+%token LSBRAC RSBRAC LPAREN RPAREN LBRAC RBRAC RARROW
+%token STAR PLUS MINUS
+%token MOD_OP DIV_OP RIGHT_OP LEFT_OP
+%token EQ_OP NE_OP LE_OP GE_OP LT_OP GT_OP AND_OP OR_OP NOT_OP
+%token ASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA
+%token XOR_BIN AND_BIN OR_BIN NOT_BIN
+
+%token <gs> IDENTIFIER
+%token ERROR
+%union
+{
+       long long ll;
+       char c;
+       struct gc_string *gs;
+       struct filter_node *n;
+}
+
+%type <gs> s_char s_char_sequence c_char c_char_sequence
+
+%type <n> primary_expression
+%type <n> postfix_expression
+%type <n> unary_expression
+%type <n> unary_operator
+%type <n> multiplicative_expression
+%type <n> additive_expression
+%type <n> shift_expression
+%type <n> relational_expression
+%type <n> equality_expression
+%type <n> and_expression
+%type <n> exclusive_or_expression
+%type <n> inclusive_or_expression
+%type <n> logical_and_expression
+%type <n> logical_or_expression
+%type <n> expression
+
+%%
+
+
+/* 1.5 Constants */
+
+c_char_sequence:
+               c_char
+               {       $$ = $1;                                        }
+       |       c_char_sequence c_char
+               {       $$ = gc_string_append(parser_ctx, $1, $2);              }
+       ;
+
+c_char:
+               CHAR_STRING_TOKEN
+               {       $$ = yylval.gs;                                 }
+       |       ESCSEQ
+               {
+                       parse_error(parser_ctx, "escape sequences not supported yet");
+               }
+       ;
+
+/* 1.6 String literals */
+
+s_char_sequence:
+               s_char
+               {       $$ = $1;                                        }
+       |       s_char_sequence s_char
+               {       $$ = gc_string_append(parser_ctx, $1, $2);              }
+       ;
+
+s_char:
+               CHAR_STRING_TOKEN
+               {       $$ = yylval.gs;                                 }
+       |       ESCSEQ
+               {
+                       parse_error(parser_ctx, "escape sequences not supported yet");
+               }
+       ;
+
+primary_expression
+       :       IDENTIFIER
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_IDENTIFIER;
+                       $$->u.expression.u.identifier = yylval.gs->s;
+               }
+       |       DECIMAL_CONSTANT
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_CONSTANT;
+                       sscanf(yylval.gs->s, "%" PRIu64,
+                              &$$->u.expression.u.constant);
+               }
+       |       OCTAL_CONSTANT
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_CONSTANT;
+                       sscanf(yylval.gs->s, "0%" PRIo64,
+                              &$$->u.expression.u.constant);
+               }
+       |       HEXADECIMAL_CONSTANT
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_CONSTANT;
+                       sscanf(yylval.gs->s, "0x%" PRIx64,
+                              &$$->u.expression.u.constant);
+               }
+       |       FLOAT_CONSTANT
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_FLOAT_CONSTANT;
+                       sscanf(yylval.gs->s, "%lg",
+                              &$$->u.expression.u.float_constant);
+               }
+       |       STRING_LITERAL_START DQUOTE
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_STRING;
+                       $$->u.expression.u.string = "";
+               }
+       |       STRING_LITERAL_START s_char_sequence DQUOTE
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_STRING;
+                       $$->u.expression.u.string = $2->s;
+               }
+       |       CHARACTER_CONSTANT_START c_char_sequence SQUOTE
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_STRING;
+                       $$->u.expression.u.string = $2->s;
+               }
+       |       LPAREN expression RPAREN
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_NESTED;
+                       $$->u.expression.u.child = $2;
+               }
+       ;
+
+postfix_expression
+       : primary_expression
+               {       $$ = $1;                                        }
+       | postfix_expression DOT IDENTIFIER
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_IDENTIFIER;
+                       $$->u.expression.post_op = AST_LINK_DOT;
+                       $$->u.expression.u.identifier = $3->s;
+                       $$->u.expression.prev = $1;
+               }
+       | postfix_expression RARROW IDENTIFIER
+               {
+                       $$ = make_node(parser_ctx, NODE_EXPRESSION);
+                       $$->u.expression.type = AST_EXP_IDENTIFIER;
+                       $$->u.expression.post_op = AST_LINK_RARROW;
+                       $$->u.expression.u.identifier = $3->s;
+                       $$->u.expression.prev = $1;
+               }
+       ;
+
+unary_expression
+       : postfix_expression
+               {       $$ = $1;                                        }
+       | unary_operator unary_expression
+               {
+                       $$ = $1;
+                       $$->u.unary_op.child = $2;
+               }
+       ;
+
+unary_operator
+       : PLUS
+               {
+                       $$ = make_node(parser_ctx, NODE_UNARY_OP);
+                       $$->u.unary_op.type = AST_UNARY_PLUS;
+               }
+       | MINUS
+               {
+                       $$ = make_node(parser_ctx, NODE_UNARY_OP);
+                       $$->u.unary_op.type = AST_UNARY_MINUS;
+               }
+       | NOT_OP
+               {
+                       $$ = make_node(parser_ctx, NODE_UNARY_OP);
+                       $$->u.unary_op.type = AST_UNARY_NOT;
+               }
+       | NOT_BIN
+               {
+                       $$ = make_node(parser_ctx, NODE_UNARY_OP);
+                       $$->u.unary_op.type = AST_UNARY_BIN_NOT;
+               }
+       ;
+
+multiplicative_expression
+       : unary_expression
+               {       $$ = $1;                                        }
+       | multiplicative_expression STAR unary_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_MUL, $1, $3);
+               }
+       | multiplicative_expression DIV_OP unary_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_DIV, $1, $3);
+               }
+       | multiplicative_expression MOD_OP unary_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_MOD, $1, $3);
+               }
+       ;
+
+additive_expression
+       : multiplicative_expression
+               {       $$ = $1;                                        }
+       | additive_expression PLUS multiplicative_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_PLUS, $1, $3);
+               }
+       | additive_expression MINUS multiplicative_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_MINUS, $1, $3);
+               }
+       ;
+
+shift_expression
+       : additive_expression
+               {       $$ = $1;                                        }
+       | shift_expression LEFT_OP additive_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_LSHIFT, $1, $3);
+               }
+       | shift_expression RIGHT_OP additive_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_RSHIFT, $1, $3);
+               }
+       ;
+
+relational_expression
+       : shift_expression
+               {       $$ = $1;                                        }
+       | relational_expression LT_OP shift_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_LT, $1, $3);
+               }
+       | relational_expression GT_OP shift_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_GT, $1, $3);
+               }
+       | relational_expression LE_OP shift_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_LE, $1, $3);
+               }
+       | relational_expression GE_OP shift_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_GE, $1, $3);
+               }
+       ;
+
+equality_expression
+       : relational_expression
+               {       $$ = $1;                                        }
+       | equality_expression EQ_OP relational_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_EQ, $1, $3);
+               }
+       | equality_expression NE_OP relational_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_NE, $1, $3);
+               }
+       ;
+
+and_expression
+       : equality_expression
+               {       $$ = $1;                                        }
+       | and_expression AND_BIN equality_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_BIN_AND, $1, $3);
+               }
+       ;
+
+exclusive_or_expression
+       : and_expression
+               {       $$ = $1;                                        }
+       | exclusive_or_expression XOR_BIN and_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_BIN_XOR, $1, $3);
+               }
+       ;
+
+inclusive_or_expression
+       : exclusive_or_expression
+               {       $$ = $1;                                        }
+       | inclusive_or_expression OR_BIN exclusive_or_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_BIN_OR, $1, $3);
+               }
+       ;
+
+logical_and_expression
+       : inclusive_or_expression
+               {       $$ = $1;                                        }
+       | logical_and_expression AND_OP inclusive_or_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_AND, $1, $3);
+               }
+       ;
+
+logical_or_expression
+       : logical_and_expression
+               {       $$ = $1;                                        }
+       | logical_or_expression OR_OP logical_and_expression
+               {
+                       $$ = make_op_node(parser_ctx, AST_OP_OR, $1, $3);
+               }
+       ;
+
+expression
+       : logical_or_expression
+               {       $$ = $1;                                        }
+       ;
+
+translation_unit
+       : expression
+               {
+                       parser_ctx->ast->root.u.root.child = $1;
+               }
+       ;
diff --git a/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c b/src/lib/lttng-ctl/filter/filter-visitor-generate-bytecode.c
new file mode 100644 (file)
index 0000000..36d35c5
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ * filter-visitor-generate-bytecode.c
+ *
+ * LTTng filter bytecode generation
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "align.h"
+#include "filter-bytecode.h"
+#include "filter-ir.h"
+#include "filter-ast.h"
+
+#ifndef max_t
+#define max_t(type, a, b)      ((type) ((a) > (b) ? (a) : (b)))
+#endif
+
+//#define INIT_ALLOC_SIZE              PAGE_SIZE
+#define INIT_ALLOC_SIZE                4
+
+static
+int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx,
+               struct ir_op *node);
+
+static
+int bytecode_init(struct lttng_filter_bytecode_alloc **fb)
+{
+       *fb = calloc(sizeof(struct lttng_filter_bytecode_alloc) + INIT_ALLOC_SIZE, 1);
+       if (!*fb) {
+               return -ENOMEM;
+       } else {
+               (*fb)->alloc_len = INIT_ALLOC_SIZE;
+               return 0;
+       }
+}
+
+static
+int32_t bytecode_reserve(struct lttng_filter_bytecode_alloc **fb, uint32_t align, uint32_t len)
+{
+       int32_t ret;
+       uint32_t padding = offset_align((*fb)->b.len, align);
+
+       if ((*fb)->b.len + padding + len > (*fb)->alloc_len) {
+               uint32_t new_len =
+                       max_t(uint32_t, (*fb)->b.len + padding + len,
+                               (*fb)->alloc_len << 1);
+               uint32_t old_len = (*fb)->alloc_len;
+
+               if (new_len > 0xFFFF)
+                       return -EINVAL;
+               *fb = realloc(*fb, sizeof(struct lttng_filter_bytecode_alloc) + new_len);
+               if (!*fb)
+                       return -ENOMEM;
+               memset(&(*fb)->b.data[old_len], 0, new_len - old_len);
+               (*fb)->alloc_len = new_len;
+       }
+       (*fb)->b.len += padding;
+       ret = (*fb)->b.len;
+       (*fb)->b.len += len;
+       return ret;
+}
+
+static
+int bytecode_push(struct lttng_filter_bytecode_alloc **fb, const void *data,
+               uint32_t align, uint32_t len)
+{
+       int32_t offset;
+
+       offset = bytecode_reserve(fb, align, len);
+       if (offset < 0)
+               return offset;
+       memcpy(&(*fb)->b.data[offset], data, len);
+       return 0;
+}
+
+static
+int bytecode_push_logical(struct lttng_filter_bytecode_alloc **fb,
+               struct logical_op *data,
+               uint32_t align, uint32_t len,
+               uint16_t *skip_offset)
+{
+       int32_t offset;
+
+       offset = bytecode_reserve(fb, align, len);
+       if (offset < 0)
+               return offset;
+       memcpy(&(*fb)->b.data[offset], data, len);
+       *skip_offset =
+               (void *) &((struct logical_op *) &(*fb)->b.data[offset])->skip_offset
+                       - (void *) &(*fb)->b.data[0];
+       return 0;
+}
+
+static
+int bytecode_patch(struct lttng_filter_bytecode_alloc **fb,
+               const void *data,
+               uint16_t offset,
+               uint32_t len)
+{
+       if (offset >= (*fb)->b.len) {
+               return -EINVAL;
+       }
+       memcpy(&(*fb)->b.data[offset], data, len);
+       return 0;
+}
+
+static
+int visit_node_root(struct filter_parser_ctx *ctx, struct ir_op *node)
+{
+       int ret;
+       struct return_op insn;
+
+       /* Visit child */
+       ret = recursive_visit_gen_bytecode(ctx, node->u.root.child);
+       if (ret)
+               return ret;
+
+       /* Generate end of bytecode instruction */
+       insn.op = FILTER_OP_RETURN;
+       return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
+}
+
+static
+int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
+{
+       int ret;
+
+       switch (node->data_type) {
+       case IR_DATA_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] Unknown data type in %s\n",
+                       __func__);
+               return -EINVAL;
+
+       case IR_DATA_STRING:
+       {
+               struct load_op *insn;
+               uint32_t insn_len = sizeof(struct load_op)
+                       + strlen(node->u.load.u.string) + 1;
+
+               insn = calloc(insn_len, 1);
+               if (!insn)
+                       return -ENOMEM;
+               insn->op = FILTER_OP_LOAD_STRING;
+               strcpy(insn->data, node->u.load.u.string);
+               ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+               free(insn);
+               return ret;
+       }
+       case IR_DATA_NUMERIC:
+       {
+               struct load_op *insn;
+               uint32_t insn_len = sizeof(struct load_op)
+                       + sizeof(struct literal_numeric);
+
+               insn = calloc(insn_len, 1);
+               if (!insn)
+                       return -ENOMEM;
+               insn->op = FILTER_OP_LOAD_S64;
+               *(int64_t *) insn->data = node->u.load.u.num;
+               ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+               free(insn);
+               return ret;
+       }
+       case IR_DATA_FLOAT:
+       {
+               struct load_op *insn;
+               uint32_t insn_len = sizeof(struct load_op)
+                       + sizeof(struct literal_double);
+
+               insn = calloc(insn_len, 1);
+               if (!insn)
+                       return -ENOMEM;
+               insn->op = FILTER_OP_LOAD_DOUBLE;
+               *(double *) insn->data = node->u.load.u.flt;
+               ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
+               free(insn);
+               return ret;
+       }
+       case IR_DATA_FIELD_REF:
+       {
+               struct load_op *insn;
+               uint32_t insn_len = sizeof(struct load_op)
+                       + sizeof(struct field_ref);
+               struct field_ref ref_offset;
+               uint16_t reloc_offset;
+
+               insn = calloc(insn_len, 1);
+               if (!insn)
+                       return -ENOMEM;
+               insn->op = FILTER_OP_LOAD_FIELD_REF;
+               ref_offset.offset = (uint16_t) -1U;
+               memcpy(insn->data, &ref_offset, sizeof(ref_offset));
+               /* reloc_offset points to struct load_op */
+               reloc_offset = bytecode_get_len(&ctx->bytecode->b);
+               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;
+       }
+       }
+}
+
+static
+int visit_node_unary(struct filter_parser_ctx *ctx, struct ir_op *node)
+{
+       int ret;
+       struct unary_op insn;
+
+       /* Visit child */
+       ret = recursive_visit_gen_bytecode(ctx, node->u.unary.child);
+       if (ret)
+               return ret;
+
+       /* Generate end of bytecode instruction */
+       switch (node->u.unary.type) {
+       case AST_UNARY_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] Unknown unary node type in %s\n",
+                       __func__);
+               return -EINVAL;
+       case AST_UNARY_PLUS:
+               /* Nothing to do. */
+               return 0;
+       case AST_UNARY_MINUS:
+               insn.op = FILTER_OP_UNARY_MINUS;
+               return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
+       case AST_UNARY_NOT:
+               insn.op = FILTER_OP_UNARY_NOT;
+               return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
+       }
+}
+
+/*
+ * Binary comparator nesting is disallowed. This allows fitting into
+ * only 2 registers.
+ */
+static
+int visit_node_binary(struct filter_parser_ctx *ctx, struct ir_op *node)
+{
+       int ret;
+       struct binary_op insn;
+
+       /* Visit child */
+       ret = recursive_visit_gen_bytecode(ctx, node->u.binary.left);
+       if (ret)
+               return ret;
+       ret = recursive_visit_gen_bytecode(ctx, node->u.binary.right);
+       if (ret)
+               return ret;
+
+       switch (node->u.binary.type) {
+       case AST_OP_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] Unknown unary node type in %s\n",
+                       __func__);
+               return -EINVAL;
+
+       case AST_OP_AND:
+       case AST_OP_OR:
+               fprintf(stderr, "[error] Unexpected logical node type in %s\n",
+                       __func__);
+               return -EINVAL;
+
+       case AST_OP_MUL:
+               insn.op = FILTER_OP_MUL;
+               break;
+       case AST_OP_DIV:
+               insn.op = FILTER_OP_DIV;
+               break;
+       case AST_OP_MOD:
+               insn.op = FILTER_OP_MOD;
+               break;
+       case AST_OP_PLUS:
+               insn.op = FILTER_OP_PLUS;
+               break;
+       case AST_OP_MINUS:
+               insn.op = FILTER_OP_MINUS;
+               break;
+       case AST_OP_RSHIFT:
+               insn.op = FILTER_OP_RSHIFT;
+               break;
+       case AST_OP_LSHIFT:
+               insn.op = FILTER_OP_LSHIFT;
+               break;
+       case AST_OP_BIN_AND:
+               insn.op = FILTER_OP_BIN_AND;
+               break;
+       case AST_OP_BIN_OR:
+               insn.op = FILTER_OP_BIN_OR;
+               break;
+       case AST_OP_BIN_XOR:
+               insn.op = FILTER_OP_BIN_XOR;
+               break;
+
+       case AST_OP_EQ:
+               insn.op = FILTER_OP_EQ;
+               break;
+       case AST_OP_NE:
+               insn.op = FILTER_OP_NE;
+               break;
+       case AST_OP_GT:
+               insn.op = FILTER_OP_GT;
+               break;
+       case AST_OP_LT:
+               insn.op = FILTER_OP_LT;
+               break;
+       case AST_OP_GE:
+               insn.op = FILTER_OP_GE;
+               break;
+       case AST_OP_LE:
+               insn.op = FILTER_OP_LE;
+               break;
+       }
+       return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
+}
+
+/*
+ * A logical op always return a s64 (1 or 0).
+ */
+static
+int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node)
+{
+       int ret;
+       struct logical_op insn;
+       uint16_t skip_offset_loc;
+       uint16_t target_loc;
+
+       /* Visit left child */
+       ret = recursive_visit_gen_bytecode(ctx, node->u.binary.left);
+       if (ret)
+               return ret;
+       /* 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_FLOAT) {
+               struct cast_op cast_insn;
+
+               if (node->u.binary.left->data_type == IR_DATA_FIELD_REF) {
+                       cast_insn.op = FILTER_OP_CAST_TO_S64;
+               } else {
+                       cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
+               }
+               ret = bytecode_push(&ctx->bytecode, &cast_insn,
+                                       1, sizeof(cast_insn));
+               if (ret)
+                       return ret;
+       }
+       switch (node->u.logical.type) {
+       default:
+               fprintf(stderr, "[error] Unknown node type in %s\n",
+                       __func__);
+               return -EINVAL;
+
+       case AST_OP_AND:
+               insn.op = FILTER_OP_AND;
+               break;
+       case AST_OP_OR:
+               insn.op = FILTER_OP_OR;
+               break;
+       }
+       insn.skip_offset = (uint16_t) -1UL;     /* Temporary */
+       ret = bytecode_push_logical(&ctx->bytecode, &insn, 1, sizeof(insn),
+                       &skip_offset_loc);
+       if (ret)
+               return ret;
+       /* Visit right child */
+       ret = recursive_visit_gen_bytecode(ctx, node->u.binary.right);
+       if (ret)
+               return ret;
+       /* 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_FLOAT) {
+               struct cast_op cast_insn;
+
+               if (node->u.binary.right->data_type == IR_DATA_FIELD_REF) {
+                       cast_insn.op = FILTER_OP_CAST_TO_S64;
+               } else {
+                       cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
+               }
+               ret = bytecode_push(&ctx->bytecode, &cast_insn,
+                                       1, sizeof(cast_insn));
+               if (ret)
+                       return ret;
+       }
+       /* We now know where the logical op can skip. */
+       target_loc = (uint16_t) bytecode_get_len(&ctx->bytecode->b);
+       ret = bytecode_patch(&ctx->bytecode,
+                       &target_loc,                    /* Offset to jump to */
+                       skip_offset_loc,                /* Where to patch */
+                       sizeof(uint16_t));
+       return ret;
+}
+
+/*
+ * Postorder traversal of the tree. We need the children result before
+ * we can evaluate the parent.
+ */
+static
+int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx,
+               struct ir_op *node)
+{
+       switch (node->op) {
+       case IR_OP_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] Unknown node type in %s\n",
+                       __func__);
+               return -EINVAL;
+
+       case IR_OP_ROOT:
+               return visit_node_root(ctx, node);
+       case IR_OP_LOAD:
+               return visit_node_load(ctx, node);
+       case IR_OP_UNARY:
+               return visit_node_unary(ctx, node);
+       case IR_OP_BINARY:
+               return visit_node_binary(ctx, node);
+       case IR_OP_LOGICAL:
+               return visit_node_logical(ctx, node);
+       }
+}
+
+__attribute__((visibility("hidden")))
+void filter_bytecode_free(struct filter_parser_ctx *ctx)
+{
+       free(ctx->bytecode);
+       ctx->bytecode = NULL;
+       free(ctx->bytecode_reloc);
+       ctx->bytecode_reloc = NULL;
+}
+
+__attribute__((visibility("hidden")))
+int filter_visitor_bytecode_generate(struct filter_parser_ctx *ctx)
+{
+       int ret;
+
+       ret = bytecode_init(&ctx->bytecode);
+       if (ret)
+               return ret;
+       ret = bytecode_init(&ctx->bytecode_reloc);
+       if (ret)
+               goto error;
+       ret = recursive_visit_gen_bytecode(ctx, ctx->ir_root);
+       if (ret)
+               goto error;
+
+       /* Finally, append symbol table to bytecode */
+       ctx->bytecode->b.reloc_table_offset = bytecode_get_len(&ctx->bytecode->b);
+       return bytecode_push(&ctx->bytecode, ctx->bytecode_reloc->b.data,
+                       1, bytecode_get_len(&ctx->bytecode_reloc->b));
+
+error:
+       filter_bytecode_free(ctx);
+       return ret;
+}
diff --git a/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c b/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c
new file mode 100644 (file)
index 0000000..eec78fc
--- /dev/null
@@ -0,0 +1,774 @@
+/*
+ * filter-visitor-generate-ir.c
+ *
+ * LTTng filter generate intermediate representation
+ *
+ * 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 "filter-ir.h"
+
+static
+struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
+               struct filter_node *node, enum ir_side side);
+
+static
+struct ir_op *make_op_root(struct ir_op *child, enum ir_side side)
+{
+       struct ir_op *op;
+
+       op = calloc(sizeof(struct ir_op), 1);
+       if (!op)
+               return NULL;
+       switch (child->data_type) {
+       case IR_DATA_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] Unknown root child data type\n");
+               return NULL;
+       case IR_DATA_STRING:
+               fprintf(stderr, "[error] String cannot be root data type\n");
+               return NULL;
+       case IR_DATA_NUMERIC:
+       case IR_DATA_FIELD_REF:
+               /* ok */
+               break;
+       }
+       op->op = IR_OP_ROOT;
+       op->side = side;
+       op->data_type = child->data_type;
+       op->signedness = child->signedness;
+       op->u.root.child = child;
+       return op;
+}
+
+static
+struct ir_op *make_op_load_string(char *string, enum ir_side side)
+{
+       struct ir_op *op;
+
+       op = calloc(sizeof(struct ir_op), 1);
+       if (!op)
+               return NULL;
+       op->op = IR_OP_LOAD;
+       op->data_type = IR_DATA_STRING;
+       op->signedness = IR_SIGN_UNKNOWN;
+       op->side = side;
+       op->u.load.u.string = strdup(string);
+       if (!op->u.load.u.string) {
+               free(op);
+               return NULL;
+       }
+       return op;
+}
+
+static
+struct ir_op *make_op_load_numeric(int64_t v, enum ir_side side)
+{
+       struct ir_op *op;
+
+       op = calloc(sizeof(struct ir_op), 1);
+       if (!op)
+               return NULL;
+       op->op = IR_OP_LOAD;
+       op->data_type = IR_DATA_NUMERIC;
+       /* TODO: for now, all numeric values are signed */
+       op->signedness = IR_SIGNED;
+       op->side = side;
+       op->u.load.u.num = v;
+       return op;
+}
+
+static
+struct ir_op *make_op_load_float(double v, enum ir_side side)
+{
+       struct ir_op *op;
+
+       op = calloc(sizeof(struct ir_op), 1);
+       if (!op)
+               return NULL;
+       op->op = IR_OP_LOAD;
+       op->data_type = IR_DATA_FLOAT;
+       op->signedness = IR_SIGN_UNKNOWN;
+       op->side = side;
+       op->u.load.u.flt = v;
+       return op;
+}
+
+static
+struct ir_op *make_op_load_field_ref(char *string, enum ir_side side)
+{
+       struct ir_op *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) {
+               free(op);
+               return NULL;
+       }
+       return op;
+}
+
+static
+struct ir_op *make_op_unary(enum unary_op_type unary_op_type,
+                       const char *op_str, enum ir_op_signedness signedness,
+                       struct ir_op *child, enum ir_side side)
+{
+       struct ir_op *op = NULL;
+
+       if (child->data_type == IR_DATA_STRING) {
+               fprintf(stderr, "[error] unary operation '%s' not allowed on string literal\n", op_str);
+               goto error;
+       }
+
+       op = calloc(sizeof(struct ir_op), 1);
+       if (!op)
+               return NULL;
+       op->op = IR_OP_UNARY;
+       op->data_type = child->data_type;
+       op->signedness = signedness;
+       op->side = side;
+       op->u.unary.type = unary_op_type;
+       op->u.unary.child = child;
+       return op;
+
+error:
+       free(op);
+       return NULL;
+}
+
+/*
+ * unary + is pretty much useless.
+ */
+static
+struct ir_op *make_op_unary_plus(struct ir_op *child, enum ir_side side)
+{
+       return make_op_unary(AST_UNARY_PLUS, "+", child->signedness,
+                       child, side);
+}
+
+static
+struct ir_op *make_op_unary_minus(struct ir_op *child, enum ir_side side)
+{
+       return make_op_unary(AST_UNARY_MINUS, "-", child->signedness,
+                       child, side);
+}
+
+static
+struct ir_op *make_op_unary_not(struct ir_op *child, enum ir_side side)
+{
+       return make_op_unary(AST_UNARY_NOT, "!", child->signedness,
+                       child, side);
+}
+
+#if 0
+static
+struct ir_op *make_op_binary_numeric(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 (right->data_type == IR_DATA_STRING
+                       || right->data_type == IR_DATA_STRING) {
+               fprintf(stderr, "[error] binary operation '%s' not allowed on string literal\n", op_str);
+               goto error;
+       }
+       if (left->data_type == IR_DATA_UNKNOWN
+               || right->data_type == IR_DATA_UNKNOWN) {
+               fprintf(stderr, "[error] binary operation '%s' has unknown type for both children\n", op_str);
+               goto error;
+
+       }
+
+       op = calloc(sizeof(struct ir_op_binary), 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;
+       op->side = side;
+
+       /*
+        * The field that is not a field ref will select type.
+        */
+       if (left->data_type != IR_DATA_FIELD_REF)
+               op->data_type = left->data_type;
+       else
+               op->data_type = right->data_type;
+
+       if (left->signedness == IR_SIGNED
+                       || right->signedness == IR_SIGNED) {
+               op->signedness = IR_SIGNED;
+       } else if (left->signedness == IR_SIGN_DYN
+                       || right->signedness == IR_SIGN_DYN) {
+               op->signedness = IR_SIGN_DYN;
+       } else if (left->signedness == IR_UNSIGNED
+                       && right->signedness == IR_UNSIGNED) {
+               op->signedness = IR_UNSIGNED;
+       } else {
+               op->signedness = IR_SIGN_UNKNOWN;
+       }
+
+       return op;
+
+error:
+       free(op);
+       return NULL;
+}
+
+static
+struct ir_op *make_op_binary_mul(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_MUL, "*", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_div(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_DIV, "/", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_mod(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_MOD, "%", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_plus(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_PLUS, "+", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_minus(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_MINUS, "-", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_rshift(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_RSHIFT, ">>", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_lshift(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_LSHIFT, "<<", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_and(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_BIN_AND, "&", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_or(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_BIN_OR, "|", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_xor(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_numeric(AST_OP_BIN_XOR, "^", left, right, side);
+}
+#endif //0
+
+static
+struct ir_op *make_op_binary_compare(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] binary operation '%s' has unknown operand type\n", op_str);
+               goto error;
+
+       }
+       if ((left->data_type == IR_DATA_STRING
+               && (right->data_type == IR_DATA_NUMERIC || right->data_type == IR_DATA_FLOAT))
+               || ((left->data_type == IR_DATA_NUMERIC || left->data_type == IR_DATA_FLOAT) &&
+                       right->data_type == IR_DATA_STRING)) {
+               fprintf(stderr, "[error] binary operation '%s' operand type mismatch\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 boolean, represented as 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_eq(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_compare(AST_OP_EQ, "==", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_ne(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_compare(AST_OP_NE, "!=", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_gt(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_compare(AST_OP_GT, ">", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_lt(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_compare(AST_OP_LT, "<", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_ge(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_compare(AST_OP_GE, ">=", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_le(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_compare(AST_OP_LE, "<=", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_logical(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] 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] logical binary operation '%s' cannot have string operand\n", op_str);
+               goto error;
+       }
+
+       op = calloc(sizeof(struct ir_op), 1);
+       if (!op)
+               return NULL;
+       op->op = IR_OP_LOGICAL;
+       op->u.binary.type = bin_op_type;
+       op->u.binary.left = left;
+       op->u.binary.right = right;
+
+       /* we return a boolean, represented as 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)
+{
+       return make_op_binary_logical(AST_OP_AND, "&&", left, right, side);
+}
+
+static
+struct ir_op *make_op_binary_logical_or(struct ir_op *left, struct ir_op *right,
+               enum ir_side side)
+{
+       return make_op_binary_logical(AST_OP_OR, "||", left, right, side);
+}
+
+static
+void filter_free_ir_recursive(struct ir_op *op)
+{
+       if (!op)
+               return;
+       switch (op->op) {
+       case IR_OP_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] Unknown op type in %s\n",
+                       __func__);
+               break;
+       case IR_OP_ROOT:
+               filter_free_ir_recursive(op->u.root.child);
+               break;
+       case IR_OP_LOAD:
+               switch (op->data_type) {
+               case IR_DATA_STRING:
+                       free(op->u.load.u.string);
+                       break;
+               case IR_DATA_FIELD_REF:
+                       free(op->u.load.u.ref);
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case IR_OP_UNARY:
+               filter_free_ir_recursive(op->u.unary.child);
+               break;
+       case IR_OP_BINARY:
+               filter_free_ir_recursive(op->u.binary.left);
+               filter_free_ir_recursive(op->u.binary.right);
+               break;
+       case IR_OP_LOGICAL:
+               filter_free_ir_recursive(op->u.logical.left);
+               filter_free_ir_recursive(op->u.logical.right);
+               break;
+       }
+       free(op);
+}
+
+static
+struct ir_op *make_expression(struct filter_parser_ctx *ctx,
+               struct filter_node *node, enum ir_side side)
+{
+       switch (node->u.expression.type) {
+       case AST_EXP_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown expression type\n", __func__);
+               return NULL;
+
+       case AST_EXP_STRING:
+               return make_op_load_string(node->u.expression.u.string, side);
+       case AST_EXP_CONSTANT:
+               return make_op_load_numeric(node->u.expression.u.constant,
+                                       side);
+       case AST_EXP_FLOAT_CONSTANT:
+               return make_op_load_float(node->u.expression.u.float_constant,
+                                       side);
+       case AST_EXP_IDENTIFIER:
+               if (node->u.expression.pre_op != AST_LINK_UNKNOWN) {
+                       fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__);
+                       return NULL;
+               }
+               return make_op_load_field_ref(node->u.expression.u.identifier,
+                                       side);
+       case AST_EXP_NESTED:
+               return generate_ir_recursive(ctx, node->u.expression.u.child,
+                                       side);
+       }
+}
+
+static
+struct ir_op *make_op(struct filter_parser_ctx *ctx,
+               struct filter_node *node, enum ir_side side)
+{
+       struct ir_op *op = NULL, *lchild, *rchild;
+       const char *op_str = "?";
+
+       switch (node->u.op.type) {
+       case AST_OP_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown binary op type\n", __func__);
+               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).
+        */
+       case AST_OP_MUL:
+               op_str = "*";
+               goto error_not_supported;
+       case AST_OP_DIV:
+               op_str = "/";
+               goto error_not_supported;
+       case AST_OP_MOD:
+               op_str = "%";
+               goto error_not_supported;
+       case AST_OP_PLUS:
+               op_str = "+";
+               goto error_not_supported;
+       case AST_OP_MINUS:
+               op_str = "-";
+               goto error_not_supported;
+       case AST_OP_RSHIFT:
+               op_str = ">>";
+               goto error_not_supported;
+       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_EQ:
+       case AST_OP_NE:
+       case AST_OP_GT:
+       case AST_OP_LT:
+       case AST_OP_GE:
+       case AST_OP_LE:
+               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_AND:
+       case AST_OP_OR:
+               /*
+                * Both children considered as left, since we need to
+                * populate R0.
+                */
+               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_LEFT);
+               if (!rchild) {
+                       filter_free_ir_recursive(lchild);
+                       return NULL;
+               }
+               break;
+       }
+
+       switch (node->u.op.type) {
+       case AST_OP_AND:
+               op = make_op_binary_logical_and(lchild, rchild, side);
+               break;
+       case AST_OP_OR:
+               op = make_op_binary_logical_or(lchild, rchild, side);
+               break;
+       case AST_OP_EQ:
+               op = make_op_binary_eq(lchild, rchild, side);
+               break;
+       case AST_OP_NE:
+               op = make_op_binary_ne(lchild, rchild, side);
+               break;
+       case AST_OP_GT:
+               op = make_op_binary_gt(lchild, rchild, side);
+               break;
+       case AST_OP_LT:
+               op = make_op_binary_lt(lchild, rchild, side);
+               break;
+       case AST_OP_GE:
+               op = make_op_binary_ge(lchild, rchild, side);
+               break;
+       case AST_OP_LE:
+               op = make_op_binary_le(lchild, rchild, side);
+               break;
+       default:
+               break;
+       }
+
+       if (!op) {
+               filter_free_ir_recursive(rchild);
+               filter_free_ir_recursive(lchild);
+       }
+       return op;
+
+error_not_supported:
+       fprintf(stderr, "[error] %s: binary operation '%s' not supported\n",
+               __func__, op_str);
+       return NULL;
+}
+
+static
+struct ir_op *make_unary_op(struct filter_parser_ctx *ctx,
+               struct filter_node *node, enum ir_side side)
+{
+       const char *op_str = "?";
+
+       switch (node->u.unary_op.type) {
+       case AST_UNARY_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown unary op type\n", __func__);
+               return NULL;
+
+       case AST_UNARY_PLUS:
+       {
+               struct ir_op *op, *child;
+
+               child = generate_ir_recursive(ctx, node->u.unary_op.child,
+                                       side);
+               if (!child)
+                       return NULL;
+               op = make_op_unary_plus(child, side);
+               if (!op) {
+                       filter_free_ir_recursive(child);
+                       return NULL;
+               }
+               return op;
+       }
+       case AST_UNARY_MINUS:
+       {
+               struct ir_op *op, *child;
+
+               child = generate_ir_recursive(ctx, node->u.unary_op.child,
+                                       side);
+               if (!child)
+                       return NULL;
+               op = make_op_unary_minus(child, side);
+               if (!op) {
+                       filter_free_ir_recursive(child);
+                       return NULL;
+               }
+               return op;
+       }
+       case AST_UNARY_NOT:
+       {
+               struct ir_op *op, *child;
+
+               child = generate_ir_recursive(ctx, node->u.unary_op.child,
+                                       side);
+               if (!child)
+                       return NULL;
+               op = make_op_unary_not(child, side);
+               if (!op) {
+                       filter_free_ir_recursive(child);
+                       return NULL;
+               }
+               return op;
+       }
+       case AST_UNARY_BIN_NOT:
+       {
+               op_str = "~";
+               goto error_not_supported;
+       }
+       }
+
+error_not_supported:
+       fprintf(stderr, "[error] %s: unary operation '%s' not supported\n",
+               __func__, op_str);
+       return NULL;
+}
+
+static
+struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx,
+               struct filter_node *node, enum ir_side side)
+{
+       switch (node->type) {
+       case NODE_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown node type\n", __func__);
+               return NULL;
+
+       case NODE_ROOT:
+       {
+               struct ir_op *op, *child;
+
+               child = generate_ir_recursive(ctx, node->u.root.child,
+                                       side);
+               if (!child)
+                       return NULL;
+               op = make_op_root(child, side);
+               if (!op) {
+                       filter_free_ir_recursive(child);
+                       return NULL;
+               }
+               return op;
+       }
+       case NODE_EXPRESSION:
+               return make_expression(ctx, node, side);
+       case NODE_OP:
+               return make_op(ctx, node, side);
+       case NODE_UNARY_OP:
+               return make_unary_op(ctx, node, side);
+       }
+       return 0;
+}
+
+__attribute__((visibility("hidden")))
+void filter_ir_free(struct filter_parser_ctx *ctx)
+{
+       filter_free_ir_recursive(ctx->ir_root);
+       ctx->ir_root = NULL;
+}
+
+__attribute__((visibility("hidden")))
+int filter_visitor_ir_generate(struct filter_parser_ctx *ctx)
+{
+       struct ir_op *op;
+
+       op = generate_ir_recursive(ctx, &ctx->ast->root, IR_LEFT);
+       if (!op) {
+               return -EINVAL;
+       }
+       ctx->ir_root = op;
+       return 0;
+}
diff --git a/src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-comparator.c b/src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-comparator.c
new file mode 100644 (file)
index 0000000..13da71e
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * filter-visitor-ir-check-binary-comparator.c
+ *
+ * LTTng filter IR check binary comparator
+ *
+ * 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 "filter-ir.h"
+
+static
+int check_bin_comparator(struct ir_op *node)
+{
+       switch (node->op) {
+       case IR_OP_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown op type\n", __func__);
+               return -EINVAL;
+
+       case IR_OP_ROOT:
+               return check_bin_comparator(node->u.root.child);
+       case IR_OP_LOAD:
+               return 0;
+       case IR_OP_UNARY:
+               return check_bin_comparator(node->u.unary.child);
+       case IR_OP_BINARY:
+       {
+               int ret;
+
+               if (node->u.binary.left->data_type == IR_DATA_STRING
+                               || node->u.binary.right->data_type
+                                       == IR_DATA_STRING) {
+                       if (node->u.binary.type != AST_OP_EQ
+                                       && node->u.binary.type != AST_OP_NE) {
+                               fprintf(stderr, "[error] Only '==' and '!=' comparators are allowed for strings\n");
+                               return -EINVAL;
+                       }
+               }
+
+               ret = check_bin_comparator(node->u.binary.left);
+               if (ret)
+                       return ret;
+               return check_bin_comparator(node->u.binary.right);
+       }
+       case IR_OP_LOGICAL:
+       {
+               int ret;
+
+               ret = check_bin_comparator(node->u.logical.left);
+               if (ret)
+                       return ret;
+               return check_bin_comparator(node->u.logical.right);
+       }
+       }
+}
+
+int filter_visitor_ir_check_binary_comparator(struct filter_parser_ctx *ctx)
+{
+       return check_bin_comparator(ctx->ir_root);
+}
diff --git a/src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-op-nesting.c b/src/lib/lttng-ctl/filter/filter-visitor-ir-check-binary-op-nesting.c
new file mode 100644 (file)
index 0000000..bb9fd12
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * filter-visitor-ir-check-binary-op-nesting.c
+ *
+ * LTTng filter IR check binary op nesting
+ *
+ * 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 "filter-ir.h"
+
+static
+int check_bin_op_nesting_recursive(struct ir_op *node, int nesting)
+{
+       switch (node->op) {
+       case IR_OP_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown op type\n", __func__);
+               return -EINVAL;
+
+       case IR_OP_ROOT:
+               return check_bin_op_nesting_recursive(node->u.root.child,
+                               nesting);
+       case IR_OP_LOAD:
+               return 0;
+       case IR_OP_UNARY:
+               return check_bin_op_nesting_recursive(node->u.unary.child,
+                               nesting);
+       case IR_OP_BINARY:
+       {
+               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++);
+               if (ret)
+                       return ret;
+               return check_bin_op_nesting_recursive(node->u.binary.right,
+                               nesting++);
+       }
+       case IR_OP_LOGICAL:
+       {
+               int ret;
+
+               ret = check_bin_op_nesting_recursive(node->u.logical.left,
+                               nesting);
+               if (ret)
+                       return ret;
+               return check_bin_op_nesting_recursive(node->u.logical.right,
+                               nesting);
+       }
+       }
+}
+
+__attribute__((visibility("hidden")))
+int filter_visitor_ir_check_binary_op_nesting(struct filter_parser_ctx *ctx)
+{
+       return check_bin_op_nesting_recursive(ctx->ir_root, 0);
+}
diff --git a/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c b/src/lib/lttng-ctl/filter/filter-visitor-set-parent.c
new file mode 100644 (file)
index 0000000..fd895f6
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * 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"
+
+static
+int update_child(struct filter_node *parent,
+               struct filter_node *old_child,
+               struct filter_node *new_child)
+{
+       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:
+                       {
+                               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) {
+                                               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;
+}
+
+__attribute__((visibility("hidden")))
+int filter_visitor_set_parent(struct filter_parser_ctx *ctx)
+{
+       return recursive_visit_set_parent(&ctx->ast->root, NULL);
+}
diff --git a/src/lib/lttng-ctl/filter/filter-visitor-xml.c b/src/lib/lttng-ctl/filter/filter-visitor-xml.c
new file mode 100644 (file)
index 0000000..90a336d
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * filter-visitor-xml.c
+ *
+ * LTTng filter XML pretty printer 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"
+
+#define fprintf_dbg(fd, fmt, args...)  fprintf(fd, "%s: " fmt, __func__, ## args)
+
+static
+int recursive_visit_print(struct filter_node *node, FILE *stream, int indent);
+
+static
+void print_tabs(FILE *fd, int depth)
+{
+       int i;
+
+       for (i = 0; i < depth; i++)
+               fprintf(fd, "\t");
+}
+
+static
+int recursive_visit_print_expression(struct filter_node *node,
+               FILE *stream, int indent)
+{
+       if (!node) {
+               fprintf(stderr, "[error] %s: NULL child\n", __func__);
+               return -EINVAL;
+       }
+       switch (node->u.expression.type) {
+       case AST_EXP_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown expression\n", __func__);
+               return -EINVAL;
+       case AST_EXP_STRING:
+               print_tabs(stream, indent);
+               fprintf(stream, "<string value=\"%s\"/>\n",
+                       node->u.expression.u.string);
+               break;
+       case AST_EXP_CONSTANT:
+               print_tabs(stream, indent);
+               fprintf(stream, "<constant value=\"%" PRIu64 "\"/>\n",
+                       node->u.expression.u.constant);
+               break;
+       case AST_EXP_FLOAT_CONSTANT:
+               print_tabs(stream, indent);
+               fprintf(stream, "<float_constant value=\"%lg\"/>\n",
+                       node->u.expression.u.float_constant);
+               break;
+       case AST_EXP_IDENTIFIER:
+               print_tabs(stream, indent);
+               fprintf(stream, "<identifier value=\"%s\"/>\n",
+                       node->u.expression.u.identifier);
+               while (node->u.expression.next) {
+                       print_tabs(stream, indent);
+                       fprintf(stream, "<link type=\"");
+                       switch (node->u.expression.pre_op) {
+                       case AST_LINK_UNKNOWN:
+                       default:
+                               fprintf(stderr, "[error] %s: unknown link\n", __func__);
+                               return -EINVAL;
+                       case AST_LINK_DOT:
+                               fprintf(stream, ".");
+                               break;
+                       case AST_LINK_RARROW:
+                               fprintf(stream, "->");
+                               break;
+                       }
+                       fprintf(stream, "\"/>\n");
+
+                       node = node->u.expression.next;
+                       if (node->type != NODE_EXPRESSION ||
+                               node->u.expression.type != AST_EXP_IDENTIFIER) {
+                               fprintf(stderr, "[error] %s: expecting identifier before link\n", __func__);
+                               return -EINVAL;
+                       }
+
+                       print_tabs(stream, indent);
+                       fprintf(stream, "<identifier value=\"%s\"/>\n",
+                               node->u.expression.u.identifier);
+               }
+               break;
+       case AST_EXP_NESTED:
+               return recursive_visit_print(node->u.expression.u.child,
+                               stream, indent + 1);
+       }
+       return 0;
+}
+
+
+static
+int recursive_visit_print(struct filter_node *node, FILE *stream, int indent)
+{
+       int ret;
+
+       if (!node) {
+               fprintf(stderr, "[error] %s: NULL child\n", __func__);
+               return -EINVAL;
+       }
+       switch (node->type) {
+       case NODE_UNKNOWN:
+       default:
+               fprintf(stderr, "[error] %s: unknown node type\n", __func__);
+               return -EINVAL;
+       case NODE_ROOT:
+               print_tabs(stream, indent);
+               fprintf(stream, "<root>\n");
+               ret = recursive_visit_print(node->u.root.child, stream,
+                                       indent + 1);
+               print_tabs(stream, indent);
+               fprintf(stream, "</root>\n");
+               return ret;
+       case NODE_EXPRESSION:
+               print_tabs(stream, indent);
+               fprintf(stream, "<expression>\n");
+               ret = recursive_visit_print_expression(node, stream,
+                                       indent + 1);
+               print_tabs(stream, indent);
+               fprintf(stream, "</expression>\n");
+               return ret;
+       case NODE_OP:
+               print_tabs(stream, indent);
+               fprintf(stream, "<op type=");
+               switch (node->u.op.type) {
+               case AST_OP_UNKNOWN:
+               default:
+                       fprintf(stderr, "[error] %s: unknown op\n", __func__);
+                       return -EINVAL;
+               case AST_OP_MUL:
+                       fprintf(stream, "\"*\"");
+                       break;
+               case AST_OP_DIV:
+                       fprintf(stream, "\"/\"");
+                       break;
+               case AST_OP_MOD:
+                       fprintf(stream, "\"%%\"");
+                       break;
+               case AST_OP_PLUS:
+                       fprintf(stream, "\"+\"");
+                       break;
+               case AST_OP_MINUS:
+                       fprintf(stream, "\"-\"");
+                       break;
+               case AST_OP_RSHIFT:
+                       fprintf(stream, "\">>\"");
+                       break;
+               case AST_OP_LSHIFT:
+                       fprintf(stream, "\"<<\"");
+                       break;
+               case AST_OP_AND:
+                       fprintf(stream, "\"&&\"");
+                       break;
+               case AST_OP_OR:
+                       fprintf(stream, "\"||\"");
+                       break;
+               case AST_OP_BIN_AND:
+                       fprintf(stream, "\"&\"");
+                       break;
+               case AST_OP_BIN_OR:
+                       fprintf(stream, "\"|\"");
+                       break;
+               case AST_OP_BIN_XOR:
+                       fprintf(stream, "\"^\"");
+                       break;
+
+               case AST_OP_EQ:
+                       fprintf(stream, "\"==\"");
+                       break;
+               case AST_OP_NE:
+                       fprintf(stream, "\"!=\"");
+                       break;
+               case AST_OP_GT:
+                       fprintf(stream, "\">\"");
+                       break;
+               case AST_OP_LT:
+                       fprintf(stream, "\"<\"");
+                       break;
+               case AST_OP_GE:
+                       fprintf(stream, "\">=\"");
+                       break;
+               case AST_OP_LE:
+                       fprintf(stream, "\"<=\"");
+                       break;
+               }
+               fprintf(stream, ">\n");
+               ret = recursive_visit_print(node->u.op.lchild,
+                                       stream, indent + 1);
+               if (ret)
+                       return ret;
+               ret = recursive_visit_print(node->u.op.rchild,
+                                       stream, indent + 1);
+               if (ret)
+                       return ret;
+               print_tabs(stream, indent);
+               fprintf(stream, "</op>\n");
+               return ret;
+       case NODE_UNARY_OP:
+               print_tabs(stream, indent);
+               fprintf(stream, "<unary_op type=");
+               switch (node->u.unary_op.type) {
+               case AST_UNARY_UNKNOWN:
+               default:
+                       fprintf(stderr, "[error] %s: unknown unary_op\n", __func__);
+                       return -EINVAL;
+               case AST_UNARY_PLUS:
+                       fprintf(stream, "\"+\"");
+                       break;
+               case AST_UNARY_MINUS:
+                       fprintf(stream, "\"-\"");
+                       break;
+               case AST_UNARY_NOT:
+                       fprintf(stream, "\"!\"");
+                       break;
+               }
+               fprintf(stream, ">\n");
+               ret = recursive_visit_print(node->u.unary_op.child,
+                                       stream, indent + 1);
+               print_tabs(stream, indent);
+               fprintf(stream, "</unary_op>\n");
+               return ret;
+       }
+       return 0;
+}
+
+__attribute__((visibility("hidden")))
+int filter_visitor_print_xml(struct filter_parser_ctx *ctx, FILE *stream,
+                       int indent)
+{
+       return recursive_visit_print(&ctx->ast->root, stream, indent);
+}
diff --git a/src/lib/lttng-ctl/filter/memstream.h b/src/lib/lttng-ctl/filter/memstream.h
new file mode 100644 (file)
index 0000000..2cbb035
--- /dev/null
@@ -0,0 +1,228 @@
+#ifndef _LTTNG_CTL_MEMSTREAM_H
+#define _LTTNG_CTL_MEMSTREAM_H
+
+/*
+ * src/lib/lttng-ctl/memstream.h
+ *
+ * Copyright 2012 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * memstream compatibility layer.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+
+#ifdef LTTNG_HAVE_FMEMOPEN
+#include <stdio.h>
+
+static inline
+FILE *lttng_fmemopen(void *buf, size_t size, const char *mode)
+{
+       return fmemopen(buf, size, mode);
+}
+
+#else /* LTTNG_HAVE_FMEMOPEN */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * Fallback for systems which don't have fmemopen. Copy buffer to a
+ * temporary file, and use that file as FILE * input.
+ */
+static inline
+FILE *lttng_fmemopen(void *buf, size_t size, const char *mode)
+{
+       char tmpname[PATH_MAX];
+       size_t len;
+       FILE *fp;
+       int ret;
+
+       /*
+        * Support reading only.
+        */
+       if (strcmp(mode, "rb") != 0) {
+               return NULL;
+       }
+       strncpy(tmpname, "/tmp/lttng-tmp-XXXXXX", PATH_MAX);
+       ret = mkstemp(tmpname);
+       if (ret < 0) {
+               return NULL;
+       }
+       /*
+        * We need to write to the file.
+        */
+       fp = fdopen(ret, "w+");
+       if (!fp) {
+               goto error_unlink;
+       }
+       /* Copy the entire buffer to the file */
+       len = fwrite(buf, sizeof(char), size, fp);
+       if (len != size) {
+               goto error_close;
+       }
+       ret = fseek(fp, 0L, SEEK_SET);
+       if (ret < 0) {
+               perror("fseek");
+               goto error_close;
+       }
+       /* We keep the handle open, but can unlink the file on the VFS. */
+       ret = unlink(tmpname);
+       if (ret < 0) {
+               perror("unlink");
+       }
+       return fp;
+
+error_close:
+       ret = fclose(fp);
+       if (ret < 0) {
+               perror("close");
+       }
+error_unlink:
+       ret = unlink(tmpname);
+       if (ret < 0) {
+               perror("unlink");
+       }
+       return NULL;
+}
+
+#endif /* LTTNG_HAVE_FMEMOPEN */
+
+#ifdef LTTNG_HAVE_OPEN_MEMSTREAM
+
+#include <stdio.h>
+
+static inline
+FILE *lttng_open_memstream(char **ptr, size_t *sizeloc)
+{
+       return open_memstream(ptr, sizeloc);
+}
+
+static inline
+int lttng_close_memstream(char **buf, size_t *size, FILE *fp)
+{
+       return fclose(fp);
+}
+
+#else /* LTTNG_HAVE_OPEN_MEMSTREAM */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * Fallback for systems which don't have open_memstream. Create FILE *
+ * with lttng_open_memstream, but require call to
+ * lttng_close_memstream to flush all data written to the FILE *
+ * into the buffer (which we allocate).
+ */
+static inline
+FILE *lttng_open_memstream(char **ptr, size_t *sizeloc)
+{
+       char tmpname[PATH_MAX];
+       int ret;
+       FILE *fp;
+
+       strncpy(tmpname, "/tmp/lttng-tmp-XXXXXX", PATH_MAX);
+       ret = mkstemp(tmpname);
+       if (ret < 0) {
+               return NULL;
+       }
+       fp = fdopen(ret, "w+");
+       if (!fp) {
+               goto error_unlink;
+       }
+       /*
+        * lttng_flush_memstream will update the buffer content
+        * with read from fp. No need to keep the file around, just the
+        * handle.
+        */
+       ret = unlink(tmpname);
+       if (ret < 0) {
+               perror("unlink");
+       }
+       return fp;
+
+error_unlink:
+       ret = unlink(tmpname);
+       if (ret < 0) {
+               perror("unlink");
+       }
+       return NULL;
+}
+
+/* Get file size, allocate buffer, copy. */
+static inline
+int lttng_close_memstream(char **buf, size_t *size, FILE *fp)
+{
+       size_t len, n;
+       long pos;
+       int ret;
+
+       ret = fflush(fp);
+       if (ret < 0) {
+               perror("fflush");
+               return ret;
+       }
+       ret = fseek(fp, 0L, SEEK_END);
+       if (ret < 0) {
+               perror("fseek");
+               return ret;
+       }
+       pos = ftell(fp);
+       if (ret < 0) {
+               perror("ftell");
+               return ret;
+       }
+       *size = pos;
+       /* add final \0 */
+       *buf = calloc(pos + 1, sizeof(char));
+       if (!*buf) {
+               return -ENOMEM;
+       }
+       ret = fseek(fp, 0L, SEEK_SET);
+       if (ret < 0) {
+               perror("fseek");
+               goto error_free;
+       }
+       /* Copy the entire file into the buffer */
+       n = 0;
+       clearerr(fp);
+       while (!feof(fp) && !ferror(fp) && (*size - n > 0)) {
+               len = fread(*buf, sizeof(char), *size - n, fp);
+               n += len;
+       }
+       if (n != *size) {
+               ret = -1;
+               goto error_close;
+       }
+       ret = fclose(fp);
+       if (ret < 0) {
+               perror("fclose");
+               return ret;
+       }
+       return 0;
+
+error_close:
+       ret = fclose(fp);
+       if (ret < 0) {
+               perror("fclose");
+       }
+error_free:
+       free(*buf);
+       *buf = NULL;
+       return ret;
+}
+
+#endif /* LTTNG_HAVE_OPEN_MEMSTREAM */
+
+#endif /* _LTTNG_CTL_MEMSTREAM_H */
diff --git a/src/lib/lttng-ctl/filter/tests.txt b/src/lib/lttng-ctl/filter/tests.txt
new file mode 100644 (file)
index 0000000..4238c94
--- /dev/null
@@ -0,0 +1,24 @@
+1+1
+a+1
+a.b.c->d.e.f+1
+1+11111-3333+1
+!a.f.d
+(1+2)*(55*666)
+1+2*55*666
+!+-+++-------+++++++++++-----!!--!44+1
+aa>=2
+aa>=2&&bb<1||c!=a
+aa>=2&&(bb<-1||c!=a)
+(!aa>=2&&bb<-1)||c!=a
+c=="test"
+c!="test"
+c=="test*"
+c!="test*"
+aaa||(gg)+(333----1)
+!aa>2
+asdf + 1 > 1
+asdfas < 2332 || asdf + 1 > 1
+asdf.asdfsd.sadf < 4
+asdfasdf->asdfasdf < 2
+0 || ("abc" != "def")) && (3 < 4)
+(intfield>500 && intfield<503 && intfield<502) && (intfield<503 && intfield < 504)
index ef288726a23b1c97779097d4e0ce9bddbf00589c..27d69089fa7faf615626be99cff64ad136f41769 100644 (file)
 #include <common/uri.h>
 #include <lttng/lttng.h>
 
-#include "filter-ast.h"
-#include "filter-parser.h"
-#include "filter-bytecode.h"
-#include "memstream.h"
+#include "filter/filter-ast.h"
+#include "filter/filter-parser.h"
+#include "filter/filter-bytecode.h"
+#include "filter/memstream.h"
 
 #ifdef DEBUG
-const int print_xml = 1;
+static const int print_xml = 1;
 #define dbg_printf(fmt, args...)       \
        printf("[debug liblttng-ctl] " fmt, ## args)
 #else
-const int print_xml = 0;
+static const int print_xml = 0;
 #define dbg_printf(fmt, args...)                               \
 do {                                                           \
        /* do nothing but check printf format */                \
diff --git a/src/lib/lttng-ctl/memstream.h b/src/lib/lttng-ctl/memstream.h
deleted file mode 100644 (file)
index 2cbb035..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-#ifndef _LTTNG_CTL_MEMSTREAM_H
-#define _LTTNG_CTL_MEMSTREAM_H
-
-/*
- * src/lib/lttng-ctl/memstream.h
- *
- * Copyright 2012 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * memstream compatibility layer.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- */
-
-#define _GNU_SOURCE
-#include <config.h>
-
-#ifdef LTTNG_HAVE_FMEMOPEN
-#include <stdio.h>
-
-static inline
-FILE *lttng_fmemopen(void *buf, size_t size, const char *mode)
-{
-       return fmemopen(buf, size, mode);
-}
-
-#else /* LTTNG_HAVE_FMEMOPEN */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-/*
- * Fallback for systems which don't have fmemopen. Copy buffer to a
- * temporary file, and use that file as FILE * input.
- */
-static inline
-FILE *lttng_fmemopen(void *buf, size_t size, const char *mode)
-{
-       char tmpname[PATH_MAX];
-       size_t len;
-       FILE *fp;
-       int ret;
-
-       /*
-        * Support reading only.
-        */
-       if (strcmp(mode, "rb") != 0) {
-               return NULL;
-       }
-       strncpy(tmpname, "/tmp/lttng-tmp-XXXXXX", PATH_MAX);
-       ret = mkstemp(tmpname);
-       if (ret < 0) {
-               return NULL;
-       }
-       /*
-        * We need to write to the file.
-        */
-       fp = fdopen(ret, "w+");
-       if (!fp) {
-               goto error_unlink;
-       }
-       /* Copy the entire buffer to the file */
-       len = fwrite(buf, sizeof(char), size, fp);
-       if (len != size) {
-               goto error_close;
-       }
-       ret = fseek(fp, 0L, SEEK_SET);
-       if (ret < 0) {
-               perror("fseek");
-               goto error_close;
-       }
-       /* We keep the handle open, but can unlink the file on the VFS. */
-       ret = unlink(tmpname);
-       if (ret < 0) {
-               perror("unlink");
-       }
-       return fp;
-
-error_close:
-       ret = fclose(fp);
-       if (ret < 0) {
-               perror("close");
-       }
-error_unlink:
-       ret = unlink(tmpname);
-       if (ret < 0) {
-               perror("unlink");
-       }
-       return NULL;
-}
-
-#endif /* LTTNG_HAVE_FMEMOPEN */
-
-#ifdef LTTNG_HAVE_OPEN_MEMSTREAM
-
-#include <stdio.h>
-
-static inline
-FILE *lttng_open_memstream(char **ptr, size_t *sizeloc)
-{
-       return open_memstream(ptr, sizeloc);
-}
-
-static inline
-int lttng_close_memstream(char **buf, size_t *size, FILE *fp)
-{
-       return fclose(fp);
-}
-
-#else /* LTTNG_HAVE_OPEN_MEMSTREAM */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-/*
- * Fallback for systems which don't have open_memstream. Create FILE *
- * with lttng_open_memstream, but require call to
- * lttng_close_memstream to flush all data written to the FILE *
- * into the buffer (which we allocate).
- */
-static inline
-FILE *lttng_open_memstream(char **ptr, size_t *sizeloc)
-{
-       char tmpname[PATH_MAX];
-       int ret;
-       FILE *fp;
-
-       strncpy(tmpname, "/tmp/lttng-tmp-XXXXXX", PATH_MAX);
-       ret = mkstemp(tmpname);
-       if (ret < 0) {
-               return NULL;
-       }
-       fp = fdopen(ret, "w+");
-       if (!fp) {
-               goto error_unlink;
-       }
-       /*
-        * lttng_flush_memstream will update the buffer content
-        * with read from fp. No need to keep the file around, just the
-        * handle.
-        */
-       ret = unlink(tmpname);
-       if (ret < 0) {
-               perror("unlink");
-       }
-       return fp;
-
-error_unlink:
-       ret = unlink(tmpname);
-       if (ret < 0) {
-               perror("unlink");
-       }
-       return NULL;
-}
-
-/* Get file size, allocate buffer, copy. */
-static inline
-int lttng_close_memstream(char **buf, size_t *size, FILE *fp)
-{
-       size_t len, n;
-       long pos;
-       int ret;
-
-       ret = fflush(fp);
-       if (ret < 0) {
-               perror("fflush");
-               return ret;
-       }
-       ret = fseek(fp, 0L, SEEK_END);
-       if (ret < 0) {
-               perror("fseek");
-               return ret;
-       }
-       pos = ftell(fp);
-       if (ret < 0) {
-               perror("ftell");
-               return ret;
-       }
-       *size = pos;
-       /* add final \0 */
-       *buf = calloc(pos + 1, sizeof(char));
-       if (!*buf) {
-               return -ENOMEM;
-       }
-       ret = fseek(fp, 0L, SEEK_SET);
-       if (ret < 0) {
-               perror("fseek");
-               goto error_free;
-       }
-       /* Copy the entire file into the buffer */
-       n = 0;
-       clearerr(fp);
-       while (!feof(fp) && !ferror(fp) && (*size - n > 0)) {
-               len = fread(*buf, sizeof(char), *size - n, fp);
-               n += len;
-       }
-       if (n != *size) {
-               ret = -1;
-               goto error_close;
-       }
-       ret = fclose(fp);
-       if (ret < 0) {
-               perror("fclose");
-               return ret;
-       }
-       return 0;
-
-error_close:
-       ret = fclose(fp);
-       if (ret < 0) {
-               perror("fclose");
-       }
-error_free:
-       free(*buf);
-       *buf = NULL;
-       return ret;
-}
-
-#endif /* LTTNG_HAVE_OPEN_MEMSTREAM */
-
-#endif /* _LTTNG_CTL_MEMSTREAM_H */
diff --git a/src/lib/lttng-ctl/tests.txt b/src/lib/lttng-ctl/tests.txt
deleted file mode 100644 (file)
index 4238c94..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-1+1
-a+1
-a.b.c->d.e.f+1
-1+11111-3333+1
-!a.f.d
-(1+2)*(55*666)
-1+2*55*666
-!+-+++-------+++++++++++-----!!--!44+1
-aa>=2
-aa>=2&&bb<1||c!=a
-aa>=2&&(bb<-1||c!=a)
-(!aa>=2&&bb<-1)||c!=a
-c=="test"
-c!="test"
-c=="test*"
-c!="test*"
-aaa||(gg)+(333----1)
-!aa>2
-asdf + 1 > 1
-asdfas < 2332 || asdf + 1 > 1
-asdf.asdfsd.sadf < 4
-asdfasdf->asdfasdf < 2
-0 || ("abc" != "def")) && (3 < 4)
-(intfield>500 && intfield<503 && intfield<502) && (intfield<503 && intfield < 504)
This page took 0.102622 seconds and 4 git commands to generate.