2005-08-12 Yoshinori K. Okuji <okuji@enbug.org>

* DISTLIST: Added normal/completion.c.

        * normal/completion.c: New file.

        * term/i386/pc/console.c (grub_console_getwh): New function.
        (grub_console_term): Assign grub_console_getwh to getwh.

        * normal/cmdline.c (grub_tab_complete): Removed. Now the same
        function is defined in normal/completion.c as
        grub_normal_do_completion.
        (grub_cmdline_get): Use grub_normal_do_completion instead of
        grub_tab_complete.

        * kern/partition.c (grub_partition_map_iterate): Return 1 if HOOK
        returns non-zero, otherwise return 0.
        (grub_partition_iterate): First, probe the partition map. Then,
        call ITERATE only for this partition map.

        * kern/misc.c (grub_strncmp): Rewritten.

        * kern/disk.c (grub_disk_dev_iterate): Return 1 if P->ITERATE
        returns non-zero. Otherwise return 0.

        * include/grub/partition.h (grub_partition_map_iterate): Return
        int instead of void.

        * include/grub/normal.h (grub_normal_do_completion): New prototype.

        * include/grub/misc.h (grub_strncmp): Change the type of N to
        grub_size_t.

        * include/grub/disk.h (grub_disk_dev_iterate): Return int instead
        of void.

        * normal/menu.c (draw_border): Cast GRUB_TERM_BORDER_WIDTH to
        unsigned explictly before comparing it with I.

        * kern/main.c (grub_env_write_root): Add the attribute unused into
        VAR.

        * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added
        normal/completion.c.
        (normal_mod_SOURCES): Likewise.
        * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise.
        (normal_mod_SOURCES): Likewise.

        * normal/command.c (grub_iterate_commands): If ITERATE returns
        non-zero, return one immediately.
This commit is contained in:
okuji 2005-08-12 19:53:33 +00:00
parent e85e144bfc
commit 8de3495c7b
18 changed files with 192 additions and 348 deletions

View file

