* Scripting framework
@ 2005-10-23 14:05 Marco Gerards
2005-10-27 9:51 ` Vladimir Serbinenko
0 siblings, 1 reply; 4+ messages in thread
From: Marco Gerards @ 2005-10-23 14:05 UTC (permalink / raw)
To: grub-devel
Hi,
In the last emails we discussed scripting support. Because it was
quite hard to explain everything and it was quite easy to implement
the basic framework we can use to implement scripting I just did some
hacking.
It is not complete scripting support. All it is is just a structure
to work from. It also shows how we can implement menu entries and
functions (I have written function support, which is just a conceptual
one liner now :-)).
Now I have to learn for some exams (like I had to do this afternoon
when I was working on this code :-/). I will clean all this up next
week and make sure it can be used by GRUB, instead of just a few
separate files.
Vladimir, there is still enough to do, don't be worried. I will stop
right after the basics work (just see how little amount of code it is
so far). I am not interested in writing complete scripting support
now.
To parse a script in `char *cmdline' you can use the following
commands using this code:
set_lex (cmdline);
yyparse ();
grub_execute_cmd (grub_script_parsed);
grub_script_parsed is a global at the moment, but I will make that
cleaner. It contains the complete parsed scripted after running
yyparse. grub_execute_cmd executes the script. Have a look at that
function, it is easy to understand how it works and how to extend it.
The same thing can be used for menu entries and functions, just use
`struct grub_script_cmd *' to store a function. And the function can
be executed by grub_execute_cmd.
If you have any questions or comments please tell me. You just have
to know that the code is not yet finished, so no need to proof read
it; it is full of bugs and ugliness.
Thanks,
Marco
/* scripting.h */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005 Free Software Foundation, Inc.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
struct grub_script_arglist
{
struct grub_script_arglist *next;
char *arg;
};
typedef enum
{
GRUB_CMDTYPE_CMDLINE,
GRUB_CMDTYPE_BLOCK,
GRUB_CMDTYPE_IF
} grub_script_command_type_t;
struct grub_script_cmd
{
grub_script_command_type_t cmdtype;
struct grub_script_cmd *next;
};
struct grub_script_cmdline
{
struct grub_script_cmd cmd;
struct grub_script_arglist *arglist;
char *cmdname;
};
struct grub_script_cmdblock
{
struct grub_script_cmd cmd;
struct grub_script_cmd *cmdlist;
};
struct grub_script_arglist *grub_script_create_arglist (void);
struct grub_script_arglist *grub_script_add_arglist (struct grub_script_arglist *list, char *arg);
struct grub_script_cmd *grub_script_create_cmdline (char *cmdname, struct grub_script_arglist *arglist);
struct grub_script_cmd *grub_script_create_cmdblock (void);
struct grub_script_cmd *grub_script_add_cmd (struct grub_script_cmdblock *cmdblock, struct grub_script_cmd *cmd);
extern struct grub_script_cmd *grub_script_parsed;
void grub_execute_cmd (struct grub_script_cmd *cmd);
--------------------------------------------------------------------------------
/* lexer.c - The scripting lexer. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005 Free Software Foundation, Inc.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <grub/parser.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include "parser.tab.h"
static grub_parser_state_t state;
static char *script;
static int
check_varstate (grub_parser_state_t state)
{
return (state == GRUB_PARSER_STATE_VARNAME
|| state == GRUB_PARSER_STATE_VARNAME2
|| state == GRUB_PARSER_STATE_QVARNAME
|| state == GRUB_PARSER_STATE_QVARNAME2);
}
void
set_lex (char *s)
{
state = GRUB_PARSER_STATE_TEXT;
script = s;
}
int
yylex (void)
{
char *buffer;
char *bp;
char use;
grub_parser_state_t newstate;
buffer = (char *) grub_malloc (4096);
bp = buffer;
if (!*script)
return 0;
while (*script)
{
newstate = grub_parser_cmdline_state (state, *script, &use);
if (check_varstate (state) && ! check_varstate (newstate))
break;
if (newstate == GRUB_PARSER_STATE_TEXT
&& state != GRUB_PARSER_STATE_ESC && use == ' ')
{
/* Don't add more than one space if multiple spaces are
used. */
if (bp != buffer && *(bp - 1))
{
script++;
break;
}
}
else if (use)
*(bp++) = use;
script++;
state = newstate;
}
*bp = '\0';
yylval.string = buffer;
if (check_varstate (state))
return GRUB_PARSER_TOKEN_VAR;
else if (! grub_strcmp (buffer, "while"))
return GRUB_PARSER_TOKEN_WHILE;
else if (! grub_strcmp (buffer, "if"))
return GRUB_PARSER_TOKEN_IF;
else if (! grub_strcmp (buffer, "function"))
return GRUB_PARSER_TOKEN_FUNCTION;
else if (! grub_strcmp (buffer, "{"))
return GRUB_PARSER_TOKEN_OBRACE;
else if (! grub_strcmp (buffer, "}"))
return GRUB_PARSER_TOKEN_CBRACE;
else
return GRUB_PARSER_TOKEN_NAME;
}
void
yyerror (char const *err)
{
grub_printf (err);
}
--------------------------------------------------------------------------------
/* parser.y - The scripting parser. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005 Free Software Foundation, Inc.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
%{
#include <grub/scripting.h>
%}
%union {
struct grub_script_cmd *cmd;
struct grub_script_arglist *arglist;
char *string;
}
%token GRUB_PARSER_TOKEN_IF "if"
%token GRUB_PARSER_TOKEN_WHILE "while"
%token GRUB_PARSER_TOKEN_FUNCTION "function"
%token GRUB_PARSER_TOKEN_OBRACE "{"
%token GRUB_PARSER_TOKEN_CBRACE "}"
%token GRUB_PARSER_TOKEN_NAME
%token GRUB_PARSER_TOKEN_VAR
%type <cmd> script grubcmd commands
%type <arglist> arguments;
%type <string> text "if" "while" GRUB_PARSER_TOKEN_NAME
%%
/* It should be possible to do this in a clean way... */
script: commands { grub_script_parsed = $1; }
| function
text: GRUB_PARSER_TOKEN_NAME { $$ = $1; }
| "if" { $$ = $1; }
| "while" { $$ = $1; }
;
arguments: /* Empty */ { $$ = grub_script_create_arglist (); }
| arguments text { $$ = grub_script_add_arglist ($1, $2); }
;
grubcmd: GRUB_PARSER_TOKEN_NAME arguments { $$ = grub_script_create_cmdline ($1, $2); }
;
commands: /* Empty */ { $$ = grub_script_create_cmdblock (); }
| commands grubcmd { $$ = grub_script_add_cmd ((struct grub_script_cmdblock *) $1, $2); }
;
function: "function" GRUB_PARSER_TOKEN_NAME "{" commands "}" { grub_script_create_function ($2, $4); }
/* | commands "if" { $$ = grub_script_add_cmd ((struct cmd_cmdblock *) $1, $2); }*/
%%
--------------------------------------------------------------------------------
/* script.c */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005 Free Software Foundation, Inc.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <grub/misc.h>
#include <grub/scripting.h>
#include <grub/parser.h>
#include <grub/mm.h>
struct grub_script_arglist *
grub_script_create_arglist (void)
{
struct grub_script_arglist *link;
link = (struct grub_script_arglist *) grub_malloc (sizeof (*link));
link->next = 0;
link->arg = 0;
return link;
}
struct grub_script_arglist *
grub_script_add_arglist (struct grub_script_arglist *list, char *arg)
{
struct grub_script_arglist *link;
struct grub_script_arglist *ll;
/* XXX: Perhaps we can just create a character array with '\0'
separators right away. */
link = (struct grub_script_arglist *) grub_malloc (sizeof (*link));
link->next = 0;
link->arg = arg;
/* Look up the last link in the chain. */
for (ll = list; list->next; list = list->next);
ll->next = link;
return list;
}
struct grub_script_cmd *
grub_script_create_cmdline (char *cmdname, struct grub_script_arglist *arglist)
{
struct grub_script_cmdline *cmd;
cmd = grub_malloc (sizeof (*cmd));
cmd->cmd.cmdtype = GRUB_CMDTYPE_CMDLINE;
cmd->cmd.next = 0;
cmd->arglist = arglist;
cmd->cmdname = cmdname;
return (struct grub_script_cmd *) cmd;
}
struct grub_script_cmd *
grub_script_create_cmdblock (void)
{
struct grub_script_cmdblock *cmdblock;
cmdblock = (struct grub_script_cmdblock *) grub_malloc (sizeof (*cmdblock));
cmdblock->cmd.cmdtype = GRUB_CMDTYPE_BLOCK;
cmdblock->cmd.next = 0;
cmdblock->cmdlist = 0;
return (struct grub_script_cmd *) cmdblock;
}
struct grub_script_cmd *
grub_script_add_cmd (struct grub_script_cmdblock *cmdblock, struct grub_script_cmd *cmd)
{
struct grub_script_cmd **last;
for (last = &cmdblock->cmdlist; *last; last = &(*last)->next);
*last = cmd;
cmd->next = 0;
return (struct grub_script_cmd *) cmdblock;
}
void
grub_script_create_function (char *functionname, struct grub_script_cmd *cmd)
{
/* Register the function FUNCTIONNAME. After that it can be called
using a standard GRUB command. */
grub_printf ("Register function `%s'\n", functionname);
}
--------------------------------------------------------------------------------
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005 Free Software Foundation, Inc.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <grub/misc.h>
#include <grub/scripting.h>
/* Execute GRUB scripts. */
struct grub_script_cmd *grub_script_parsed = 0;
static void
grub_execute_cmdline (struct grub_script_cmdline *cmdline)
{
struct grub_script_arglist *arglist;
int i = 1;
grub_printf ("Command name: `%s'\n", cmdline->cmdname);
for (arglist = cmdline->arglist->next; arglist; arglist = arglist->next)
grub_printf ("Argument %d) %s\n", i++, arglist->arg);
}
static void
grub_execute_cmdblock (struct grub_script_cmdblock *cmdblock)
{
struct grub_script_cmd *cmd;
grub_printf ("Executing block of commands\n");
/* Loop over every command and execute it. */
for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next)
grub_execute_cmd (cmd);
}
/* static grub_execute_cmdif (struct grub_script_cmdline *cmd) */
/* { */
/* } */
void
grub_execute_cmd (struct grub_script_cmd *cmd)
{
if (cmd == 0)
{
/* XXX */
grub_printf ("No script!\n");
return;
}
grub_printf ("Execute: %d\n", cmd->cmdtype);
switch (cmd->cmdtype)
{
case GRUB_CMDTYPE_CMDLINE:
grub_execute_cmdline ((struct grub_script_cmdline *) cmd);
break;
case GRUB_CMDTYPE_BLOCK:
grub_execute_cmdblock ((struct grub_script_cmdblock *) cmd);
break;
case GRUB_CMDTYPE_IF:
/* grub_execute_cmdif ((struct grub_script_cmdif *) cmd); */
break;
}
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Scripting framework
2005-10-23 14:05 Scripting framework Marco Gerards
@ 2005-10-27 9:51 ` Vladimir Serbinenko
2005-10-27 13:25 ` Marco Gerards
0 siblings, 1 reply; 4+ messages in thread
From: Vladimir Serbinenko @ 2005-10-27 9:51 UTC (permalink / raw)
To: The development of GRUB 2
I wrote the scripting support.
The patch can be found under http://phcoder.hut1.ru/bash.patch
As in this version there is no arithmethic support I added commands true5 and false 5 for testing
They return five times true and then false (true5) or inverse (false5)
TODO:
1) Positional arguments like $1, $2, ... and $*/$@
2) Arithmethic module for commands like ((2+3*5))
3) logical module for commands like [[ -f /boot/vmlinuz ]]
4) break, continue and return commands
5) menu parameters like:
menu --default "Linux" { ... }
Can anybody propose the way to generate menu entries from loop?
What about
menu --prepend var=val --prepend val=var ...
Then compiler will expand var=val and put it to the begin of menu
6) Regexp recognizer for case command
In difference with bash ( and ) are not the word separators. So you have to put spaces around them in case command
e.g.
case $x in ( 123 ) ....;; ... esac
and not
case $x in (123) ....;; ... esac
The same with functions.
e.g. hello ( ) { .. }
or
hello () { .. }
and not
hello() { .. }
Command select is not done. Menu should be enough.
Expansions and arrays are NOT the part of scripting but of split_cmdline and environment and is not made yet
Unfortunately I have now no more time. So I send this letter as is. More information will be available in my next letter and on the site.
Vladimir 'phcoder' Serbinenko
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Scripting framework
2005-10-27 9:51 ` Vladimir Serbinenko
@ 2005-10-27 13:25 ` Marco Gerards
2005-10-27 15:09 ` Vladimir Serbinenko
0 siblings, 1 reply; 4+ messages in thread
From: Marco Gerards @ 2005-10-27 13:25 UTC (permalink / raw)
To: The development of GRUB 2
Vladimir Serbinenko <phcoder@gmail.com> writes:
> I wrote the scripting support.
> The patch can be found under http://phcoder.hut1.ru/bash.patch
This URL does not work for me.
--
Marco
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Scripting framework
2005-10-27 13:25 ` Marco Gerards
@ 2005-10-27 15:09 ` Vladimir Serbinenko
0 siblings, 0 replies; 4+ messages in thread
From: Vladimir Serbinenko @ 2005-10-27 15:09 UTC (permalink / raw)
To: The development of GRUB 2
>>I wrote the scripting support.
>>The patch can be found under http://phcoder.hut1.ru/bash.patch
>>
>>
>
>This URL does not work for me.
>
>
>
Could you try to enter the site (http://phcoder.hut1.ru/) then click on
Scripting support->patch for scripting support. It seems that hoster
blocks if you try to access directly (I'm not sure)
Vladimir 'phcoder' Serbinenko
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2005-10-27 15:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-10-23 14:05 Scripting framework Marco Gerards
2005-10-27 9:51 ` Vladimir Serbinenko
2005-10-27 13:25 ` Marco Gerards
2005-10-27 15:09 ` Vladimir Serbinenko
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.