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

@ -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;
cmd = grub_command_find (cmdline);
grub_errno = GRUB_ERR_NONE;
struct grub_script *parsed_script;
if (cur_entry)
currline++;
/* 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;
/* 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);
return 0;
}
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;
/* Execute the command(s). */
grub_script_execute (parsed_script);
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;
}
}
/* The parsed script was executed, throw it away. */
grub_script_free (parsed_script);
}
fail:
return newmenu;
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;
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;
}
}
return menu;
return 0;
}
/* This starts the normal mode. */