discover/grub2: Add function support
authorJeremy Kerr <jk@ozlabs.org>
Tue, 17 Sep 2013 01:36:11 +0000 (09:36 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Tue, 24 Sep 2013 05:14:59 +0000 (13:14 +0800)
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
discover/grub2/grub2.h
discover/grub2/parser.y
discover/grub2/script.c

index 4949f3c031a9027f4aa5e42c9c92626ff5258535..5b83fad5d05f38503fd755207de96b8955d800cd 100644 (file)
@@ -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);
index 550c3748df70c0ec1a3636a3f2fc0e242e19e9ef..bcf5935d58015c054b7666e8a0595bbd732c786b 100644 (file)
@@ -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)
 {
index ec37fbb0c06bc1b8da5984e339c90a27502689a3..9c087373ac0454524308fa6da5370a0b86b69cc5 100644 (file)
@@ -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;