While and until loops support to GRUB script.
* include/grub/script_sh.h (grub_script_cmdwhile): New struct. (grub_script_create_cmdwhile): New function prototype. (grub_script_execute_cmdwhile): New function prototype. * script/execute.c (grub_script_execute_cmdwhile): New function. * script/parser.y (command): New commands. (whilecmd): New grammar rule. (untilcmd): New grammar rule. * script/script.c (grub_script_create_cmdwhile): New function. * util/grub-script-check.c (grub_script_execute_cmdwhile): New function. * tests/grub_script_while1.in: New testcase. * conf/tests.rmk: Rule for new testcase.
This commit is contained in:
commit
34bb22dfa5
8 changed files with 169 additions and 8 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
2010-04-09 BVK Chaitanya <bvk.groups@gmail.com>
|
||||
|
||||
While and until loops support to GRUB script.
|
||||
|
||||
* include/grub/script_sh.h (grub_script_cmdwhile): New struct.
|
||||
(grub_script_create_cmdwhile): New function prototype.
|
||||
(grub_script_execute_cmdwhile): New function prototype.
|
||||
* script/execute.c (grub_script_execute_cmdwhile): New function.
|
||||
* script/parser.y (command): New commands.
|
||||
(whilecmd): New grammar rule.
|
||||
(untilcmd): New grammar rule.
|
||||
* script/script.c (grub_script_create_cmdwhile): New function.
|
||||
* util/grub-script-check.c (grub_script_execute_cmdwhile): New
|
||||
function.
|
||||
|
||||
* tests/grub_script_while1.in: New testcase.
|
||||
* conf/tests.rmk: Rule for new testcase.
|
||||
|
||||
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
* util/grub.d/00_header.in: Add few missing quotes. Recognise *.jpeg
|
||||
|
|
|
@ -53,6 +53,9 @@ grub_script_vars1_SOURCES = tests/grub_script_vars1.in
|
|||
check_SCRIPTS += grub_script_for1
|
||||
grub_script_for1_SOURCES = tests/grub_script_for1.in
|
||||
|
||||
check_SCRIPTS += grub_script_while1
|
||||
grub_script_while1_SOURCES = tests/grub_script_while1.in
|
||||
|
||||
check_SCRIPTS += grub_script_blanklines
|
||||
grub_script_blanklines_SOURCES = tests/grub_script_blanklines.in
|
||||
|
||||
|
@ -69,6 +72,7 @@ SCRIPTED_TESTS = grub_script_echo1
|
|||
SCRIPTED_TESTS += grub_script_echo_keywords
|
||||
SCRIPTED_TESTS += grub_script_vars1
|
||||
SCRIPTED_TESTS += grub_script_for1
|
||||
SCRIPTED_TESTS += grub_script_while1
|
||||
SCRIPTED_TESTS += grub_script_blanklines
|
||||
SCRIPTED_TESTS += grub_script_final_semicolon
|
||||
|
||||
|
|
|
@ -121,6 +121,21 @@ struct grub_script_cmdfor
|
|||
struct grub_script_cmd *list;
|
||||
};
|
||||
|
||||
/* A while/until command. */
|
||||
struct grub_script_cmdwhile
|
||||
{
|
||||
struct grub_script_cmd cmd;
|
||||
|
||||
/* The command list used as condition. */
|
||||
struct grub_script_cmd *cond;
|
||||
|
||||
/* The command list executed in each loop. */
|
||||
struct grub_script_cmd *list;
|
||||
|
||||
/* The flag to indicate this as "until" loop. */
|
||||
int until;
|
||||
};
|
||||
|
||||
/* A menu entry generate statement. */
|
||||
struct grub_script_cmd_menuentry
|
||||
{
|
||||
|
@ -234,6 +249,12 @@ grub_script_create_cmdfor (struct grub_parser_param *state,
|
|||
struct grub_script_arglist *words,
|
||||
struct grub_script_cmd *list);
|
||||
|
||||
struct grub_script_cmd *
|
||||
grub_script_create_cmdwhile (struct grub_parser_param *state,
|
||||
struct grub_script_cmd *cond,
|
||||
struct grub_script_cmd *list,
|
||||
int is_an_until_loop);
|
||||
|
||||
struct grub_script_cmd *
|
||||
grub_script_create_cmdmenu (struct grub_parser_param *state,
|
||||
struct grub_script_arglist *arglist,
|
||||
|
@ -283,6 +304,7 @@ grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd);
|
|||
grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd);
|
||||
grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd);
|
||||
grub_err_t grub_script_execute_cmdfor (struct grub_script_cmd *cmd);
|
||||
grub_err_t grub_script_execute_cmdwhile (struct grub_script_cmd *cmd);
|
||||
grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd);
|
||||
|
||||
/* Execute any GRUB pre-parsed command or script. */
|
||||
|
|
|
@ -26,13 +26,24 @@
|
|||
#include <grub/lib/arg.h>
|
||||
#include <grub/normal.h>
|
||||
|
||||
/* Max digits for a char is 3 (0xFF is 255), similarly for an int it
|
||||
is sizeof (int) * 3, and one extra for a possible -ve sign. */
|
||||
#define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1)
|
||||
|
||||
static grub_err_t
|
||||
grub_script_execute_cmd (struct grub_script_cmd *cmd)
|
||||
{
|
||||
int ret;
|
||||
char errnobuf[ERRNO_DIGITS_MAX + 1];
|
||||
|
||||
if (cmd == 0)
|
||||
return 0;
|
||||
|
||||
return cmd->exec (cmd);
|
||||
ret = cmd->exec (cmd);
|
||||
|
||||
grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret);
|
||||
grub_env_set ("?", errnobuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ARG_ALLOCATION_UNIT (32 * sizeof (char))
|
||||
|
@ -260,13 +271,14 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
|
|||
grub_err_t
|
||||
grub_script_execute_cmdblock (struct grub_script_cmd *cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
struct grub_script_cmdblock *cmdblock = (struct grub_script_cmdblock *) cmd;
|
||||
|
||||
/* Loop over every command and execute it. */
|
||||
for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next)
|
||||
grub_script_execute_cmd (cmd);
|
||||
ret = grub_script_execute_cmd (cmd);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Execute an if statement. */
|
||||
|
@ -317,6 +329,26 @@ grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Execute a "while" or "until" command. */
|
||||
grub_err_t
|
||||
grub_script_execute_cmdwhile (struct grub_script_cmd *cmd)
|
||||
{
|
||||
int cond;
|
||||
int result;
|
||||
struct grub_script_cmdwhile *cmdwhile = (struct grub_script_cmdwhile *) cmd;
|
||||
|
||||
result = 0;
|
||||
do {
|
||||
cond = grub_script_execute_cmd (cmdwhile->cond);
|
||||
if (cmdwhile->until ? !cond : cond)
|
||||
break;
|
||||
|
||||
result = grub_script_execute_cmd (cmdwhile->list);
|
||||
} while (1); /* XXX Put a check for ^C here */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Execute the menu entry generate statement. */
|
||||
grub_err_t
|
||||
grub_script_execute_menuentry (struct grub_script_cmd *cmd)
|
||||
|
|
|
@ -74,8 +74,9 @@
|
|||
%token <arg> GRUB_PARSER_TOKEN_WORD "word"
|
||||
|
||||
%type <arglist> word argument arguments0 arguments1
|
||||
%type <cmd> script_init script grubcmd ifcmd forcmd command
|
||||
%type <cmd> commands1 menuentry statement
|
||||
%type <cmd> script_init script
|
||||
%type <cmd> grubcmd ifcmd forcmd whilecmd untilcmd
|
||||
%type <cmd> command commands1 menuentry statement
|
||||
|
||||
%pure-parser
|
||||
%lex-param { struct grub_parser_param *state };
|
||||
|
@ -174,6 +175,8 @@ grubcmd: word arguments0
|
|||
command: grubcmd { $$ = $1; }
|
||||
| ifcmd { $$ = $1; }
|
||||
| forcmd { $$ = $1; }
|
||||
| whilecmd { $$ = $1; }
|
||||
| untilcmd { $$ = $1; }
|
||||
;
|
||||
|
||||
/* A list of commands. */
|
||||
|
@ -248,3 +251,25 @@ forcmd: "for" "name"
|
|||
grub_script_lexer_deref (state->lexerstate);
|
||||
}
|
||||
;
|
||||
|
||||
whilecmd: "while"
|
||||
{
|
||||
grub_script_lexer_ref (state->lexerstate);
|
||||
}
|
||||
commands1 delimiters1 "do" commands1 delimiters1 "done"
|
||||
{
|
||||
$$ = grub_script_create_cmdwhile (state, $3, $6, 0);
|
||||
grub_script_lexer_deref (state->lexerstate);
|
||||
}
|
||||
;
|
||||
|
||||
untilcmd: "until"
|
||||
{
|
||||
grub_script_lexer_ref (state->lexerstate);
|
||||
}
|
||||
commands1 delimiters1 "do" commands1 delimiters1 "done"
|
||||
{
|
||||
$$ = grub_script_create_cmdwhile (state, $3, $6, 1);
|
||||
grub_script_lexer_deref (state->lexerstate);
|
||||
}
|
||||
;
|
||||
|
|
|
@ -245,6 +245,28 @@ grub_script_create_cmdfor (struct grub_parser_param *state,
|
|||
return (struct grub_script_cmd *) cmd;
|
||||
}
|
||||
|
||||
/* Create a "while" or "until" command. */
|
||||
struct grub_script_cmd *
|
||||
grub_script_create_cmdwhile (struct grub_parser_param *state,
|
||||
struct grub_script_cmd *cond,
|
||||
struct grub_script_cmd *list,
|
||||
int is_an_until_loop)
|
||||
{
|
||||
struct grub_script_cmdwhile *cmd;
|
||||
|
||||
cmd = grub_script_malloc (state, sizeof (*cmd));
|
||||
if (! cmd)
|
||||
return 0;
|
||||
|
||||
cmd->cmd.exec = grub_script_execute_cmdwhile;
|
||||
cmd->cmd.next = 0;
|
||||
cmd->cond = cond;
|
||||
cmd->list = list;
|
||||
cmd->until = is_an_until_loop;
|
||||
|
||||
return (struct grub_script_cmd *) cmd;
|
||||
}
|
||||
|
||||
/* Create a command that adds a menu entry to the menu. Title is an
|
||||
argument that is parsed to generate a string that can be used as
|
||||
the title. The sourcecode for this entry is passed in SOURCECODE.
|
||||
|
|
32
tests/grub_script_while1.in
Normal file
32
tests/grub_script_while1.in
Normal file
|
@ -0,0 +1,32 @@
|
|||
#! @builddir@/grub-shell-tester
|
||||
|
||||
echo one
|
||||
foo=""
|
||||
while test "$foo" != "1111"; do foo="${foo}1"; echo "$foo"; done
|
||||
|
||||
echo two
|
||||
foo=""
|
||||
while test "$foo" != "aaaa"
|
||||
do
|
||||
foo="${foo}a"
|
||||
echo $foo
|
||||
done
|
||||
|
||||
foo=""
|
||||
until test "$foo" = "1111"; do foo="${foo}1"; echo $foo; done
|
||||
foo=""
|
||||
until test "$foo" = "aaaa"
|
||||
do
|
||||
foo="${foo}a"
|
||||
echo $foo
|
||||
done
|
||||
|
||||
# check "$?" in condition gets its value from while body commands
|
||||
foo=""
|
||||
false
|
||||
while test "$?" != "0"
|
||||
do
|
||||
echo $foo
|
||||
foo="${foo}1"
|
||||
test "$foo" = "111111"
|
||||
done
|
|
@ -87,6 +87,12 @@ grub_script_execute_cmdfor (struct grub_script_cmd *cmd __attribute__ ((unused))
|
|||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_script_execute_cmdwhile (struct grub_script_cmd *cmd __attribute__ ((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused)))
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue