2006-01-17 Marco Gerards <marco@gnu.org>

* include/grub/normal.h: Include <grub/script.h>.
	(grub_command_list): Removed struct.
	(grub_command_list_t): Removed type.
	(grub_menu_entry): Remove members `num' and `command_list'.  Add
	members `commands' and `sourcecode'.
	* include/grub/script.h: Add inclusion guards.
	(grub_script_cmd_menuentry): New struct.
	(grub_script_execute_menuentry): New prototype.
	(grub_script_lexer_record_start): Likewise.
	(grub_script_lexer_record_stop): Likewise.
	* normal/execute.c (grub_script_execute_menuentry): New function.
	* normal/lexer.c (record, recording, recordpos, recordlen): New
	variables.
	(grub_script_lexer_record_start): New function.
	(grub_script_lexer_record_stop): Likewise.
	(recordchar): Likewise.
	(nextchar): Likewise.
	(grub_script_yylex): Use `nextchar' to fetch new characters.  Use
	2048 as the buffer size.  Add the tokens `menuentry' and `@'.
	* normal/main.c: Include <grub/parser.h> and <grub/script.h>
	(current_menu): New variable.
	(free_menu): Mainly rewritten.
	(grub_normal_menu_addentry): New function.
	(read_config_file): Rewritten.
	* normal/menu.c (run_menu_entry): Mainly rewritten.
	* normal/menu_entry.c (make_screen): Rewritten te code to insert
	the menu entry.
	(run): Mainly rewritten.
	* normal/parser.y (menu_entry): New variable.
	(GRUB_PARSER_TOKEN_MENUENTRY): New token.
	(menuentry): New rule.
	(command): Add `menuentry'.
	(if_statement): Allow additional returns before `fi'.
	* normal/script.c (grub_script_create_cmdmenu): New function.
This commit is contained in:
marco_g 2006-01-17 09:50:47 +00:00
parent 144f1f986f
commit 77c4a3939d
10 changed files with 378 additions and 221 deletions

View file

@ -1,3 +1,40 @@
2006-01-17 Marco Gerards <marco@gnu.org>
* include/grub/normal.h: Include <grub/script.h>.
(grub_command_list): Removed struct.
(grub_command_list_t): Removed type.
(grub_menu_entry): Remove members `num' and `command_list'. Add
members `commands' and `sourcecode'.
* include/grub/script.h: Add inclusion guards.
(grub_script_cmd_menuentry): New struct.
(grub_script_execute_menuentry): New prototype.
(grub_script_lexer_record_start): Likewise.
(grub_script_lexer_record_stop): Likewise.
* normal/execute.c (grub_script_execute_menuentry): New function.
* normal/lexer.c (record, recording, recordpos, recordlen): New
variables.
(grub_script_lexer_record_start): New function.
(grub_script_lexer_record_stop): Likewise.
(recordchar): Likewise.
(nextchar): Likewise.
(grub_script_yylex): Use `nextchar' to fetch new characters. Use
2048 as the buffer size. Add the tokens `menuentry' and `@'.
* normal/main.c: Include <grub/parser.h> and <grub/script.h>
(current_menu): New variable.
(free_menu): Mainly rewritten.
(grub_normal_menu_addentry): New function.
(read_config_file): Rewritten.
* normal/menu.c (run_menu_entry): Mainly rewritten.
* normal/menu_entry.c (make_screen): Rewritten te code to insert
the menu entry.
(run): Mainly rewritten.
* normal/parser.y (menu_entry): New variable.
(GRUB_PARSER_TOKEN_MENUENTRY): New token.
(menuentry): New rule.
(command): Add `menuentry'.
(if_statement): Allow additional returns before `fi'.
* normal/script.c (grub_script_create_cmdmenu): New function.
2006-01-03 Marco Gerards <marco@gnu.org>
* INSTALL: GNU Bison is required.

View file

