/* parser.y - The scripting parser. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
%{
#include <grub/script_sh.h>
#define YYMALLOC grub_malloc
#define YYLTYPE_IS_TRIVIAL 0
#define YYENABLE_NLS 0
#include "grub_script.tab.h"
%}
%union {
struct grub_script_cmd *cmd;
struct grub_script_arglist *arglist;
struct grub_script_arg *arg;
char *string;
struct {
unsigned offset;
struct grub_script_mem *memory;
struct grub_script *scripts;
};
}
%%
/* It should be possible to do this in a clean way... */
;
{
$$ = 0;
}
{
}
| error
{
$$ = 0;
}
;
| "\n"
;
| delimiters1 "\n"
;
;
| function { $$ = 0; }
;
| word { $$ = $1; }
;
/*
Block parameter is passed to commands in two forms: as unparsed
string and as pre-parsed grub_script object. Passing as grub_script
object makes memory management difficult, because:
(1) Command may want to keep a reference to grub_script objects for
later use, so script framework may not free the grub_script
object after command completes.
(2) Command may get called multiple times with same grub_script
object under loops, so we should not let command implementation
to free the grub_script object.
To solve above problems, we rely on reference counting for
grub_script objects. Commands that want to keep the grub_script
object must take a reference to it.
Other complexity comes with arbitrary nesting of grub_script
objects: a grub_script object may have commands with several block
parameters, and each block parameter may further contain multiple
block parameters nested. We use temporary variable, state->scripts
to collect nested child scripts (that are linked by siblings and
children members), and will build grub_scripts tree from bottom.
*/
{
/* save currently known scripts. */
}
{
char *p;
struct grub_script_mem *memory;
else {
/* attach nested scripts to $$->script as children */
/* restore old scripts; append $$->script to siblings. */
if (s) {
while (s->next_siblings)
s = s->next_siblings;
s->next_siblings = $$->script;
}
}
}
;
| block { $$ = $1; }
;
| arguments1 { $$ = $1; }
;
{
if ($1 && $2)
{
$2->argcount = 0;
}
$$ = $1;
}
;
{
struct grub_script_arglist *x = $2;
if ($3)
if ($1 && x) {
$1->next = x;
x->argcount = 0;
}
}
;
/* A single command. */
| ifcmd { $$ = $1; }
| forcmd { $$ = $1; }
| whilecmd { $$ = $1; }
| untilcmd { $$ = $1; }
;
/* A list of commands. */
{
}
{
}
;
{
}
{
struct grub_script *script;
if (! script)
else {
}
}
;
{
}
ifclause "fi"
{
$$ = $3;
}
;
{
}
{
}
{
}
;
{
}
{
}
;
{
}
{
}
;
{
}
{
}
;