X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Ffilter%2Ffilter-visitor-generate-ir.c;h=85aadcae6fe7baedec1b30d8d34960c65c5b43fd;hp=d694dcc1609d202ab0dd60a0be65795e5fdf03af;hb=661dfdd190c65bad5a044e21c1d5f9ad59144bf8;hpb=654600c6275417dba4faecd0a151d065d9f7b42d diff --git a/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c b/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c index d694dcc16..85aadcae6 100644 --- a/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c +++ b/src/lib/lttng-ctl/filter/filter-visitor-generate-ir.c @@ -31,6 +31,7 @@ #include "filter-ir.h" #include +#include static struct ir_op *generate_ir_recursive(struct filter_parser_ctx *ctx, @@ -68,6 +69,22 @@ struct ir_op *make_op_root(struct ir_op *child, enum ir_side side) return op; } +static +enum ir_load_string_type get_literal_string_type(const char *string) +{ + assert(string); + + if (strutils_is_star_glob_pattern(string)) { + if (strutils_is_star_at_the_end_only_glob_pattern(string)) { + return IR_LOAD_STRING_TYPE_GLOB_STAR_END; + } + + return IR_LOAD_STRING_TYPE_GLOB_STAR; + } + + return IR_LOAD_STRING_TYPE_PLAIN; +} + static struct ir_op *make_op_load_string(char *string, enum ir_side side) { @@ -80,8 +97,9 @@ struct ir_op *make_op_load_string(char *string, enum ir_side side) 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) { + op->u.load.u.string.type = get_literal_string_type(string); + op->u.load.u.string.value = strdup(string); + if (!op->u.load.u.string.value) { free(op); return NULL; } @@ -122,7 +140,8 @@ struct ir_op *make_op_load_float(double v, enum ir_side side) } static -struct ir_op *make_op_load_field_ref(char *string, enum ir_side side) +struct ir_op *make_op_load_field_ref(char *string, + enum ir_side side) { struct ir_op *op; @@ -135,14 +154,61 @@ struct ir_op *make_op_load_field_ref(char *string, enum ir_side side) op->side = side; op->u.load.u.ref = strdup(string); if (!op->u.load.u.ref) { - free(op); + goto error; + } + return op; + +error: + free(op); + return NULL; +} + +static +struct ir_op *make_op_load_field_ref_index(char *string, + struct filter_node *next, + 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_INDEX; + op->signedness = IR_SIGN_DYN; + op->side = side; + op->u.load.u.ref_index.symbol = strdup(string); + if (!op->u.load.u.ref_index.symbol) { + goto error; + } + /* Only positive integer literals accepted as index. */ + if (next->type == NODE_UNARY_OP) { + fprintf(stderr, "[error] Unexpected unary operator as index\n"); + goto error; + } + if (next->type != NODE_EXPRESSION) { + fprintf(stderr, "[error] Expecting expression as index\n"); + goto error; + } + if (next->u.expression.type != AST_EXP_CONSTANT) { + fprintf(stderr, "[error] Expecting constant index\n"); + goto error; + } + if (next->u.expression.u.constant < 0) { + fprintf(stderr, "[error] Expecting positive constant index\n"); + goto error; } + op->u.load.u.ref_index.index = next->u.expression.u.constant; return op; + +error: + free(op); + return NULL; } static -struct ir_op *make_op_load_get_context_ref(char *string, enum ir_side side) +struct ir_op *make_op_load_get_context_ref(char *string, + enum ir_side side) { struct ir_op *op; @@ -155,10 +221,56 @@ struct ir_op *make_op_load_get_context_ref(char *string, enum ir_side side) op->side = side; op->u.load.u.ref = strdup(string); if (!op->u.load.u.ref) { - free(op); + goto error; + } + return op; + +error: + free(op); + return NULL; +} + +static +struct ir_op *make_op_load_get_context_ref_index(char *string, + struct filter_node *next, + 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_GET_CONTEXT_REF_INDEX; + op->signedness = IR_SIGN_DYN; + op->side = side; + op->u.load.u.ref_index.symbol = strdup(string); + if (!op->u.load.u.ref_index.symbol) { + goto error; + } + /* Only positive integer literals accepted as offset. */ + if (next->type == NODE_UNARY_OP) { + fprintf(stderr, "[error] Unexpected unary operator as index\n"); + goto error; + } + if (next->type != NODE_EXPRESSION) { + fprintf(stderr, "[error] Expecting expression as index\n"); + goto error; + } + if (next->u.expression.type != AST_EXP_CONSTANT) { + fprintf(stderr, "[error] Expecting constant index\n"); + goto error; + } + if (next->u.expression.u.constant < 0) { + fprintf(stderr, "[error] Expecting positive constant index\n"); + goto error; } + op->u.load.u.ref_index.index = next->u.expression.u.constant; return op; + +error: + free(op); + return NULL; } static @@ -366,12 +478,16 @@ void filter_free_ir_recursive(struct ir_op *op) case IR_OP_LOAD: switch (op->data_type) { case IR_DATA_STRING: - free(op->u.load.u.string); + free(op->u.load.u.string.value); break; case IR_DATA_FIELD_REF: /* fall-through */ case IR_DATA_GET_CONTEXT_REF: free(op->u.load.u.ref); break; + case IR_DATA_FIELD_REF_INDEX: /* fall-through */ + case IR_DATA_GET_CONTEXT_REF_INDEX: + free(op->u.load.u.ref_index.symbol); + break; default: break; } @@ -410,45 +526,56 @@ struct ir_op *make_expression(struct filter_parser_ctx *ctx, return make_op_load_float(node->u.expression.u.float_constant, side); case AST_EXP_IDENTIFIER: - if (node->u.expression.pre_op != AST_LINK_UNKNOWN) { + switch (node->u.expression.pre_op) { + case AST_LINK_UNKNOWN: + return make_op_load_field_ref(node->u.expression.u.identifier, + side); + case AST_LINK_BRACKET: + return make_op_load_field_ref_index(node->u.expression.u.identifier, + node->u.expression.next, + side); + default: fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__); return NULL; } - return make_op_load_field_ref(node->u.expression.u.identifier, - side); case AST_EXP_GLOBAL_IDENTIFIER: { - struct filter_node *next; + const char *name; - if (node->u.expression.pre_op == AST_LINK_UNKNOWN) { - fprintf(stderr, "[error] %s: global identifiers need chained identifier \n", __func__); - return NULL; - } - /* We currently only support $ctx (context) identifiers */ + /* + * We currently only support $ctx (context) and $app + * identifiers. + */ if (strncmp(node->u.expression.u.identifier, - "$ctx", strlen("$ctx")) != 0) { - fprintf(stderr, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" currently implemented.\n", __func__, node->u.expression.u.identifier); - return NULL; - } - next = node->u.expression.next; - if (!next) { - fprintf(stderr, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__); + "$ctx.", strlen("$ctx.")) != 0 + && strncmp(node->u.expression.u.identifier, + "$app.", strlen("$app.")) != 0) { + fprintf(stderr, "[error] %s: \"%s\" global identifier is unknown. Only \"$ctx\" and \"$app\" are currently implemented.\n", __func__, node->u.expression.u.identifier); return NULL; } - if (next->type != NODE_EXPRESSION) { - fprintf(stderr, "[error] %s: Expecting expression.\n", __func__); + name = strchr(node->u.expression.u.identifier, '.'); + if (!name) { + fprintf(stderr, "[error] %s: Expecting '.'\n", __func__); return NULL; } - if (next->u.expression.type != AST_EXP_IDENTIFIER) { - fprintf(stderr, "[error] %s: Expecting identifier.\n", __func__); + name++; /* Skip . */ + if (!strlen(name)) { + fprintf(stderr, "[error] %s: Expecting a context name, e.g. \'$ctx.name\'.\n", __func__); return NULL; } - if (next->u.expression.pre_op != AST_LINK_UNKNOWN) { - fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported after identifier\n", __func__); + switch (node->u.expression.pre_op) { + case AST_LINK_UNKNOWN: + return make_op_load_get_context_ref(node->u.expression.u.identifier, + side); + case AST_LINK_BRACKET: + return make_op_load_get_context_ref_index(node->u.expression.u.identifier, + node->u.expression.next, + side); + default: + fprintf(stderr, "[error] %s: dotted and dereferenced identifiers not supported\n", __func__); return NULL; } - return make_op_load_get_context_ref(next->u.expression.u.identifier, - side); + } case AST_EXP_NESTED: return generate_ir_recursive(ctx, node->u.expression.u.child,