2006-05-20 Marco Gerards <marco@gnu.org>

* normal/lexer.c (grub_script_yylex): Don't filter out newlines.

	* normal/parser.y (commandblock): Defined as <cmd>.  A subroutine
	for `menuentry'.
	(script): Accept leading newlines.
	(newlines): New rule to describe 0 or more newlines.
	(commands): Accept `command' with trailing newline.  Fixed the
	order in which arguments were passed to `grub_script_add_cmd'.
	Accept commands separated by newlines.
	(function): Changed to accept newlines.
	(menuentry) Rewritten.

	* normal/script.c (grub_script_create_cmdmenu): Add new entries in
	front of the list, instead of to the end.
This commit is contained in:
marco_g 2006-05-20 11:10:22 +00:00
parent 577b405042
commit 7dc4f874a6
3 changed files with 51 additions and 30 deletions

View file

@ -1,7 +1,7 @@
/* lexer.c - The scripting lexer. */ /* lexer.c - The scripting lexer. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2005 Free Software Foundation, Inc. * Copyright (C) 2005, 2006 Free Software Foundation, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -147,7 +147,7 @@ grub_script_yylex (YYSTYPE *yylval, struct grub_parser_param *parsestate)
while (r == -1) while (r == -1)
{ {
r = grub_script_yylex2 (yylval, parsestate); r = grub_script_yylex2 (yylval, parsestate);
if (r == ' ' || r == '\n') if (r == ' ')
r = -1; r = -1;
} }
return r; return r;

View file

@ -1,7 +1,7 @@
/* parser.y - The scripting parser. */ /* parser.y - The scripting parser. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2005 Free Software Foundation, Inc. * Copyright (C) 2005, 2006 Free Software Foundation, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -44,7 +44,7 @@
%token GRUB_PARSER_TOKEN_FI "fi" %token GRUB_PARSER_TOKEN_FI "fi"
%token GRUB_PARSER_TOKEN_NAME %token GRUB_PARSER_TOKEN_NAME
%token GRUB_PARSER_TOKEN_VAR %token GRUB_PARSER_TOKEN_VAR
%type <cmd> script grubcmd command commands menuentry if %type <cmd> script grubcmd command commands commandblock menuentry if
%type <arglist> arguments; %type <arglist> arguments;
%type <arg> argument; %type <arg> argument;
%type <string> "if" "while" "function" "else" "then" "fi" %type <string> "if" "while" "function" "else" "then" "fi"
@ -56,12 +56,16 @@
%% %%
/* It should be possible to do this in a clean way... */ /* It should be possible to do this in a clean way... */
script: { state->err = 0} commands script: { state->err = 0} newlines commands
{ {
state->parsed = $2; state->parsed = $3;
} }
; ;
newlines: /* Empty */
| newlines '\n'
;
/* Some tokens are both used as token or as plain text. XXX: Add all /* Some tokens are both used as token or as plain text. XXX: Add all
tokens without causing conflicts. */ tokens without causing conflicts. */
text: GRUB_PARSER_TOKEN_NAME text: GRUB_PARSER_TOKEN_NAME
@ -128,15 +132,25 @@ command: grubcmd { $$ = $1; }
; ;
/* A block of commands. */ /* A block of commands. */
commands: command commands: command '\n'
{
$$ = grub_script_add_cmd (state, 0, $1);
}
| command
{ {
$$ = grub_script_add_cmd (state, 0, $1); $$ = grub_script_add_cmd (state, 0, $1);
} }
| command ';' commands | command ';' commands
{ {
struct grub_script_cmdblock *cmd; struct grub_script_cmdblock *cmd;
cmd = (struct grub_script_cmdblock *) $1; cmd = (struct grub_script_cmdblock *) $3;
$$ = grub_script_add_cmd (state, cmd, $3); $$ = grub_script_add_cmd (state, cmd, $1);
}
| command '\n' newlines commands
{
struct grub_script_cmdblock *cmd;
cmd = (struct grub_script_cmdblock *) $4;
$$ = grub_script_add_cmd (state, cmd, $1);
} }
| error | error
{ {
@ -146,17 +160,22 @@ commands: command
} }
; ;
/* A function. Carefully save the memory that is allocated. */ /* A function. Carefully save the memory that is allocated. Don't
change any stuff because it might seem like a fun thing to do!
Special care was take to make sure the mid-rule actions are
executed on the right moment. So the `commands' rule should be
recognised after executing the `grub_script_mem_record; and before
`grub_script_mem_record_stop'. */
function: "function" GRUB_PARSER_TOKEN_NAME function: "function" GRUB_PARSER_TOKEN_NAME
{ {
grub_script_lexer_ref (state->lexerstate); grub_script_lexer_ref (state->lexerstate);
} '{' } newlines '{'
{ {
/* The first part of the function was recognised. /* The first part of the function was recognised.
Now start recording the memory usage to store Now start recording the memory usage to store
this function. */ this function. */
state->func_mem = grub_script_mem_record (state); state->func_mem = grub_script_mem_record (state);
} commands '}' } newlines commands '}'
{ {
struct grub_script *script; struct grub_script *script;
@ -164,29 +183,33 @@ function: "function" GRUB_PARSER_TOKEN_NAME
was recorded. */ was recorded. */
state->func_mem = grub_script_mem_record_stop (state, state->func_mem = grub_script_mem_record_stop (state,
state->func_mem); state->func_mem);
script = grub_script_create ($6, state->func_mem); script = grub_script_create ($8, state->func_mem);
if (script) if (script)
grub_script_function_create ($2, script); grub_script_function_create ($2, script);
grub_script_lexer_deref (state->lexerstate); grub_script_lexer_deref (state->lexerstate);
} }
; ;
/* A menu entry. Carefully save the memory that is allocated. */ /* Carefully designed, together with `menuentry' so everything happens
menuentry: "menuentry" argument just in the expected order. */
{ commandblock: '{'
{
grub_script_lexer_ref (state->lexerstate); grub_script_lexer_ref (state->lexerstate);
} '{' grub_script_lexer_record_start (state->lexerstate);
{ }
/* Record sourcecode of the menu entry. It can be newlines commands '}'
parsed multiple times if it is part of a {
loop. */ grub_script_lexer_deref (state->lexerstate);
grub_script_lexer_record_start (state->lexerstate); $$ = $4;
} commands '}' }
;
/* A menu entry. Carefully save the memory that is allocated. */
menuentry: "menuentry" argument newlines commandblock
{ {
char *menu_entry; char *menu_entry;
menu_entry = grub_script_lexer_record_stop (state->lexerstate); menu_entry = grub_script_lexer_record_stop (state->lexerstate);
$$ = grub_script_create_cmdmenu (state, $2, menu_entry, 0); $$ = grub_script_create_cmdmenu (state, $2, menu_entry, 0);
grub_script_lexer_deref (state->lexerstate);
} }
; ;

View file

@ -1,7 +1,7 @@
/* script.c -- Functions to create an in memory description of the script. */ /* script.c -- Functions to create an in memory description of the script. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2005 Free Software Foundation, Inc. * Copyright (C) 2005, 2006 Free Software Foundation, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -253,16 +253,14 @@ grub_script_add_cmd (struct grub_parser_param *state,
cmdblock->cmd.exec = grub_script_execute_cmdblock; cmdblock->cmd.exec = grub_script_execute_cmdblock;
cmdblock->cmd.next = 0; cmdblock->cmd.next = 0;
cmdblock->cmdlist = cmd; cmdblock->cmdlist = cmd;
cmd->next = 0;
} }
else else
{ {
struct grub_script_cmd **last; cmd->next = cmdblock->cmdlist;
for (last = &cmdblock->cmdlist; *last; last = &(*last)->next); cmdblock->cmdlist = cmd;
*last = cmd;
} }
cmd->next = 0;
return (struct grub_script_cmd *) cmdblock; return (struct grub_script_cmd *) cmdblock;
} }