summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2014-01-24 14:40:46 +0800
committerJeremy Kerr <jk@ozlabs.org>2014-01-30 21:59:10 +0800
commit1b272c7d47390077eee0a0638329b1a7df521329 (patch)
tree43b348731a7db7585050ebc8140790f91232b01a
parente1b713b0c862a93cd3e8cea59070f469510d3c39 (diff)
downloadtalos-petitboot-1b272c7d47390077eee0a0638329b1a7df521329.tar.gz
talos-petitboot-1b272c7d47390077eee0a0638329b1a7df521329.zip
discover/grub2: Add support for for-loops
GRUB2 syntax allows for for-loops; this change adds supoprt in the parser grammar and script execution code to implement them. In the execution code, we simply update the for-loop variable and re-execute the body statements. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
-rw-r--r--discover/grub2/grub2.h13
-rw-r--r--discover/grub2/parser.y19
-rw-r--r--discover/grub2/script.c23
3 files changed, 55 insertions, 0 deletions
diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h
index 6166289..e79bf41 100644
--- a/discover/grub2/grub2.h
+++ b/discover/grub2/grub2.h
@@ -83,6 +83,13 @@ struct grub2_statement_function {
struct grub2_statements *body;
};
+struct grub2_statement_for {
+ struct grub2_statement st;
+ struct grub2_word *var;
+ struct grub2_argv *list;
+ struct grub2_statements *body;
+};
+
struct grub2_script {
struct grub2_statements *statements;
struct list environment;
@@ -125,6 +132,10 @@ struct grub2_statement *create_statement_block(struct grub2_parser *parser,
struct grub2_statement *create_statement_function(struct grub2_parser *parser,
struct grub2_word *name, struct grub2_statements *body);
+struct grub2_statement *create_statement_for(struct grub2_parser *parser,
+ struct grub2_word *var, struct grub2_argv *list,
+ struct grub2_statements *body);
+
struct grub2_word *create_word_text(struct grub2_parser *parser,
const char *text);
@@ -153,6 +164,8 @@ int statement_menuentry_execute(struct grub2_script *script,
struct grub2_statement *statement);
int statement_function_execute(struct grub2_script *script,
struct grub2_statement *statement);
+int statement_for_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 0beddd6..23bf427 100644
--- a/discover/grub2/parser.y
+++ b/discover/grub2/parser.y
@@ -130,6 +130,12 @@ statement:
/* we just flatten everything */
$$ = create_statement_block(parser, $6);
}
+ | "for" TOKEN_DELIM word TOKEN_DELIM "in" TOKEN_DELIM words TOKEN_EOL
+ "do" sep
+ statements
+ "done" {
+ $$ = create_statement_for(parser, $3, $7, $11);
+ }
words: word {
$$ = create_argv(parser);
@@ -243,6 +249,19 @@ struct grub2_statement *create_statement_function(struct grub2_parser *parser,
return &stmt->st;
}
+struct grub2_statement *create_statement_for(struct grub2_parser *parser,
+ struct grub2_word *var, struct grub2_argv *list,
+ struct grub2_statements *body)
+{
+ struct grub2_statement_for *stmt =
+ talloc(parser, struct grub2_statement_for);
+ stmt->st.exec = statement_for_execute;
+ stmt->var = var;
+ stmt->list = list;
+ 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 bfca607..0618297 100644
--- a/discover/grub2/script.c
+++ b/discover/grub2/script.c
@@ -19,6 +19,8 @@
container_of(stmt, struct grub2_statement_menuentry, st)
#define to_stmt_function(stmt) \
container_of(stmt, struct grub2_statement_function, st)
+#define to_stmt_for(stmt) \
+ container_of(stmt, struct grub2_statement_for, st)
#define to_stmt_conditional(stmt) \
container_of(stmt, struct grub2_statement_conditional, st)
@@ -401,6 +403,27 @@ int statement_function_execute(struct grub2_script *script,
return 0;
}
+int statement_for_execute(struct grub2_script *script,
+ struct grub2_statement *statement)
+{
+ struct grub2_statement_for *st = to_stmt_for(statement);
+ const char *varname;
+ int i, rc = 0;
+
+ if (st->var->type == GRUB2_WORD_VAR)
+ expand_var(script, st->var);
+ varname = st->var->text;
+
+ process_expansions(script, st->list);
+
+ for (i = 0; i < st->list->argc; ++i) {
+ script_env_set(script, varname, st->list->argv[i]);
+ rc = statements_execute(script, st->body);
+ }
+
+ return rc;
+}
+
static void init_env(struct grub2_script *script)
{
struct env_entry *env;
OpenPOWER on IntegriCloud