%{ /* Copyright (c) 2018, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the separately licensed software that they have either included with the program or referenced in the documentation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "sql/debug_lo_misc.h" #include "sql/debug_lo_parser.h" #include "sql/debug_lo_scanner.h" #include "sql/debug_lock_order.h" #include "mysql/components/services/log_builtins.h" #include "mysqld_error.h" class LO_graph; void process_arc(LO_parser_param *p, char *from, char *state, char *to, bool recursive, char *operation, int flags, char *constraint, char *comment); void process_bind(LO_parser_param *p, char *from, char *to, int flags); void process_node(LO_parser_param *p, char *node, char *operation, int flags); void LOCK_ORDER_error(YYLTYPE *yyloc, LO_parser_param *p, const char* msg); #define YYLEX_PARAM param->m_scanner %} %pure-parser %locations %lex-param { yyscan_t YYLEX_PARAM } %parse-param { struct LO_parser_param *param } %union { char *m_str; int m_flags; } %start graph %expect 0 %token ARC_SYM %token BIND_SYM %token COMMENT_SYM %token CONSTRAINT_SYM %token DEBUG_SYM %token FLAGS_SYM %token FROM_SYM %token IGNORED_SYM %token LOOP_SYM %token NODE_SYM %token OP_SYM %token RECURSIVE_SYM %token STATE_SYM %token STR_SYM %token TO_SYM %token TRACE_SYM %token UNFAIR_SYM %type opt_arc_flags; %type arc_flags; %type arc_flag; %type opt_bind_flags; %type bind_flags; %type bind_flag; %type node_flag; %type opt_comment; %type opt_constraint; %type opt_state; %% graph: list_of_declarations_opt ; list_of_declarations_opt: /* empty */ | list_of_declarations ; list_of_declarations: declaration | list_of_declarations declaration ; opt_arc_flags: /* empty */ { $$ = 0; } | FLAGS_SYM arc_flags { $$ = $2; } ; arc_flags: arc_flags arc_flag { $$ = $1 | $2; } | arc_flag { $$ = $1; } ; arc_flag: TRACE_SYM { $$ = LO_FLAG_TRACE; } | DEBUG_SYM { $$ = LO_FLAG_DEBUG; } | LOOP_SYM { $$ = LO_FLAG_LOOP; } | IGNORED_SYM { $$ = LO_FLAG_IGNORED; } ; opt_bind_flags: /* empty */ { $$ = 0; } | FLAGS_SYM bind_flags { $$ = $2; } ; bind_flags: bind_flags bind_flag { $$ = $1 | $2; } | bind_flag { $$ = $1; } ; bind_flag: UNFAIR_SYM { $$ = LO_FLAG_UNFAIR; } ; node_flag: IGNORED_SYM { $$ = LO_FLAG_IGNORED; } ; opt_state: /* empty */ { $$ = nullptr; } | STATE_SYM STR_SYM { $$ = $2; } ; opt_constraint: /* empty */ { $$ = nullptr; } | CONSTRAINT_SYM STR_SYM { $$ = $2; } ; opt_comment: /* empty */ { $$ = nullptr; } | COMMENT_SYM STR_SYM { $$ = $2; } ; declaration: arc_declaration | bind_declaration | node_declaration ; /* Note: can not use the [from] and $from syntax, because this requires a recent bison. */ arc_declaration: ARC_SYM FROM_SYM STR_SYM /* [from] = 3 */ opt_state /* [state] = 4 */ TO_SYM STR_SYM /* [to] = 6 */ opt_arc_flags /* [flags] = 7 */ opt_constraint /* [constraint] = 8 */ opt_comment /* [comment] = 9 */ { process_arc(param, $3, $4, $6, false, nullptr, $7, $8, $9); } | ARC_SYM FROM_SYM STR_SYM /* [from] = 3 */ opt_state /* [state] = 4 */ TO_SYM STR_SYM /* [to] = 6 */ OP_SYM STR_SYM /* [op] = 8 */ opt_arc_flags /* [flags] = 9 */ opt_constraint /* [constraint] = 10 */ opt_comment /* [comment] = 11 */ { process_arc(param, $3, $4, $6, false, $8, $9, $10, $11); } | ARC_SYM FROM_SYM STR_SYM /* [from] = 3 */ opt_state /* [state] = 4 */ TO_SYM STR_SYM /* [to] = 6 */ RECURSIVE_SYM OP_SYM STR_SYM /* [op] = 9 */ opt_arc_flags /* [flags] = 10 */ opt_constraint /* [constraint] = 11 */ opt_comment /* [comment] == 12 */ { process_arc(param, $3, $4, $6, true, $9, $10, $11, $12); } ; bind_declaration: BIND_SYM STR_SYM /* [from] = 2 */ TO_SYM STR_SYM /* [to] = 4 */ opt_bind_flags /* [flags] = 5 */ { process_bind(param, $2, $4, $5); } ; node_declaration: NODE_SYM STR_SYM /* [node] = 2 */ node_flag /* [flag] = 3 */ { process_node(param, $2, nullptr, $3); } | NODE_SYM STR_SYM /* [node] = 2 */ OP_SYM STR_SYM /* [op] = 4 */ node_flag /* [flag] = 5 */ { process_node(param, $2, $4, $5); } ; %% void process_arc(LO_parser_param *p, char *from, char *state, char *to, bool recursive, char *operation, int flags, char *constraint, char *comment) { LO_authorised_arc arc; arc.m_from_name = from; arc.m_from_state = state; arc.m_to_name = to; arc.m_op_recursive = recursive; arc.m_to_operation = operation; arc.m_flags = flags; arc.m_constraint = constraint; arc.m_comment = comment; LO_add_authorised_arc(p->m_graph, &arc); } void process_bind(LO_parser_param *p, char *from, char *to, int flags) { LO_authorised_arc arc; arc.m_from_name = from; arc.m_from_state = nullptr; arc.m_to_name = to; arc.m_op_recursive = false; arc.m_to_operation = nullptr; arc.m_flags = LO_FLAG_BIND | flags; arc.m_constraint = nullptr; arc.m_comment = nullptr; LO_add_authorised_arc(p->m_graph, &arc); } void process_node(LO_parser_param *p, char *node, char *operation, int flags) { LO_node_properties prop; prop.m_name = node; prop.m_operation = operation; prop.m_flags = flags; LO_add_node_properties(p->m_graph, &prop); } void LOCK_ORDER_error(YYLTYPE * yylloc_param, LO_parser_param * p, const char* msg) { /* message format = "Lock order dependencies file <%s> (%d:%d) - (%d:%d) : %s" */ LogErr(ERROR_LEVEL, ER_LOCK_ORDER_DEPENDENCIES_SYNTAX, p->m_filename, yylloc_param->first_line, yylloc_param->first_column, yylloc_param->last_line, yylloc_param->last_column, msg); }