@ -25,6 +25,7 @@
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/arg.h>
#include <grub/script.h>
/* The maximum size of a command-line. */
#define GRUB_MAX_CMDLINE 1600
@ -84,28 +85,17 @@ struct grub_command
};
typedef struct grub_command *grub_command_t;
/* The command list. */
struct grub_command_list
{
/* The string of a command. */
char *command;
/* The next element. */
struct grub_command_list *next;
};
typedef struct grub_command_list *grub_command_list_t;
/* The menu entry. */
struct grub_menu_entry
{
/* The title name. */
const char *title;
/* The number of commands. */
int num;
/* The commands associated with this menu entry. */
struct grub_script *commands;
/* The list of commands. */
grub_command_list_t command_list;
/* The sourcecode of the menu entry, used by the editor. */
const char *sourcecode;
/* The next element. */
struct grub_menu_entry *next;
@ -192,6 +182,9 @@ void grub_context_pop_menu (void);
char *grub_normal_do_completion (char *buf, int *restore,
void (*hook) (const char *item, grub_completion_type_t type, int count));
grub_err_t grub_normal_print_device_info (const char *name);
grub_err_t grub_normal_menu_addentry (const char *title,
struct grub_script *script,
const char *sourcecode);
#ifdef GRUB_UTIL
void grub_normal_init (void);

View file

@ -17,6 +17,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef GRUB_SCRIPT_HEADER
#define GRUB_SCRIPT_HEADER 1
#include <grub/types.h>
#include <grub/err.h>
@ -104,6 +108,21 @@ struct grub_script_cmdif
struct grub_script_cmd *false;
};
/* A menu entry generate statement. */
struct grub_script_cmd_menuentry
{
struct grub_script_cmd cmd;
/* The title of the menu entry. */
struct grub_script_arg *title;
/* The sourcecode the entry will be generated from. */
const char *sourcecode;
/* Options. XXX: Not used yet. */
int options;
};
struct grub_script_arglist *
grub_script_create_arglist (void);
@ -120,6 +139,12 @@ struct grub_script_cmd *
grub_script_create_cmdif (struct grub_script_cmd *bool,
struct grub_script_cmd *true,
struct grub_script_cmd *false);
struct grub_script_cmd *
grub_script_create_cmdmenu (struct grub_script_arg *title,
char *sourcecode,
int options);
struct grub_script_cmd *
grub_script_add_cmd (struct grub_script_cmdblock *cmdblock,
struct grub_script_cmd *cmd);
@ -136,6 +161,8 @@ struct grub_script *grub_script_create (struct grub_script_cmd *cmd,
void grub_script_lexer_init (char *s, grub_err_t (*getline) (char **));
void grub_script_lexer_ref (void);
void grub_script_lexer_deref (void);
void grub_script_lexer_record_start (void);
char *grub_script_lexer_record_stop (void);
/* Functions to track allocated memory. */
void *grub_script_malloc (grub_size_t size);
@ -151,6 +178,7 @@ void grub_script_yyerror (char const *err);
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_menuentry (struct grub_script_cmd *cmd);
/* Execute any GRUB pre-parsed command or script. */
grub_err_t grub_script_execute (struct grub_script *script);
@ -187,3 +215,5 @@ grub_script_function_t grub_script_function_find (char *functionname);
int grub_script_function_iterate (int (*iterate) (grub_script_function_t));
int grub_script_function_call (grub_script_function_t func,
int argc, char **args);
#endif /* ! GRUB_SCRIPT_HEADER */

View file

@ -191,6 +191,36 @@ grub_script_execute_cmdif (struct grub_script_cmd *cmd)
return grub_script_execute_cmd (cmdif->false);
}
/* Execute the menu entry generate statement. */
grub_err_t
grub_script_execute_menuentry (struct grub_script_cmd *cmd)
{
struct grub_script_cmd_menuentry *cmd_menuentry;
char *title;
struct grub_script *script;
cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;
/* The title can contain variables, parse them and generate a string
from it. */
title = grub_script_execute_argument_to_string (cmd_menuentry->title);
if (! title)
return grub_errno;
/* Parse the menu entry *again*. */
script = grub_script_parse ((char *) cmd_menuentry->sourcecode, 0);
if (! script)
{
grub_free (title);
return grub_errno;
}
/* XXX: When this fails, the memory should be free'ed? */
return grub_normal_menu_addentry (title, script,
cmd_menuentry->sourcecode);
}
/* Execute any GRUB pre-parsed command or script. */

View file

