diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2013-09-17 13:02:05 +0800 |
---|---|---|
committer | Jeremy Kerr <jk@ozlabs.org> | 2013-09-24 13:14:59 +0800 |
commit | 9638c29114c8d575d1b89c26dcf1f274ea6ab6c4 (patch) | |
tree | d39b3d16444474f7018a1948d59c7e479f3fd5ee /discover | |
parent | 63575c2045b1505da7a2abca8a51a4a7aa3df6f7 (diff) | |
download | talos-petitboot-9638c29114c8d575d1b89c26dcf1f274ea6ab6c4.tar.gz talos-petitboot-9638c29114c8d575d1b89c26dcf1f274ea6ab6c4.zip |
discover/grub2: Create 'conditional' statements
Rather than holding the condition and conditional-statements in struct
grub2_statment_if, create a new conditional type that contains these. We
can then use this to implement elif statements.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'discover')
-rw-r--r-- | discover/grub2/grub2.h | 21 | ||||
-rw-r--r-- | discover/grub2/parser.y | 41 | ||||
-rw-r--r-- | discover/grub2/script.c | 34 |
3 files changed, 65 insertions, 31 deletions
diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h index 5b83fad..7f4a834 100644 --- a/discover/grub2/grub2.h +++ b/discover/grub2/grub2.h @@ -43,6 +43,7 @@ struct grub2_statement { STMT_TYPE_MENUENTRY, STMT_TYPE_IF, STMT_TYPE_BLOCK, + STMT_TYPE_CONDITIONAL, } type; int (*exec)(struct grub2_script *, struct grub2_statement *); @@ -59,11 +60,16 @@ struct grub2_statement_menuentry { struct grub2_statements *statements; }; -struct grub2_statement_if { +struct grub2_statement_conditional { struct grub2_statement st; struct grub2_statement *condition; - struct grub2_statements *true_case; - struct grub2_statements *false_case; + struct grub2_statements *statements; +}; + +struct grub2_statement_if { + struct grub2_statement st; + struct grub2_statement *conditional; + struct grub2_statements *else_case; }; struct grub2_statement_block { @@ -102,10 +108,13 @@ struct grub2_statement *create_statement_simple(struct grub2_parser *parser, struct grub2_statement *create_statement_menuentry(struct grub2_parser *parser, struct grub2_argv *argv, struct grub2_statements *stmts); +struct grub2_statement *create_statement_conditional( + struct grub2_parser *parser, struct grub2_statement *condition, + struct grub2_statements *statements); + struct grub2_statement *create_statement_if(struct grub2_parser *parser, - struct grub2_statement *condition, - struct grub2_statements *true_case, - struct grub2_statements *false_case); + struct grub2_statement *conditional, + struct grub2_statements *else_case); struct grub2_statement *create_statement_block(struct grub2_parser *parser, struct grub2_statements *stmts); diff --git a/discover/grub2/parser.y b/discover/grub2/parser.y index 0540ff3..52dac9c 100644 --- a/discover/grub2/parser.y +++ b/discover/grub2/parser.y @@ -47,6 +47,7 @@ static void yyerror(struct grub2_parser *, char const *s); %type <statement> statement %type <statements> statements +%type <statement> conditional %type <argv> words %type <word> word @@ -75,6 +76,10 @@ statements: /* empty */ { $$ = $1; } +conditional: statement TOKEN_EOL "then" TOKEN_EOL statements { + $$ = create_statement_conditional(parser, $1, $5); + } + statement: words { $$ = create_statement_simple(parser, $1); @@ -82,19 +87,14 @@ statement: | '{' statements '}' { $$ = create_statement_block(parser, $2); } - | "if" TOKEN_DELIM statement - "then" TOKEN_EOL - statements - "fi" { - $$ = create_statement_if(parser, $3, $6, NULL); + | "if" TOKEN_DELIM conditional "fi" { + $$ = create_statement_if(parser, $3, NULL); } - | "if" TOKEN_DELIM statement - "then" TOKEN_EOL - statements + | "if" TOKEN_DELIM conditional "else" TOKEN_EOL statements "fi" { - $$ = create_statement_if(parser, $3, $6, $9); + $$ = create_statement_if(parser, $3, $6); } | "function" TOKEN_DELIM word TOKEN_DELIM '{' statements '}' { $$ = create_statement_function(parser, $3, $6); @@ -163,18 +163,29 @@ struct grub2_statement *create_statement_menuentry(struct grub2_parser *parser, return &stmt->st; } -struct grub2_statement *create_statement_if(struct grub2_parser *parser, +struct grub2_statement *create_statement_conditional( + struct grub2_parser *parser, struct grub2_statement *condition, - struct grub2_statements *true_case, - struct grub2_statements *false_case) + struct grub2_statements *statements) +{ + struct grub2_statement_conditional *stmt = + talloc(parser, struct grub2_statement_conditional); + stmt->st.type = STMT_TYPE_CONDITIONAL; + stmt->condition = condition; + stmt->statements = statements; + return &stmt->st; +} + +struct grub2_statement *create_statement_if(struct grub2_parser *parser, + struct grub2_statement *conditional, + struct grub2_statements *else_case) { struct grub2_statement_if *stmt = talloc(parser, struct grub2_statement_if); stmt->st.type = STMT_TYPE_IF; stmt->st.exec = statement_if_execute; - stmt->condition = condition; - stmt->true_case = true_case; - stmt->false_case = false_case; + stmt->conditional = conditional; + stmt->else_case = else_case; return &stmt->st; } diff --git a/discover/grub2/script.c b/discover/grub2/script.c index 9c08737..c0d6e1a 100644 --- a/discover/grub2/script.c +++ b/discover/grub2/script.c @@ -15,6 +15,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_conditional(stmt) \ + container_of(stmt, struct grub2_statement_conditional, st) struct env_entry { const char *name; @@ -252,24 +254,36 @@ int statement_simple_execute(struct grub2_script *script, return rc; } +/* returns 0 if the statement was executed, 1 otherwise */ +static int statement_conditional_execute(struct grub2_script *script, + struct grub2_statement *statement, bool *executed) +{ + struct grub2_statement_conditional *st = to_stmt_conditional(statement); + int rc; + + rc = st->condition->exec(script, st->condition); + *executed = (!rc); + if (*executed) + rc = statements_execute(script, st->statements); + + return rc; +} + int statement_if_execute(struct grub2_script *script, struct grub2_statement *statement) { struct grub2_statement_if *st = to_stmt_if(statement); - struct grub2_statements *case_stmts; + struct grub2_statement *conditional; + bool executed; int rc; - rc = st->condition->exec(script, st->condition); + conditional = st->conditional; - if (rc == 0) - case_stmts = st->true_case; - else - case_stmts = st->false_case; + rc = statement_conditional_execute(script, + conditional, &executed); - if (case_stmts) - statements_execute(script, case_stmts); - else - rc = 0; + if (!executed && st->else_case) + rc = statements_execute(script, st->else_case); return rc; } |