X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Ffilter%2Ffilter-parser.y;h=e9c2e6aabe9c1ad25891052f2af76381b2d1202f;hp=a72fcd04bd74ba3f24c9d6210aaae0986b7746f9;hb=831b702b8e8914a3ca3b4905a55aed93c7d30bbf;hpb=37600d7967a38d394621847163b0f854bd7566fa diff --git a/src/lib/lttng-ctl/filter/filter-parser.y b/src/lib/lttng-ctl/filter/filter-parser.y index a72fcd04b..e9c2e6aab 100644 --- a/src/lib/lttng-ctl/filter/filter-parser.y +++ b/src/lib/lttng-ctl/filter/filter-parser.y @@ -32,20 +32,27 @@ #include "filter-ast.h" #include "filter-parser.h" -__attribute__((visibility("hidden"))) +#include + +#define WIDTH_u64_SCANF_IS_A_BROKEN_API "20" +#define WIDTH_o64_SCANF_IS_A_BROKEN_API "22" +#define WIDTH_x64_SCANF_IS_A_BROKEN_API "17" +#define WIDTH_lg_SCANF_IS_A_BROKEN_API "4096" /* Hugely optimistic approximation */ + +LTTNG_HIDDEN int yydebug; -__attribute__((visibility("hidden"))) +LTTNG_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"))) +LTTNG_HIDDEN +int yyparse(struct filter_parser_ctx *parser_ctx, yyscan_t scanner); +LTTNG_HIDDEN +int yylex(union YYSTYPE *yyval, yyscan_t scanner); +LTTNG_HIDDEN int yylex_init_extra(struct filter_parser_ctx *parser_ctx, yyscan_t * ptr_yy_globals); -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int yylex_destroy(yyscan_t yyparser_ctx); -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN void yyrestart(FILE * in_str, yyscan_t parser_ctx); struct gc_string { @@ -62,7 +69,7 @@ static const char *node_type_to_str[] = { [ NODE_UNARY_OP ] = "NODE_UNARY_OP", }; -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN const char *node_type(struct filter_node *node) { if (node->type < NR_NODE_TYPES) @@ -82,9 +89,13 @@ static struct gc_string *gc_string_alloc(struct filter_parser_ctx *parser_ctx, for (alloclen = 8; alloclen < sizeof(long) + sizeof(*gstr) + len; alloclen *= 2); - gstr = malloc(alloclen); + gstr = zmalloc(alloclen); + if (!gstr) { + goto end; + } cds_list_add(&gstr->gc, &parser_ctx->allocated_strings); gstr->alloclen = alloclen; +end: return gstr; } @@ -93,7 +104,7 @@ static struct gc_string *gc_string_alloc(struct filter_parser_ctx *parser_ctx, * 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"))) +LTTNG_HIDDEN struct gc_string *gc_string_append(struct filter_parser_ctx *parser_ctx, struct gc_string *gstr, struct gc_string *gsrc) @@ -123,7 +134,7 @@ struct gc_string *gc_string_append(struct filter_parser_ctx *parser_ctx, return gstr; } -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN void setstring(struct filter_parser_ctx *parser_ctx, YYSTYPE *lvalp, const char *src) { lvalp->gs = gc_string_alloc(parser_ctx, strlen(src) + 1); @@ -136,7 +147,7 @@ static struct filter_node *make_node(struct filter_parser_ctx *scanner, struct filter_ast *ast = filter_parser_get_ast(scanner); struct filter_node *node; - node = malloc(sizeof(*node)); + node = zmalloc(sizeof(*node)); if (!node) return NULL; memset(node, 0, sizeof(*node)); @@ -173,7 +184,7 @@ static struct filter_node *make_op_node(struct filter_parser_ctx *scanner, struct filter_ast *ast = filter_parser_get_ast(scanner); struct filter_node *node; - node = malloc(sizeof(*node)); + node = zmalloc(sizeof(*node)); if (!node) return NULL; memset(node, 0, sizeof(*node)); @@ -185,13 +196,13 @@ static struct filter_node *make_op_node(struct filter_parser_ctx *scanner, return node; } -__attribute__((visibility("hidden"))) -void yyerror(struct filter_parser_ctx *parser_ctx, const char *str) +LTTNG_HIDDEN +void yyerror(struct filter_parser_ctx *parser_ctx, yyscan_t scanner, const char *str) { fprintf(stderr, "error %s\n", str); } -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int yywrap(void) { return 1; @@ -199,7 +210,7 @@ int yywrap(void) #define parse_error(parser_ctx, str) \ do { \ - yyerror(parser_ctx, YY_("parse error: " str "\n")); \ + yyerror(parser_ctx, parser_ctx->scanner, YY_("parse error: " str "\n")); \ YYERROR; \ } while (0) @@ -215,7 +226,7 @@ static struct filter_ast *filter_ast_alloc(void) { struct filter_ast *ast; - ast = malloc(sizeof(*ast)); + ast = zmalloc(sizeof(*ast)); if (!ast) return NULL; memset(ast, 0, sizeof(*ast)); @@ -233,13 +244,13 @@ static void filter_ast_free(struct filter_ast *ast) free(ast); } -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN int filter_parser_ctx_append_ast(struct filter_parser_ctx *parser_ctx) { - return yyparse(parser_ctx); + return yyparse(parser_ctx, parser_ctx->scanner); } -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN struct filter_parser_ctx *filter_parser_ctx_alloc(FILE *input) { struct filter_parser_ctx *parser_ctx; @@ -247,7 +258,7 @@ struct filter_parser_ctx *filter_parser_ctx_alloc(FILE *input) yydebug = filter_parser_debug; - parser_ctx = malloc(sizeof(*parser_ctx)); + parser_ctx = zmalloc(sizeof(*parser_ctx)); if (!parser_ctx) return NULL; memset(parser_ctx, 0, sizeof(*parser_ctx)); @@ -281,7 +292,7 @@ cleanup_parser_ctx: return NULL; } -__attribute__((visibility("hidden"))) +LTTNG_HIDDEN void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx) { int ret; @@ -299,7 +310,8 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx) %define api.pure /* %locations */ %parse-param {struct filter_parser_ctx *parser_ctx} -%lex-param {struct filter_parser_ctx *parser_ctx} +%parse-param {yyscan_t scanner} +%lex-param {yyscan_t scanner} %start translation_unit %token CHARACTER_CONSTANT_START SQUOTE STRING_LITERAL_START DQUOTE %token ESCSEQ CHAR_STRING_TOKEN @@ -311,7 +323,7 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx) %token ASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA %token XOR_BIN AND_BIN OR_BIN NOT_BIN -%token IDENTIFIER +%token IDENTIFIER GLOBAL_IDENTIFIER %token ERROR %union { @@ -324,6 +336,8 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx) %type s_char s_char_sequence c_char c_char_sequence %type primary_expression +%type prefix_expression +%type prefix_expression_rec %type postfix_expression %type unary_expression %type unary_operator @@ -338,6 +352,7 @@ void filter_parser_ctx_free(struct filter_parser_ctx *parser_ctx) %type logical_and_expression %type logical_or_expression %type expression +%type identifiers %% @@ -378,40 +393,44 @@ s_char: } ; -primary_expression - : IDENTIFIER - { - $$ = make_node(parser_ctx, NODE_EXPRESSION); - $$->u.expression.type = AST_EXP_IDENTIFIER; - $$->u.expression.u.identifier = yylval.gs->s; - } - | DECIMAL_CONSTANT +primary_expression: + DECIMAL_CONSTANT { $$ = make_node(parser_ctx, NODE_EXPRESSION); $$->u.expression.type = AST_EXP_CONSTANT; - sscanf(yylval.gs->s, "%" PRIu64, - &$$->u.expression.u.constant); + if (sscanf(yylval.gs->s, "%" WIDTH_u64_SCANF_IS_A_BROKEN_API SCNu64, + &$$->u.expression.u.constant) != 1) { + parse_error(parser_ctx, "cannot scanf decimal 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); + if (!strcmp(yylval.gs->s, "0")) { + $$->u.expression.u.constant = 0; + } else if (sscanf(yylval.gs->s, "0%" WIDTH_o64_SCANF_IS_A_BROKEN_API SCNo64, + &$$->u.expression.u.constant) != 1) { + parse_error(parser_ctx, "cannot scanf octal 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); + if (sscanf(yylval.gs->s, "0x%" WIDTH_x64_SCANF_IS_A_BROKEN_API SCNx64, + &$$->u.expression.u.constant) != 1) { + parse_error(parser_ctx, "cannot scanf hexadecimal 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); + if (sscanf(yylval.gs->s, "%" WIDTH_lg_SCANF_IS_A_BROKEN_API "lg", + &$$->u.expression.u.float_constant) != 1) { + parse_error(parser_ctx, "cannot scanf float constant"); + } } | STRING_LITERAL_START DQUOTE { @@ -439,23 +458,62 @@ primary_expression } ; -postfix_expression - : primary_expression - { $$ = $1; } - | postfix_expression DOT IDENTIFIER +identifiers + : IDENTIFIER { $$ = make_node(parser_ctx, NODE_EXPRESSION); $$->u.expression.type = AST_EXP_IDENTIFIER; + $$->u.expression.u.identifier = yylval.gs->s; + } + | GLOBAL_IDENTIFIER + { + $$ = make_node(parser_ctx, NODE_EXPRESSION); + $$->u.expression.type = AST_EXP_GLOBAL_IDENTIFIER; + $$->u.expression.u.identifier = yylval.gs->s; + } + ; + +prefix_expression_rec + : LSBRAC unary_expression RSBRAC + { + $$ = $2; + } + | LSBRAC unary_expression RSBRAC prefix_expression_rec + { + $$ = $2; + $$->u.expression.pre_op = AST_LINK_BRACKET; + $$->u.expression.prev = $4; + } + ; + +prefix_expression + : identifiers + { + $$ = $1; + } + | identifiers prefix_expression_rec + { + $$ = $1; + $$->u.expression.pre_op = AST_LINK_BRACKET; + $$->u.expression.next_bracket = $2; + } + ; + +postfix_expression + : prefix_expression + { + $$ = $1; + } + | postfix_expression DOT prefix_expression + { + $$ = $3; $$->u.expression.post_op = AST_LINK_DOT; - $$->u.expression.u.identifier = $3->s; $$->u.expression.prev = $1; } - | postfix_expression RARROW IDENTIFIER + | postfix_expression RARROW prefix_expression { - $$ = make_node(parser_ctx, NODE_EXPRESSION); - $$->u.expression.type = AST_EXP_IDENTIFIER; + $$ = $3; $$->u.expression.post_op = AST_LINK_RARROW; - $$->u.expression.u.identifier = $3->s; $$->u.expression.prev = $1; } ; @@ -463,6 +521,8 @@ postfix_expression unary_expression : postfix_expression { $$ = $1; } + | primary_expression + { $$ = $1; } | unary_operator unary_expression { $$ = $1; @@ -489,7 +549,7 @@ unary_operator | NOT_BIN { $$ = make_node(parser_ctx, NODE_UNARY_OP); - $$->u.unary_op.type = AST_UNARY_BIN_NOT; + $$->u.unary_op.type = AST_UNARY_BIT_NOT; } ; @@ -528,30 +588,57 @@ shift_expression { $$ = $1; } | shift_expression LEFT_OP additive_expression { - $$ = make_op_node(parser_ctx, AST_OP_LSHIFT, $1, $3); + $$ = make_op_node(parser_ctx, AST_OP_BIT_LSHIFT, $1, $3); } | shift_expression RIGHT_OP additive_expression { - $$ = make_op_node(parser_ctx, AST_OP_RSHIFT, $1, $3); + $$ = make_op_node(parser_ctx, AST_OP_BIT_RSHIFT, $1, $3); } ; -relational_expression +and_expression : shift_expression { $$ = $1; } - | relational_expression LT_OP shift_expression + | and_expression AND_BIN shift_expression + { + $$ = make_op_node(parser_ctx, AST_OP_BIT_AND, $1, $3); + } + ; + +exclusive_or_expression + : and_expression + { $$ = $1; } + | exclusive_or_expression XOR_BIN and_expression + { + $$ = make_op_node(parser_ctx, AST_OP_BIT_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_BIT_OR, $1, $3); + } + ; + +relational_expression + : inclusive_or_expression + { $$ = $1; } + | relational_expression LT_OP inclusive_or_expression { $$ = make_op_node(parser_ctx, AST_OP_LT, $1, $3); } - | relational_expression GT_OP shift_expression + | relational_expression GT_OP inclusive_or_expression { $$ = make_op_node(parser_ctx, AST_OP_GT, $1, $3); } - | relational_expression LE_OP shift_expression + | relational_expression LE_OP inclusive_or_expression { $$ = make_op_node(parser_ctx, AST_OP_LE, $1, $3); } - | relational_expression GE_OP shift_expression + | relational_expression GE_OP inclusive_or_expression { $$ = make_op_node(parser_ctx, AST_OP_GE, $1, $3); } @@ -570,37 +657,10 @@ equality_expression } ; -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 + : equality_expression { $$ = $1; } - | logical_and_expression AND_OP inclusive_or_expression + | logical_and_expression AND_OP equality_expression { $$ = make_op_node(parser_ctx, AST_OP_AND, $1, $3); }