@ -54,6 +54,11 @@ static int grub_script_lexer_refs = 0;
static char *script;
static char *newscript;
static int record = 0;
static char *recording = 0;
static int recordpos = 0;
static int recordlen = 0;
/* XXX: The lexer is not reentrant. */
void
grub_script_lexer_init (char *s, grub_err_t (*getline) (char **))
@ -78,6 +83,63 @@ grub_script_lexer_deref (void)
grub_script_lexer_refs--;
}
/* Start recording all characters passing through the lexer. */
void
grub_script_lexer_record_start (void)
{
record = 1;
recordlen = 100;
recording = grub_malloc (recordlen);
recordpos = 0;
}
char *
grub_script_lexer_record_stop (void)
{
record = 0;
/* Delete the last character, it is a `}'. */
if (recordpos > 0)
{
if (recording[--recordpos] != '}')
{
grub_printf ("Internal error while parsing menu entry");
for (;;); /* XXX */
}
recording[recordpos] = '\0';
}
return recording;
}
/* When recording is enabled, record the character C as the next item
in the character stream. */
static void
recordchar (char c)
{
if (recordpos == recordlen)
{
char *old = recording;
recordlen += 100;
recording = grub_realloc (recording, recordlen);
if (! recording)
{
grub_free (old);
record = 0;
}
}
recording[recordpos++] = c;
}
/* Fetch the next character for the lexer. */
static void
nextchar (void)
{
if (record)
recordchar (*script);
script++;
}
int
grub_script_yylex (void)
{
@ -96,13 +158,17 @@ grub_script_yylex (void)
|| grub_script_lexer_state == GRUB_PARSER_STATE_ESC)
&& grub_script_lexer_getline)
{
while (! grub_strlen (script))
while (!script || ! grub_strlen (script))
{
grub_free (newscript);
newscript = 0;
grub_script_lexer_getline (&newscript);
script = newscript;
if (! script)
return 0;
}
grub_dprintf ("scripting", "token=`\\n'\n");
recordchar ('\n');
if (grub_script_lexer_state != GRUB_PARSER_STATE_ESC)
return '\n';
}
@ -139,7 +205,7 @@ grub_script_yylex (void)
return ' ';
}
grub_script_lexer_state = newstate;
script++;
nextchar ();
}
grub_dprintf ("scripting", "token=` '\n");
return ' ';
@ -147,13 +213,18 @@ grub_script_yylex (void)
case '}':
case ';':
case '\n':
{
char c;
grub_dprintf ("scripting", "token=`%c'\n", *script);
return *(script++);
c = *script;;
nextchar ();
return c;
}
}
}
/* XXX: Use a better size. */
buffer = grub_script_malloc (2096);
buffer = grub_script_malloc (2048);
if (! buffer)
return 0;
@ -194,7 +265,7 @@ grub_script_yylex (void)
*(bp++) = use;
grub_script_lexer_state = newstate;
script++;
nextchar ();
}
/* A string of text was read in. */
@ -209,6 +280,10 @@ grub_script_yylex (void)
return GRUB_PARSER_TOKEN_IF;
else if (! grub_strcmp (buffer, "function"))
return GRUB_PARSER_TOKEN_FUNCTION;
else if (! grub_strcmp (buffer, "menuentry"))
return GRUB_PARSER_TOKEN_MENUENTRY;
else if (! grub_strcmp (buffer, "@"))
return GRUB_PARSER_TOKEN_MENUENTRY;
else if (! grub_strcmp (buffer, "else"))
return GRUB_PARSER_TOKEN_ELSE;
else if (! grub_strcmp (buffer, "then"))
@ -240,14 +315,14 @@ grub_script_yylex (void)
{
if (grub_script_lexer_state == GRUB_PARSER_STATE_VARNAME2
|| grub_script_lexer_state == GRUB_PARSER_STATE_QVARNAME2)
script++;
nextchar ();
grub_script_lexer_state = newstate;
break;
}
if (use)
*(bp++) = use;
script++;
nextchar ();
grub_script_lexer_state = newstate;
}

View file

