From 9638c29114c8d575d1b89c26dcf1f274ea6ab6c4 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 17 Sep 2013 13:02:05 +0800 Subject: [PATCH] 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 --- discover/grub2/grub2.h | 21 +++++++++++++++------ discover/grub2/parser.y | 41 ++++++++++++++++++++++++++--------------- 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 %type statements +%type conditional %type words %type 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; } -- 2.39.2