@ -133,304 +133,6 @@ grub_history_replace (int pos, char *s)
hist_lines[pos] = grub_strdup (s);
}
/* Try to complete the string in BUF, return the characters that
should be added to the string. This command outputs the possible
completions, in that case set RESTORE to 1 so the caller can
restore the prompt. */
static char *
grub_tab_complete (char *buf, int *restore)
{
char *pos = buf;
char *path;
char *found = 0;
int begin;
int end;
int len;
int numfound = 0;
/* The disk that is used for grub_partition_iterate. */
grub_device_t partdev;
/* String that is added when matched. */
char *matchstr;
auto void print_simple_completion (char *comp);
auto void print_partition_completion (char *comp);
auto int NESTED_FUNC_ATTR add_completion (const char *comp, const char *match,
const char *what,
void (*print_completion) (char *));
auto int iterate_commands (grub_command_t cmd);
auto int iterate_dev (const char *devname);
auto int iterate_part (const grub_partition_t p);
auto int iterate_dir (const char *filename, int dir);
void print_simple_completion (char *comp)
{
grub_printf (" %s", comp);
}
void print_partition_completion (char *comp)
{
grub_print_partinfo (partdev, comp);
grub_errno = 0;
}
/* Add a string to the list of possible completions. COMP is the
string that should be added. If this string completely matches
add the string MATCH to the input after adding COMP. The string
WHAT contains a discription of the kind of data that is added.
Use PRINT_COMPLETION to show the completions if there are
multiple matches. XXX: Because of a bug in gcc it is required to
use __regparm__ in some cases. */
int NESTED_FUNC_ATTR add_completion (const char *comp, const char *match,
const char *what,
void (*print_completion) (char *))
{
/* Bug in strncmp then len ==0. */
if (!len || grub_strncmp (pos, comp, len) == 0)
{
numfound++;
if (numfound == 1)
{
begin = len;
found = grub_strdup (comp);
end = grub_strlen (found);
matchstr = (char *) match;
}
/* Multiple matches found, print the first instead of completing. */
else if (numfound == 2)
{
grub_printf ("\nPossible %s are:\n", what);
print_completion (found);
}
if (numfound > 1)
{
char *s1 = found;
const char *s2 = comp;
int cnt = 0;
print_completion ((char *) comp);
/* Find out how many characters match. */
while ((cnt < end) && *s1 && *s2 && (*s1 == *s2))
{
s1++;
s2++;
cnt++;
}
end = cnt;
}
}
return 0;
}
int iterate_part (const grub_partition_t p)
{
add_completion (grub_partition_get_name (p), ")", "partitions",
print_partition_completion);
return 0;
}
int iterate_dir (const char *filename, int dir)
{
if (!dir)
add_completion (filename, " ", "files", print_simple_completion);
else
{
char fname[grub_strlen (filename) + 2];
grub_strcpy (fname, filename);
grub_sprintf (fname, "%s/", filename);
add_completion (fname, "", "files", print_simple_completion);
}
return 0;
}
int iterate_dev (const char *devname)
{
grub_device_t dev;
/* Complete the partition part. */
dev = grub_device_open (devname);
if (dev)
{
if (dev->disk && dev->disk->has_partitions)
add_completion (devname, ",", "disks", print_simple_completion);
else
add_completion (devname, ")", "disks", print_simple_completion);
}
grub_errno = GRUB_ERR_NONE;
return 0;
}
int iterate_commands (grub_command_t cmd)
{
if (grub_command_find (cmd->name))
{
if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)
add_completion (cmd->name, " ", "commands",
print_simple_completion);
}
return 0;
}
/* Remove blank space on the beginning of the line. */
while (*pos == ' ')
pos++;
/* Check if the string is a command or path. */
path = grub_strchr (pos, ' ');
if (!path)
{
/* Tab complete a command. */
len = grub_strlen (pos);
grub_iterate_commands (iterate_commands);
}
else
{
pos = path;
/* Remove blank space on the beginning of the line. */
while (*pos == ' ')
pos++;
/* Check if this is a completion for a device name. */
if (*pos == '(' && !grub_strchr (pos, ')'))
{
/* Check if this is a device or partition. */
char *partition = grub_strchr (++pos, ',');
if (!partition)
{
/* Complete the disk part. */
len = grub_strlen (pos);
grub_disk_dev_iterate (iterate_dev);
if (grub_errno)
goto fail;
}
else
{
*partition = '\0';
/* Complete the partition part. */
partdev = grub_device_open (pos);
*partition = ',';
grub_errno = GRUB_ERR_NONE;
if (partdev)
{
if (partdev->disk && partdev->disk->has_partitions)
{
pos = partition + 1;
len = grub_strlen (pos);
grub_partition_iterate (partdev->disk, iterate_part);
if (grub_errno)
grub_errno = 0;
}
grub_device_close (partdev);
}
else
goto fail;
}
}
else
{
char *device = grub_file_get_device_name (pos);
grub_device_t dev;
grub_fs_t fs;
dev = grub_device_open (device);
if (!dev)
goto fail;
fs = grub_fs_probe (dev);
if (grub_errno)
goto fail;
pos = grub_strrchr (pos, '/');
if (pos)
{
char *dir;
char *dirfile;
pos++;
len = grub_strlen (pos);
dir = grub_strchr (path, '/');
if (!dir)
{
*restore = 0;
return 0;
}
dir = grub_strdup (dir);
/* Cut away the filename part. */
dirfile = grub_strrchr (dir, '/');
dirfile[1] = '\0';
/* Tab complete a file. */
(fs->dir) (dev, dir, iterate_dir);
if (dev)
grub_device_close (dev);
grub_free (device);
grub_free (dir);
if (grub_errno)
goto fail;
}
else
{
found = grub_strdup ("/");
matchstr = "";
numfound = 1;
begin = 0;
end = 1;
}
}
}
/* If more than one match is found those matches will be printed and
the prompt should be restored. */
if (numfound > 1)
*restore = 1;
else
*restore = 0;
/* Return the part that matches. */
if (end && found)
{
char *insert;
insert = grub_malloc (end - begin + 1 + sizeof (matchstr));
grub_strncpy (insert, found + begin, end - begin);
insert[end - begin] = '\0';
if (numfound == 1)
grub_strcat (insert, matchstr);
grub_free (found);
return insert;
}
fail:
grub_free (found);
grub_errno = GRUB_ERR_NONE;
return 0;
}
void
grub_cmdline_run (int nested)
{
@ -607,7 +309,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
buf[lpos] = '\0';
insert = grub_tab_complete (buf, &restore);
insert = grub_normal_do_completion (buf, &restore);
/* Restore the original string. */
buf[lpos] = backup;