2005-10-24 Marco Gerards <mgerards@xs4all.nl>

* include/grub/parser.h: New file.

	* kern/parser.c: Likewise.

	* conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/parser.c'.
	(grub_setup_SOURCES): Likewise.
	(grub_probefs_SOURCES): Likewise.
	(grub_emu_SOURCES): Likewise.
	(kernel_img_HEADERS): Add `parser.h'.

	* conf/powerpc-ieee1275.rmk (grubof_HEADERS): Add `parser.h'.
	(grub_emu_SOURCES): Add `kern/parser.c'.
	(grubof_SOURCES): Likewise.

	* conf/sparc64-ieee1275.rmk (grubof_HEADERS): Add `parser.h'.
	(grubof_SOURCES): Add `kern/parser.c'.

	* include/grub/misc.h (grub_split_cmdline): Removed prototype.

	* kern/misc.c (grub_split_cmdline): Removed function.

	* kern/rescue.c: Include <grub/parser.h>.
	(grub_enter_rescue_mode): Use `grub_parser_split_cmdline' instead
	of `grub_split_cmdline'.

	* normal/command.c: Include <grub/parser.h>.
	(grub_command_execute):  Use `grub_parser_split_cmdline' instead
	of `grub_split_cmdline'.

	* normal/completion.c: Include <grub/parser.h>.
	(cmdline_state): New variable.
	(iterate_dir): End the filename with a quote depending on the
	command line state.
	(get_state): new function.
	(grub_normal_do_completion): Use `grub_parser_split_cmdline' to
	split the arguments and determine the current argument.  When the
	argument string is not quoted, escape all spaces.
This commit is contained in:
marco_g 2005-10-24 10:23:46 +00:00
parent 6d8f4b0e60
commit 04ccf3ec6f
14 changed files with 531 additions and 324 deletions

View file

@ -24,6 +24,7 @@
#include <grub/term.h>
#include <grub/env.h>
#include <grub/dl.h>
#include <grub/parser.h>
static grub_command_t grub_command_list;
@ -203,7 +204,7 @@ grub_command_execute (char *cmdline, int interactive)
char **arglist;
int numargs;
if (grub_split_cmdline (cmdline, cmdline_get, &num, &args))
if (grub_parser_split_cmdline (cmdline, cmdline_get, &num, &args))
return 0;
/* In case of an assignment set the environment accordingly instead

View file

@ -25,6 +25,7 @@
#include <grub/partition.h>
#include <grub/disk.h>
#include <grub/file.h>
#include <grub/parser.h>
/* The current word. */
static char *current_word;
@ -41,6 +42,8 @@ static const char *suffix;
/* The callback function to print items. */
static void (*print_func) (const char *, grub_completion_type_t, int);
/* The state the command line is in. */
static grub_parser_state_t cmdline_state;
/* Add a string to the list of possible completions. COMPLETION is the
@ -125,7 +128,15 @@ iterate_dir (const char *filename, int dir)
{
if (! dir)
{
if (add_completion (filename, " ", GRUB_COMPLETION_TYPE_FILE))
const char *prefix;
if (cmdline_state == GRUB_PARSER_STATE_DQUOTE)
prefix = "\" ";
else if (cmdline_state == GRUB_PARSER_STATE_QUOTE)
prefix = "\' ";
else
prefix = " ";
if (add_completion (filename, prefix, GRUB_COMPLETION_TYPE_FILE))
return 1;
}
else
@ -358,6 +369,19 @@ complete_arguments (char *command)
return 0;
}
static grub_parser_state_t
get_state (const char *cmdline)
{
grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
char use;
while (*cmdline)
state = grub_parser_cmdline_state (state, *(cmdline++), &use);
return state;
}
/* Try to complete the string in BUF. Return the characters that
should be added to the string. This command outputs the possible
completions by calling HOOK, in that case set RESTORE to 1 so the
@ -366,7 +390,8 @@ char *
grub_normal_do_completion (char *buf, int *restore,
void (*hook) (const char *, grub_completion_type_t, int))
{
char *first_word;
int argc;
char **argv;
/* Initialize variables. */
match = 0;
@ -375,45 +400,38 @@ grub_normal_do_completion (char *buf, int *restore,
print_func = hook;
*restore = 1;
/* Find the first word. */
for (first_word = buf; *first_word == ' '; first_word++)
;
/* Find the delimeter of the current word. */
for (current_word = first_word + grub_strlen (first_word);
current_word > first_word;
current_word--)
if (*current_word == ' ' || *current_word == '=')
break;
if (current_word == first_word)
if (grub_parser_split_cmdline (buf, 0, &argc, &argv))
return 0;
current_word = argv[argc];
/* Determine the state the command line is in, depending on the
state, it can be determined how to complete. */
cmdline_state = get_state (buf);
if (argc == 0)
{
/* Complete a command. */
if (grub_iterate_commands (iterate_command))
goto fail;
}
else if (*current_word == '-')
{
if (complete_arguments (buf))
goto fail;
}
else if (*current_word == '(' && ! grub_strchr (current_word, ')'))
{
/* Complete a device. */
if (complete_device ())
goto fail;
}
else
{
current_word++;
if (*current_word == '-')
{
if (complete_arguments (buf))
goto fail;
}
else if (*current_word == '(' && ! grub_strchr (current_word, ')'))
{
/* Complete a device. */
if (complete_device ())
goto fail;
}
else
{
/* Complete a file. */
if (complete_file ())
goto fail;
}
/* Complete a file. */
if (complete_file ())
goto fail;
}
/* If more than one match is found those matches will be printed and
@ -427,13 +445,32 @@ grub_normal_do_completion (char *buf, int *restore,
if (match)
{
char *ret;
char *escstr;
char *newstr;
int current_len;
int match_len;
int spaces = 0;
current_len = grub_strlen (current_word);
match_len = grub_strlen (match);
ret = grub_malloc (match_len - current_len + grub_strlen (suffix) + 1);
grub_strcpy (ret, match + current_len);
/* Count the number of spaces that have to be escaped. XXX:
More than just spaces have to be escaped. */
for (escstr = match + current_len; *escstr; escstr++)
if (*escstr == ' ')
spaces++;
ret = grub_malloc (match_len - current_len + grub_strlen (suffix) + spaces + 1);
newstr = ret;
for (escstr = match + current_len; *escstr; escstr++)
{
if (*escstr == ' ' && cmdline_state != GRUB_PARSER_STATE_QUOTE
&& cmdline_state != GRUB_PARSER_STATE_QUOTE)
*(newstr++) = '\\';
*(newstr++) = *escstr;
}
*newstr = '\0';
if (num_found == 1)
grub_strcat (ret, suffix);