Fix hang/crash when requesting ZPOOL with incorrect backing device
[grub2/phcoder.git] / script / sh / parser.y
blob094a8856e57b3f14838758fbb929f954804c530c
1 /* parser.y - The scripting parser. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
6 * GRUB 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, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/script_sh.h>
22 #include <grub/mm.h>
24 #define YYFREE grub_free
25 #define YYMALLOC grub_malloc
26 #define YYLTYPE_IS_TRIVIAL 0
27 #define YYENABLE_NLS 0
31 %union {
32 struct grub_script_cmd *cmd;
33 struct grub_script_arglist *arglist;
34 struct grub_script_arg *arg;
35 char *string;
38 %token GRUB_PARSER_TOKEN_IF "if"
39 %token GRUB_PARSER_TOKEN_WHILE "while"
40 %token GRUB_PARSER_TOKEN_FUNCTION "function"
41 %token GRUB_PARSER_TOKEN_MENUENTRY "menuentry"
42 %token GRUB_PARSER_TOKEN_ELSE "else"
43 %token GRUB_PARSER_TOKEN_THEN "then"
44 %token GRUB_PARSER_TOKEN_FI "fi"
45 %token GRUB_PARSER_TOKEN_ARG
46 %type <cmd> script_init script grubcmd command commands commandblock menuentry if
47 %type <arglist> arguments;
48 %type <arg> GRUB_PARSER_TOKEN_ARG;
50 %pure-parser
51 %lex-param { struct grub_parser_param *state };
52 %parse-param { struct grub_parser_param *state };
55 /* It should be possible to do this in a clean way... */
56 script_init: { state->err = 0; } script
58 state->parsed = $2;
62 script: { $$ = 0; }
63 | '\n' { $$ = 0; }
64 | commands { $$ = $1; }
65 | function '\n' { $$ = 0; }
66 | menuentry '\n' { $$ = $1; }
67 | error
69 $$ = 0;
70 yyerror (state, "Incorrect command");
71 state->err = 1;
72 yyerrok;
76 delimiter: '\n'
77 | ';'
78 | delimiter '\n'
81 newlines: /* Empty */
82 | newlines '\n'
87 arguments: GRUB_PARSER_TOKEN_ARG
89 $$ = grub_script_add_arglist (state, 0, $1);
91 | arguments GRUB_PARSER_TOKEN_ARG
93 $$ = grub_script_add_arglist (state, $1, $2);
97 grubcmd: arguments
99 $$ = grub_script_create_cmdline (state, $1);
103 /* A single command. */
104 command: grubcmd delimiter { $$ = $1; }
105 | if delimiter { $$ = $1; }
106 | commandblock delimiter { $$ = $1; }
109 /* A block of commands. */
110 commands: command
112 $$ = grub_script_add_cmd (state, 0, $1);
114 | command commands
116 struct grub_script_cmdblock *cmd;
117 cmd = (struct grub_script_cmdblock *) $2;
118 $$ = grub_script_add_cmd (state, cmd, $1);
122 /* A function. Carefully save the memory that is allocated. Don't
123 change any stuff because it might seem like a fun thing to do!
124 Special care was take to make sure the mid-rule actions are
125 executed on the right moment. So the `commands' rule should be
126 recognized after executing the `grub_script_mem_record; and before
127 `grub_script_mem_record_stop'. */
128 function: "function" GRUB_PARSER_TOKEN_ARG
130 grub_script_lexer_ref (state->lexerstate);
131 } newlines '{'
133 /* The first part of the function was recognized.
134 Now start recording the memory usage to store
135 this function. */
136 state->func_mem = grub_script_mem_record (state);
137 } newlines commands '}'
139 struct grub_script *script;
141 /* All the memory usage for parsing this function
142 was recorded. */
143 state->func_mem = grub_script_mem_record_stop (state,
144 state->func_mem);
145 script = grub_script_create ($8, state->func_mem);
146 if (script)
147 grub_script_function_create ($2, script);
148 grub_script_lexer_deref (state->lexerstate);
152 /* Carefully designed, together with `menuentry' so everything happens
153 just in the expected order. */
154 commandblock: '{'
156 grub_script_lexer_ref (state->lexerstate);
158 newlines commands '}'
160 grub_script_lexer_deref (state->lexerstate);
161 $$ = $4;
165 /* A menu entry. Carefully save the memory that is allocated. */
166 menuentry: "menuentry"
168 grub_script_lexer_ref (state->lexerstate);
169 } arguments newlines '{'
171 grub_script_lexer_record_start (state->lexerstate);
172 } newlines commands '}'
174 char *menu_entry;
175 menu_entry = grub_script_lexer_record_stop (state->lexerstate);
176 grub_script_lexer_deref (state->lexerstate);
177 $$ = grub_script_create_cmdmenu (state, $3, menu_entry, 0);
181 /* The first part of the if statement. It's used to switch the lexer
182 to a state in which it demands more tokens. */
183 if_statement: "if" { grub_script_lexer_ref (state->lexerstate); }
186 /* The if statement. */
187 if: if_statement commands "then" newlines commands "fi"
189 $$ = grub_script_create_cmdif (state, $2, $5, 0);
190 grub_script_lexer_deref (state->lexerstate);
192 | if_statement commands "then" newlines commands "else" newlines commands "fi"
194 $$ = grub_script_create_cmdif (state, $2, $5, $8);
195 grub_script_lexer_deref (state->lexerstate);