@ -27,11 +27,16 @@
#include <grub/mm.h>
#include <grub/term.h>
#include <grub/env.h>
#include <grub/parser.h>
#include <grub/script.h>
grub_jmp_buf grub_exit_env;
static grub_fs_module_list_t fs_module_list = 0;
/* The menu to which the new entries are added by the parser. */
static grub_menu_t current_menu = 0;
#define GRUB_DEFAULT_HISTORY_SIZE 50
/* Read a line from the file FILE. */
@ -110,188 +115,118 @@ free_menu (grub_menu_t menu)
while (entry)
{
grub_menu_entry_t next_entry = entry->next;
grub_command_list_t cmd = entry->command_list;
while (cmd)
{
grub_command_list_t next_cmd = cmd->next;
grub_free ((void *) cmd->command);
cmd = next_cmd;
}
grub_script_free (entry->commands);
grub_free ((void *) entry->title);
grub_free ((void *) entry->sourcecode);
entry = next_entry;
}
grub_free (menu);
}
/* Read the config file CONFIG and return a menu. If no entry is present,
return NULL. */
grub_err_t
grub_normal_menu_addentry (const char *title, struct grub_script *script,
const char *sourcecode)
{
const char *menutitle;
grub_menu_entry_t *last = &current_menu->entry_list;
menutitle = grub_strdup (title);
if (! menutitle)
return grub_errno;
/* Add the menu entry at the end of the list. */
while (*last)
last = &(*last)->next;
*last = grub_malloc (sizeof (**last));
if (! *last)
{
grub_free ((void *) menutitle);
grub_free ((void *) sourcecode);
return grub_errno;
}
(*last)->commands = script;
(*last)->title = menutitle;
(*last)->next = 0;
(*last)->sourcecode = sourcecode;
return GRUB_ERR_NONE;
}
static grub_menu_t
read_config_file (const char *config)
{
grub_file_t file;
static char cmdline[GRUB_MAX_CMDLINE];
grub_menu_t menu;
grub_menu_entry_t *next_entry, cur_entry = 0;
grub_command_list_t *next_cmd, cur_cmd;
auto grub_err_t getline (char **line);
int currline = 0;
grub_err_t getline (char **line)
{
char cmdline[100];
currline++;
if (! get_line (file, cmdline, sizeof (cmdline)))
return 0;
*line = grub_strdup (cmdline);
if (! *line)
return grub_errno;
return GRUB_ERR_NONE;
}
char cmdline[100];
grub_menu_t newmenu;
newmenu = grub_malloc (sizeof (*newmenu));
if (! newmenu)
return 0;
newmenu->default_entry = 0;
newmenu->fallback_entry = -1;
newmenu->timeout = -1;
newmenu->size = 0;
newmenu->entry_list = 0;
current_menu = newmenu;
/* Try to open the config file. */
file = grub_file_open (config);
if (! file)
return 0;
/* Initialize the menu. */
menu = (grub_menu_t) grub_malloc (sizeof (*menu));
if (! menu)
{
grub_file_close (file);
return 0;
}
menu->default_entry = 0;
menu->fallback_entry = -1;
menu->timeout = -1;
menu->size = 0;
menu->entry_list = 0;
if (! grub_context_push_menu (menu))
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
free_menu (menu);
grub_file_close (file);
/* Wait until the user pushes any key so that the user
can see what happened. */
grub_printf ("\nPress any key to continue...");
(void) grub_getkey ();
return 0;
}
next_entry = &(menu->entry_list);
next_cmd = 0;
/* Read each line. */
while (get_line (file, cmdline, sizeof (cmdline)))
{
grub_command_t cmd;
struct grub_script *parsed_script;
cmd = grub_command_find (cmdline);
grub_errno = GRUB_ERR_NONE;
currline++;
if (cur_entry)
/* Execute the script, line for line. */
parsed_script = grub_script_parse (cmdline, getline);
if (! parsed_script)
{
if (! cmd || ! (cmd->flags & GRUB_COMMAND_FLAG_TITLE))
{
cur_cmd = (grub_command_list_t) grub_malloc (sizeof (*cur_cmd));
if (! cur_cmd)
goto fail;
cur_cmd->command = grub_strdup (cmdline);
if (! cur_cmd->command)
{
grub_free (cur_cmd);
goto fail;
}
cur_cmd->next = 0;
*next_cmd = cur_cmd;
next_cmd = &(cur_cmd->next);
cur_entry->num++;
continue;
}
}
if (! cmd)
{
grub_printf ("Unknown command `%s' is ignored.\n", cmdline);
continue;
}
if (cmd->flags & GRUB_COMMAND_FLAG_TITLE)
{
char *p;
cur_entry = (grub_menu_entry_t) grub_malloc (sizeof (*cur_entry));
if (! cur_entry)
goto fail;
p = grub_strchr (cmdline, ' ');
if (p)
cur_entry->title = grub_strdup (p);
else
cur_entry->title = grub_strdup ("");
if (! cur_entry->title)
{
grub_free (cur_entry);
goto fail;
}
cur_entry->num = 0;
cur_entry->command_list = 0;
cur_entry->next = 0;
*next_entry = cur_entry;
next_entry = &(cur_entry->next);
next_cmd = &(cur_entry->command_list);
menu->size++;
}
else
{
/* Run the command if possible. */
if (cmd->flags & GRUB_COMMAND_FLAG_MENU)
{
grub_command_execute (cmdline, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
}
else
{
grub_printf ("Invalid command `%s' is ignored.\n", cmdline);
continue;
}
}
}
fail:
/* Wait until the user pushes any key so that the user can
see what happened. */
grub_printf ("\nPress any key to continue...");
(void) grub_getkey ();
grub_file_close (file);
/* If no entry was found or any error occurred, return NULL. */
if (menu->size == 0 || grub_errno != GRUB_ERR_NONE)
{
grub_context_pop_menu ();
free_menu (menu);
return 0;
}
/* Check values of the default entry and the fallback one. */
if (menu->fallback_entry >= menu->size)
menu->fallback_entry = -1;
/* Execute the command(s). */
grub_script_execute (parsed_script);
if (menu->default_entry < 0 || menu->default_entry >= menu->size)
{
if (menu->fallback_entry < 0)
menu->default_entry = 0;
else
{
menu->default_entry = menu->fallback_entry;
menu->fallback_entry = -1;
}
/* The parsed script was executed, throw it away. */
grub_script_free (parsed_script);
}
return menu;
return newmenu;
grub_file_close (file);
return 0;
}
/* This starts the normal mode. */

