1
2%{
3
4/* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; version 2 of the License.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
18
19#include <string>
20#include "sql/debug_lo_misc.h"
21#include "sql/debug_lo_parser.h"
22#include "sql/debug_lo_scanner.h"
23#include "sql/debug_lock_order.h"
24#include "mysql/components/services/log_builtins.h"
25#include "mysqld_error.h"
26
27class LO_graph;
28
29void process_arc(LO_parser_param *p,
30  char *from,
31  char *state,
32  char *to,
33  bool recursive,
34  char *operation,
35  int flags,
36  char *constraint,
37  char *comment);
38
39void process_bind(LO_parser_param *p,
40  char *from,
41  char *to,
42  int flags);
43
44void process_node(LO_parser_param *p,
45  char *node,
46  char *operation,
47  int flags);
48
49void LOCK_ORDER_error(YYLTYPE *yyloc, LO_parser_param *p, const char* msg);
50
51#define YYLEX_PARAM param->m_scanner
52
53%}
54
55%pure-parser
56%locations
57
58%lex-param { yyscan_t YYLEX_PARAM }
59%parse-param { struct LO_parser_param *param }
60
61%union
62{
63  char *m_str;
64  int m_flags;
65}
66
67%start graph
68
69%expect 0
70
71%token ARC_SYM
72%token BIND_SYM
73%token COMMENT_SYM
74%token CONSTRAINT_SYM
75%token DEBUG_SYM
76%token FLAGS_SYM
77%token FROM_SYM
78%token IGNORED_SYM
79%token LOOP_SYM
80%token NODE_SYM
81%token OP_SYM
82%token RECURSIVE_SYM
83%token STATE_SYM
84%token <m_str> STR_SYM
85%token TO_SYM
86%token TRACE_SYM
87%token UNFAIR_SYM
88
89%type <m_flags> opt_arc_flags;
90%type <m_flags> arc_flags;
91%type <m_flags> arc_flag;
92%type <m_flags> opt_bind_flags;
93%type <m_flags> bind_flags;
94%type <m_flags> bind_flag;
95%type <m_flags> node_flag;
96%type <m_str> opt_comment;
97%type <m_str> opt_constraint;
98%type <m_str> opt_state;
99
100%%
101
102graph:
103      list_of_declarations_opt
104    ;
105
106list_of_declarations_opt:
107      /* empty */
108    | list_of_declarations
109    ;
110
111list_of_declarations:
112      declaration
113    | list_of_declarations declaration
114    ;
115
116opt_arc_flags:
117      /* empty */
118      {
119        $$ = 0;
120      }
121    | FLAGS_SYM arc_flags
122      {
123        $$ = $2;
124      }
125    ;
126
127arc_flags:
128      arc_flags arc_flag
129      {
130        $$ = $1 | $2;
131      }
132    | arc_flag
133      {
134        $$ = $1;
135      }
136    ;
137
138arc_flag:
139      TRACE_SYM
140      {
141        $$ = LO_FLAG_TRACE;
142      }
143    | DEBUG_SYM
144      {
145        $$ = LO_FLAG_DEBUG;
146      }
147    | LOOP_SYM
148      {
149        $$ = LO_FLAG_LOOP;
150      }
151    | IGNORED_SYM
152      {
153        $$ = LO_FLAG_IGNORED;
154      }
155    ;
156
157opt_bind_flags:
158      /* empty */
159      {
160        $$ = 0;
161      }
162    | FLAGS_SYM bind_flags
163      {
164        $$ = $2;
165      }
166    ;
167
168bind_flags:
169      bind_flags bind_flag
170      {
171        $$ = $1 | $2;
172      }
173    | bind_flag
174      {
175        $$ = $1;
176      }
177    ;
178
179bind_flag:
180      UNFAIR_SYM
181      {
182        $$ = LO_FLAG_UNFAIR;
183      }
184    ;
185
186node_flag:
187      IGNORED_SYM
188      {
189        $$ = LO_FLAG_IGNORED;
190      }
191    ;
192
193opt_state:
194      /* empty */
195      {
196        $$ = nullptr;
197      }
198    | STATE_SYM STR_SYM
199      {
200        $$ = $2;
201      }
202    ;
203
204opt_constraint:
205      /* empty */
206      {
207        $$ = nullptr;
208      }
209    | CONSTRAINT_SYM STR_SYM
210      {
211        $$ = $2;
212      }
213    ;
214
215opt_comment:
216      /* empty */
217      {
218        $$ = nullptr;
219      }
220    | COMMENT_SYM STR_SYM
221      {
222        $$ = $2;
223      }
224    ;
225
226declaration:
227      arc_declaration
228    | bind_declaration
229    | node_declaration
230    ;
231
232/*
233  Note: can not use the [from] and $from syntax,
234  because this requires a recent bison.
235*/
236
237arc_declaration:
238      ARC_SYM
239      FROM_SYM
240      STR_SYM /* [from] = 3 */
241      opt_state /* [state] = 4 */
242      TO_SYM
243      STR_SYM /* [to] = 6 */
244      opt_arc_flags /* [flags] = 7 */
245      opt_constraint /* [constraint] = 8 */
246      opt_comment /* [comment] = 9 */
247      {
248        process_arc(param, $3, $4, $6, false, nullptr, $7, $8, $9);
249      }
250    | ARC_SYM
251      FROM_SYM
252      STR_SYM /* [from] = 3 */
253      opt_state /* [state] = 4 */
254      TO_SYM
255      STR_SYM /* [to] = 6 */
256      OP_SYM
257      STR_SYM /* [op] = 8 */
258      opt_arc_flags /* [flags] = 9 */
259      opt_constraint /* [constraint] = 10 */
260      opt_comment /* [comment] = 11 */
261      {
262        process_arc(param, $3, $4, $6, false, $8, $9, $10, $11);
263      }
264    | ARC_SYM
265      FROM_SYM
266      STR_SYM /* [from] = 3 */
267      opt_state /* [state] = 4 */
268      TO_SYM
269      STR_SYM /* [to] = 6 */
270      RECURSIVE_SYM
271      OP_SYM
272      STR_SYM /* [op] = 9 */
273      opt_arc_flags /* [flags] = 10 */
274      opt_constraint /* [constraint] = 11 */
275      opt_comment /* [comment] == 12 */
276      {
277        process_arc(param, $3, $4, $6, true, $9, $10, $11, $12);
278      }
279    ;
280
281bind_declaration:
282      BIND_SYM
283      STR_SYM /* [from] = 2 */
284      TO_SYM
285      STR_SYM /* [to] = 4 */
286      opt_bind_flags /* [flags] = 5 */
287      {
288        process_bind(param, $2, $4, $5);
289      }
290    ;
291
292node_declaration:
293      NODE_SYM
294      STR_SYM /* [node] = 2 */
295      node_flag /* [flag] = 3 */
296      {
297        process_node(param, $2, nullptr, $3);
298      }
299    | NODE_SYM
300      STR_SYM /* [node] = 2 */
301      OP_SYM
302      STR_SYM /* [op] = 4 */
303      node_flag /* [flag] = 5 */
304      {
305        process_node(param, $2, $4, $5);
306      }
307    ;
308
309%%
310
311void process_arc(LO_parser_param *p,
312  char *from,
313  char *state,
314  char *to,
315  bool recursive,
316  char *operation,
317  int flags,
318  char *constraint,
319  char *comment)
320{
321  LO_authorised_arc arc;
322  arc.m_from_name = from;
323  arc.m_from_state = state;
324  arc.m_to_name = to;
325  arc.m_op_recursive = recursive;
326  arc.m_to_operation = operation;
327  arc.m_flags = flags;
328  arc.m_constraint = constraint;
329  arc.m_comment = comment;
330  LO_add_authorised_arc(p->m_graph, &arc);
331}
332
333void process_bind(LO_parser_param *p,
334  char *from,
335  char *to,
336  int flags)
337{
338  LO_authorised_arc arc;
339  arc.m_from_name = from;
340  arc.m_from_state = nullptr;
341  arc.m_to_name = to;
342  arc.m_op_recursive = false;
343  arc.m_to_operation = nullptr;
344  arc.m_flags = LO_FLAG_BIND | flags;
345  arc.m_constraint = nullptr;
346  arc.m_comment = nullptr;
347  LO_add_authorised_arc(p->m_graph, &arc);
348}
349
350void process_node(LO_parser_param *p,
351  char *node,
352  char *operation,
353  int flags)
354{
355  LO_node_properties prop;
356  prop.m_name = node;
357  prop.m_operation = operation;
358  prop.m_flags = flags;
359  LO_add_node_properties(p->m_graph, &prop);
360}
361
362void LOCK_ORDER_error(YYLTYPE * yylloc_param, LO_parser_param * p, const char* msg)
363{
364  /* message format = "Lock order dependencies file <%s> (%d:%d) - (%d:%d) : %s" */
365  LogErr(ERROR_LEVEL, ER_LOCK_ORDER_DEPENDENCIES_SYNTAX,
366    p->m_filename,
367    yylloc_param->first_line,
368    yylloc_param->first_column,
369    yylloc_param->last_line,
370    yylloc_param->last_column,
371    msg);
372}
373
374