3 %lex-param { yyscan_t scanner }
4 %parse-param { struct grub2_parser *parser }
8 #include <talloc/talloc.h>
14 static void print_token(FILE *fp, int type, YYSTYPE value);
16 #define YYLEX_PARAM parser->scanner
17 #define YYPRINT(f, t, v) print_token(f, t, v)
19 static void yyerror(struct grub2_parser *, char const *s);
23 struct grub2_word *word;
24 struct grub2_argv *argv;
25 struct grub2_statement *statement;
26 struct grub2_statements *statements;
30 %token TOKEN_LDSQBRACKET "[["
31 %token TOKEN_RDSQBRACKET "]]"
32 %token TOKEN_CASE "case"
34 %token TOKEN_DONE "done"
35 %token TOKEN_ELIF "elif"
36 %token TOKEN_ELSE "else"
37 %token TOKEN_ESAC "esac"
39 %token TOKEN_FOR "for"
40 %token TOKEN_FUNCTION "function"
43 %token TOKEN_MENUENTRY "menuentry"
44 %token TOKEN_SELECT "select"
45 %token TOKEN_SUBMENU "submenu"
46 %token TOKEN_THEN "then"
47 %token TOKEN_TIME "time"
48 %token TOKEN_UTIL "until"
49 %token TOKEN_WHILE "while"
51 %type <statement> statement
52 %type <statements> statements
53 %type <statement> conditional
54 %type <statement> elif
55 %type <statements> elifs
62 %token <word> TOKEN_WORD
71 parser->script->statements = $1;
74 eol: TOKEN_EOL | TOKEN_EOF;
76 statements: /* empty */ {
77 $$ = create_statements(parser);
79 | statements statement eol {
80 statement_append($1, $2);
83 | statements TOKEN_EOL {
87 sep: TOKEN_DELIM | TOKEN_EOL;
89 conditional: statement TOKEN_EOL "then" sep statements {
90 $$ = create_statement_conditional(parser, $1, $5);
93 elif: "elif" TOKEN_DELIM conditional {
98 $$ = create_statements(parser);
101 statement_append($1, $2);
107 $$ = create_statement_simple(parser, $1);
109 | '{' statements '}' {
110 $$ = create_statement_block(parser, $2);
112 | "if" TOKEN_DELIM conditional elifs "fi" {
113 $$ = create_statement_if(parser, $3, $4, NULL);
115 | "if" TOKEN_DELIM conditional
120 $$ = create_statement_if(parser, $3, $4, $7);
122 | "function" TOKEN_DELIM word TOKEN_DELIM '{' statements '}' {
123 $$ = create_statement_function(parser, $3, $6);
125 | "menuentry" TOKEN_DELIM words TOKEN_DELIM
127 $$ = create_statement_menuentry(parser, $3, $6);
129 | "submenu" TOKEN_DELIM words TOKEN_DELIM
131 /* we just flatten everything */
132 $$ = create_statement_block(parser, $6);
136 $$ = create_argv(parser);
139 | words TOKEN_DELIM word {
151 void yyerror(struct grub2_parser *parser, char const *s)
153 fprintf(stderr, "%d: error: %s '%s'\n",
154 yyget_lineno(parser->scanner),
155 s, yyget_text(parser->scanner));
158 static void print_token(FILE *fp, int type, YYSTYPE value)
160 if (type != TOKEN_WORD)
162 fprintf(fp, "%s", value.word->text);
165 struct grub2_statements *create_statements(struct grub2_parser *parser)
167 struct grub2_statements *stmts = talloc(parser,
168 struct grub2_statements);
169 list_init(&stmts->list);
173 struct grub2_statement *create_statement_simple(struct grub2_parser *parser,
174 struct grub2_argv *argv)
176 struct grub2_statement_simple *stmt =
177 talloc(parser, struct grub2_statement_simple);
178 stmt->st.type = STMT_TYPE_SIMPLE;
179 stmt->st.exec = statement_simple_execute;
184 struct grub2_statement *create_statement_menuentry(struct grub2_parser *parser,
185 struct grub2_argv *argv, struct grub2_statements *stmts)
187 struct grub2_statement_menuentry *stmt =
188 talloc(parser, struct grub2_statement_menuentry);
189 stmt->st.type = STMT_TYPE_MENUENTRY;
190 stmt->st.exec = statement_menuentry_execute;
192 stmt->statements = stmts;
196 struct grub2_statement *create_statement_conditional(
197 struct grub2_parser *parser,
198 struct grub2_statement *condition,
199 struct grub2_statements *statements)
201 struct grub2_statement_conditional *stmt =
202 talloc(parser, struct grub2_statement_conditional);
203 stmt->st.type = STMT_TYPE_CONDITIONAL;
204 stmt->condition = condition;
205 stmt->statements = statements;
209 struct grub2_statement *create_statement_if(struct grub2_parser *parser,
210 struct grub2_statement *conditional,
211 struct grub2_statements *elifs,
212 struct grub2_statements *else_case)
214 struct grub2_statement_if *stmt =
215 talloc(parser, struct grub2_statement_if);
217 list_add(&elifs->list, &conditional->list);
219 stmt->st.type = STMT_TYPE_IF;
220 stmt->st.exec = statement_if_execute;
221 stmt->conditionals = elifs;
222 stmt->else_case = else_case;
226 struct grub2_statement *create_statement_block(struct grub2_parser *parser,
227 struct grub2_statements *stmts)
229 struct grub2_statement_block *stmt =
230 talloc(parser, struct grub2_statement_block);
231 stmt->st.type = STMT_TYPE_BLOCK;
232 stmt->st.exec = statement_block_execute;
233 stmt->statements = stmts;
237 struct grub2_statement *create_statement_function(struct grub2_parser *parser,
238 struct grub2_word *name, struct grub2_statements *body)
240 struct grub2_statement_function *stmt =
241 talloc(parser, struct grub2_statement_function);
242 stmt->st.exec = statement_function_execute;
248 void statement_append(struct grub2_statements *stmts,
249 struct grub2_statement *stmt)
253 list_add_tail(&stmts->list, &stmt->list);
256 struct grub2_word *create_word_text(struct grub2_parser *parser,
259 struct grub2_word *word = talloc(parser, struct grub2_word);
260 word->type = GRUB2_WORD_TEXT;
262 word->text = talloc_strdup(word, text);
268 struct grub2_word *create_word_var(struct grub2_parser *parser,
269 const char *name, bool split)
271 struct grub2_word *word = talloc(parser, struct grub2_word);
272 word->type = GRUB2_WORD_VAR;
273 word->name = talloc_strdup(word, name);
280 struct grub2_argv *create_argv(struct grub2_parser *parser)
282 struct grub2_argv *argv = talloc(parser, struct grub2_argv);
283 list_init(&argv->words);
287 void argv_append(struct grub2_argv *argv, struct grub2_word *word)
289 list_add_tail(&argv->words, &word->argv_list);
292 void word_append(struct grub2_word *w1, struct grub2_word *w2)
298 struct grub2_parser *grub2_parser_create(struct discover_context *ctx)
300 struct grub2_parser *parser;
302 parser = talloc(ctx, struct grub2_parser);
303 yylex_init_extra(parser, &parser->scanner);
304 parser->script = create_script(parser, ctx);
309 void grub2_parser_parse(struct grub2_parser *parser, char *buf, int len)
311 YY_BUFFER_STATE bufstate;
314 bufstate = yy_scan_bytes(buf, len - 1, parser->scanner);
316 rc = yyparse(parser);
318 yy_delete_buffer(bufstate, parser->scanner);
321 script_execute(parser->script);