View file

@ -347,17 +347,7 @@ run_menu (grub_menu_t menu, int nested)
static void
run_menu_entry (grub_menu_entry_t entry)
{
grub_command_list_t cl;
for (cl = entry->command_list; cl != 0; cl = cl->next)
{
if (cl->command[0] == '\0')
/* Ignore an empty command line. */
continue;
if (grub_command_execute (cl->command, 0) != 0)
break;
}
grub_script_execute (entry->commands);
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */

View file

@ -413,7 +413,6 @@ static struct screen *
make_screen (grub_menu_entry_t entry)
{
struct screen *screen;
grub_command_list_t cl;
/* Initialize the screen. */
screen = grub_malloc (sizeof (*screen));
@ -436,15 +435,7 @@ make_screen (grub_menu_entry_t entry)
if (! init_line (screen->lines))
goto fail;
/* Input the entry. */
for (cl = entry->command_list; cl; cl = cl->next)
{
if (! insert_string (screen, cl->command, 0))
goto fail;
if (! insert_string (screen, "\n", 0))
goto fail;
}
insert_string (screen, (char *) entry->sourcecode, 0);
/* Reset the cursor position. */
screen->column = 0;
@ -979,38 +970,61 @@ clear_completions (void)
static int
run (struct screen *screen)
{
int i;
struct grub_script *parsed_script = 0;
int currline = 0;
char *nextline;
grub_cls ();
grub_printf (" Booting a command list\n\n");
for (i = 0; i < screen->num_lines; i++)
auto grub_err_t editor_getline (char **line);
grub_err_t editor_getline (char **line)
{
struct line *linep = screen->lines + i;
struct line *linep = screen->lines + currline;
char *p;
if (currline > screen->num_lines)
{
*line = 0;
return 0;
}
/* Trim down space characters. */
for (p = linep->buf + linep->len - 1;
p >= linep->buf && grub_isspace (*p);
p--)
;
*++p = '\0';
linep->len = p - linep->buf;
linep->len = p - linep->buf;
for (p = linep->buf; grub_isspace (*p); p++)
;
if (*p == '\0')
/* Ignore an empty command line. */
continue;
if (grub_command_execute (p, 0) != 0)
break;
*line = p;
currline++;
return 0;
}
grub_cls ();
grub_printf (" Booting a command list\n\n");
/* Execute the script, line for line. */
while (currline < screen->num_lines - 1)
{
editor_getline (&nextline);
parsed_script = grub_script_parse (nextline, editor_getline);
if (parsed_script)
{
/* Execute the command(s). */
grub_script_execute (parsed_script);
/* The parsed script was executed, throw it away. */
grub_script_free (parsed_script);
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */
grub_command_execute ("boot", 0);
}
else
break;
}
if (grub_errno != GRUB_ERR_NONE)
{

View file

@ -28,6 +28,8 @@
/* Keep track of the memory allocated for this specific function. */
static struct grub_script_mem *func_mem = 0;
static char *menu_entry = 0;
%}
%union {
@ -40,12 +42,13 @@ static struct grub_script_mem *func_mem = 0;
%token GRUB_PARSER_TOKEN_IF "if"
%token GRUB_PARSER_TOKEN_WHILE "while"
%token GRUB_PARSER_TOKEN_FUNCTION "function"
%token GRUB_PARSER_TOKEN_MENUENTRY "menuentry"
%token GRUB_PARSER_TOKEN_ELSE "else"
%token GRUB_PARSER_TOKEN_THEN "then"
%token GRUB_PARSER_TOKEN_FI "fi"
%token GRUB_PARSER_TOKEN_NAME
%token GRUB_PARSER_TOKEN_VAR
%type <cmd> script grubcmd command commands if
%type <cmd> script grubcmd command commands menuentry if
%type <arglist> arguments;
%type <arg> argument;
%type <string> "if" "while" "function" "else" "then" "fi"
@ -53,7 +56,7 @@ static struct grub_script_mem *func_mem = 0;
%%
/* It should be possible to do this in a clean way... */
script: commands '\n'
script: commands returns
{
grub_script_parsed = $1;
}
@ -127,6 +130,7 @@ grubcmd: ws GRUB_PARSER_TOKEN_NAME ' ' arguments ws
command: grubcmd { $$ = $1; }
| if { $$ = $1; }
| function { $$ = 0; }
| menuentry { $$ = $1; }
;
/* A block of commands. */
@ -172,6 +176,24 @@ function: "function" ' ' GRUB_PARSER_TOKEN_NAME
}
;
/* A menu entry. Carefully save the memory that is allocated. */
menuentry: "menuentry" ' ' argument
{
grub_script_lexer_ref ();
} ws '{' returns
{
/* Record sourcecode of the menu entry. It can be
parsed multiple times if it is part of a
loop. */
grub_script_lexer_record_start ();
} commands returns '}'
{
menu_entry = grub_script_lexer_record_stop ();
$$ = grub_script_create_cmdmenu ($3, menu_entry, 0);
grub_script_lexer_deref ();
}
;
/* The first part of the if statement. It's used to switch the lexer
to a state in which it demands more tokens. */
if_statement: "if" { grub_script_lexer_ref (); }
@ -183,7 +205,7 @@ if: if_statement grubcmd ';' ws "then" returns commands returns "fi"
$$ = grub_script_create_cmdif ($2, $7, 0);
grub_script_lexer_deref ();
}
| if_statement grubcmd ';' ws "then" returns commands returns "else" returns commands "fi"
| if_statement grubcmd ';' ws "then" returns commands returns "else" returns commands returns "fi"
{
$$ = grub_script_create_cmdif ($2, $7, $11);
grub_script_lexer_deref ();

View file

@ -201,6 +201,37 @@ grub_script_create_cmdif (struct grub_script_cmd *bool,
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.
The options for this entry are passed in OPTIONS. */
struct grub_script_cmd *
grub_script_create_cmdmenu (struct grub_script_arg *title,
char *sourcecode,
int options)
{
struct grub_script_cmd_menuentry *cmd;
int i;
/* Having trailing returns can some some annoying conflicts, remove
them. XXX: Can the parser be improved to handle this? */
for (i = grub_strlen (sourcecode) - 1; i > 0; i--)
{
if (sourcecode[i] != '\n')
break;
sourcecode[i] = '\0';
}
cmd = grub_script_malloc (sizeof (*cmd));
cmd->cmd.exec = grub_script_execute_menuentry;
cmd->cmd.next = 0;
cmd->sourcecode = sourcecode;
cmd->title = title;
cmd->options = options;
return (struct grub_script_cmd *) cmd;
}
/* Create a block of commands. CMD contains the command that should
be added at the end of CMDBLOCK's list. If CMDBLOCK is zero, a new
cmdblock will be created. */