diff options
Diffstat (limited to 'discover/grub2')
-rw-r--r-- | discover/grub2/grub2.h | 10 | ||||
-rw-r--r-- | discover/grub2/parser.y | 14 | ||||
-rw-r--r-- | discover/grub2/script.c | 33 |
3 files changed, 57 insertions, 0 deletions
diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h index 4949f3c..5b83fad 100644 --- a/discover/grub2/grub2.h +++ b/discover/grub2/grub2.h @@ -71,6 +71,11 @@ struct grub2_statement_block { struct grub2_statements *statements; }; +struct grub2_statement_function { + struct grub2_statement st; + struct grub2_word *name; + struct grub2_statements *body; +}; struct grub2_script { struct grub2_statements *statements; @@ -105,6 +110,9 @@ struct grub2_statement *create_statement_if(struct grub2_parser *parser, struct grub2_statement *create_statement_block(struct grub2_parser *parser, struct grub2_statements *stmts); +struct grub2_statement *create_statement_function(struct grub2_parser *parser, + struct grub2_word *name, struct grub2_statements *body); + struct grub2_word *create_word_text(struct grub2_parser *parser, const char *text); @@ -129,6 +137,8 @@ int statement_if_execute(struct grub2_script *script, struct grub2_statement *statement); int statement_menuentry_execute(struct grub2_script *script, struct grub2_statement *statement); +int statement_function_execute(struct grub2_script *script, + struct grub2_statement *statement); struct grub2_script *create_script(struct grub2_parser *parser, struct discover_context *ctx); diff --git a/discover/grub2/parser.y b/discover/grub2/parser.y index 550c374..bcf5935 100644 --- a/discover/grub2/parser.y +++ b/discover/grub2/parser.y @@ -95,6 +95,9 @@ statement: TOKEN_EOL { "fi" TOKEN_EOL { $$ = create_statement_if(parser, $3, $6, $9); } + | "function" TOKEN_DELIM word TOKEN_DELIM '{' statements '}' { + $$ = create_statement_function(parser, $3, $6); + } | "menuentry" TOKEN_DELIM words TOKEN_DELIM '{' statements '}' TOKEN_EOL { @@ -181,6 +184,17 @@ struct grub2_statement *create_statement_block(struct grub2_parser *parser, return &stmt->st; } +struct grub2_statement *create_statement_function(struct grub2_parser *parser, + struct grub2_word *name, struct grub2_statements *body) +{ + struct grub2_statement_function *stmt = + talloc(parser, struct grub2_statement_function); + stmt->st.exec = statement_function_execute; + stmt->name = name; + stmt->body = body; + return &stmt->st; +} + void statement_append(struct grub2_statements *stmts, struct grub2_statement *stmt) { diff --git a/discover/grub2/script.c b/discover/grub2/script.c index ec37fbb..9c08737 100644 --- a/discover/grub2/script.c +++ b/discover/grub2/script.c @@ -13,6 +13,8 @@ container_of(stmt, struct grub2_statement_if, st) #define to_stmt_menuentry(stmt) \ container_of(stmt, struct grub2_statement_menuentry, st) +#define to_stmt_function(stmt) \ + container_of(stmt, struct grub2_statement_function, st) struct env_entry { const char *name; @@ -297,6 +299,37 @@ int statement_menuentry_execute(struct grub2_script *script, return 0; } +static int function_invoke(struct grub2_script *script, + void *data, int argc, char **argv) +{ + struct grub2_statement_function *fn = data; + char *name; + int i; + + /* set positional parameters */ + for (i = 0; i < argc; i++) { + name = talloc_asprintf(script, "$%d", i); + script_env_set(script, name, argv[i]); + } + + return statements_execute(script, fn->body); +} + +int statement_function_execute(struct grub2_script *script, + struct grub2_statement *statement) +{ + struct grub2_statement_function *st = to_stmt_function(statement); + const char *name; + + if (st->name->type == GRUB2_WORD_VAR) + expand_var(script, st->name); + + name = st->name->text; + script_register_function(script, name, function_invoke, st); + + return 0; +} + static void init_env(struct grub2_script *script) { struct env_entry *env; |