diff --git a/ChangeLog b/ChangeLog index 622c18d8d..b1de12f2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +1999-09-19 OKUJI Yoshinori + + The completion code is heavily modified. + + * stage2/char_io.c [!STAGE1_5] (get_cmdline): In the completion + code, use COMPLETION_BUFFER to get the completion instead of + writing to BUF directly. + Save the position of a possible equal character after a command + in EQUAL_POS and replace the equal character with a space + temporarily for the code simplicity. + At first, just get completions, and, if there is more than one + completions, then print the list of the completions. + * stage2/disk_io.c [!STAGE1_5] (do_completion): New variable. + [!STAGE1_5] (unique): Moved the definition near the beginning. + [!STAGE1_5] (unique_string): Likewise. And changed the type to + char *. + (check_BSD_parts) [!STAGE1_5]: If DO_COMPLETION is non-zero, do + not print anything. + (real_open_partition) [!STAGE1_5]: Likewise. + [!STAGE1_5] (print_fsys_type): Likewise. + [!STAGE1_5] (print_a_completion): The argument FILENAME is + renamed to NAME. + If DO_COMPLETION is non-zero, get the unique part from NAME and + set UNIQUE_STRING to it. + If DO_COMPLETION is zero, just print NAME. + Do not call printf unconditionally. + [!STAGE1_5] (print_completions): Accept two arguements + IS_FILENAME and IS_COMPLETION instead of FILENAME. + Set UNIQUE_STRING to UNIQUE_BUF. + Set DO_COMPLETION to IS_COMPLETION and set it to zero before + returning. + If IS_FILENAME is zero, then complete builtin commands and + return UNIQUE - 1. + Use BUF instead of FILENAME. + If IS_COMPLETION is non-zero, do not print anything. + Copy UNIQUE_STRING to PTR only if IS_COMPLETION and + *UNIQUE_STRING are non-zero. + * stage2/shared.h (COMPLETION_BUF): New macro. + (COMPLETION_BUFLEN): Likewise. + (UNIQUE_BUF): Likewise. + (UNIQUE_BUFLEN): Likewise. + (MENU_BUF): Set to UNIQUE_BUF + UNIQUE_BUFLEN. + (MENU_BUFLEN): Set to 0x8000 + PASSWORD_BUF - UNIQUE_BUF. + (print_completions): Adjusted to the definition. + 1999-09-19 OKUJI Yoshinori * acinclude.m4 (grub_ASM_PREFIX_REQUIREMENT): Do not call diff --git a/stage2/char_io.c b/stage2/char_io.c index 4ad656962..9423addba 100644 --- a/stage2/char_io.c +++ b/stage2/char_io.c @@ -373,57 +373,65 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, { case 9: /* TAB lists completions */ { - int i, j = 0, llen_old = llen; - + int i; + /* POS points to the first space after a command. */ + int pos = 0; + int ret; + char *completion_buffer = (char *) COMPLETION_BUF; + int equal_pos = -1; + int is_filename; + /* Find the first word. */ - while (buf[j] == ' ') - j++; - while (buf[j] && buf[j] != '=' && buf[j] != ' ') - j++; + while (buf[pos] == ' ') + pos++; + while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ') + pos++; + + is_filename = (lpos > pos); - /* Since the command line cannot have a '\n', we're OK to - use C. */ - c = buf[lpos]; - - cl_kill_to_end (); - - /* goto part after line here */ - yend = ((llen + plen) / 79) + ystart; - putchar ('\n'); - gotoxy (0, getxy () & 0xff); - - - if (lpos > j) + /* Find the position of the equal character after a + command, and replace it with a space. */ + for (i = pos; buf[i] && buf[i] != ' '; i++) + if (buf[i] == '=') + { + equal_pos = i; + buf[i] = ' '; + break; + } + + /* Find the position of the first character in this + word. */ + for (i = lpos; i > 0 && buf[i - 1] != ' '; i--) + ; + + /* Copy this word to COMPLETION_BUFFER and do the + completion. */ + grub_memmove (completion_buffer, buf + i, lpos - i); + completion_buffer[lpos - i] = 0; + ret = print_completions (is_filename, 1); + + if (ret >= 0) { - for (i = lpos; i > 0 && buf[i - 1] != ' '; i--); - if (i <= j) - i = j + 1; - /* print possible completions */ - print_completions (buf + i); - /* if somebody in print_completions has added something, - account for that */ - while (buf[lpos]) - lpos++, llen_old++; - } - else - { - /* Print the command list. */ - struct builtin **builtin; + /* Found, so insert COMPLETION_BUFFER. */ + cl_insert (completion_buffer + lpos - i); - for (builtin = builtin_table; *builtin != 0; builtin++) + if (ret > 0) { - /* Do not print the name if it cannot be run in - the command-line interface. */ - if (! ((*builtin)->flags & BUILTIN_CMDLINE)) - continue; + /* There is more than one candidates, so print + the list. */ - grub_printf ("%s ", (*builtin)->name); + /* Go to the part after the line here. */ + yend = ((llen + plen) / 79) + ystart; + grub_putchar ('\n'); + gotoxy (0, getxy () & 0xff); + + print_completions (is_filename, 0); } } - /* restore command-line */ - buf[lpos] = c; - llen = llen_old; + /* Restore the command-line. */ + if (equal_pos >= 0) + buf[equal_pos] = '='; cl_init (); } break; diff --git a/stage2/disk_io.c b/stage2/disk_io.c index 4a0bf28b9..c9e963d8f 100644 --- a/stage2/disk_io.c +++ b/stage2/disk_io.c @@ -30,6 +30,11 @@ void (*debug_fs) (int) = NULL; void (*debug_fs_func) (int) = NULL; int print_possibilities; + +static int do_completion; +static int unique; +static char *unique_string; + #endif int fsmax; @@ -406,10 +411,13 @@ check_BSD_parts (int flags) { if (!got_part) { - printf ("[BSD sub-partitions immediately follow]\n"); + if (! do_completion) + printf ("[BSD sub-partitions immediately follow]\n"); got_part = 1; } - printf (" BSD Partition num: \'%c\', ", part_no + 'a'); + + if (! do_completion) + printf (" BSD Partition num: \'%c\', ", part_no + 'a'); check_and_print_mount (); } else @@ -537,7 +545,8 @@ real_open_partition (int flags) else if (flags) { current_partition |= 0xFFFF; - printf (" Partition num: %d, ", slice_no); + if (! do_completion) + printf (" Partition num: %d, ", slice_no); if (! IS_PC_SLICE_TYPE_BSD (current_slice)) check_and_print_mount (); else @@ -632,10 +641,6 @@ open_partition (void) /* XX used for device completion in 'set_device' and 'print_completions' */ static int incomplete, disk_choice; -#ifndef STAGE1_5 -static int unique; -static char unique_string[128]; /* XXX Don't know yet */ -#endif static enum { PART_UNSPECIFIED = 0, @@ -957,48 +962,51 @@ setup_part (char *filename) void print_fsys_type (void) { - printf (" Filesystem type "); - - if (fsys_type != NUM_FSYS) - printf ("is %s, ", fsys_table[fsys_type].name); - else - printf ("unknown, "); - - if (current_partition == 0xFFFFFF) - printf ("using whole disk\n"); - else - printf ("partition type 0x%x\n", current_slice); + if (! do_completion) + { + printf (" Filesystem type "); + + if (fsys_type != NUM_FSYS) + printf ("is %s, ", fsys_table[fsys_type].name); + else + printf ("unknown, "); + + if (current_partition == 0xFFFFFF) + printf ("using whole disk\n"); + else + printf ("partition type 0x%x\n", current_slice); + } } #endif /* STAGE1_5 */ #ifndef STAGE1_5 -/* - * print_a_completion saves what has been printed to unique_string - * printf's with a leading ' '. - */ - +/* If DO_COMPLETION is true, just print NAME. Otherwise save the unique + part into UNIQUE_STRING. */ void -print_a_completion (char *filename) +print_a_completion (char *name) { - char *f = filename; - char *u = unique_string; - - if (! *u && unique == 0) + if (do_completion) { - /* copy first string, this is unique. */ - while ((*u++ = *f++)) - ; + char *buf = unique_string; + + if (! unique) + while ((*buf++ = *name++)) + ; + else + { + while (*buf && (*buf == *name)) + { + buf++; + name++; + } + /* mismatch, strip it. */ + *buf = '\0'; + } } else - { - while (*u && (*u == *f)) - u++, f++; - /* mismatch, strip it. */ - *u = '\0'; - } + grub_printf (" %s", name); + unique++; - - printf (" %s", filename); } /* @@ -1006,27 +1014,66 @@ print_a_completion (char *filename) * any sane combination of the two. */ -void -print_completions (char *filename) +int +print_completions (int is_filename, int is_completion) { - char *ptr = filename; + char *buf = (char *) COMPLETION_BUF; + char *ptr = buf; - *unique_string = '\0'; + unique_string = (char *) UNIQUE_BUF; + *unique_string = 0; unique = 0; + do_completion = is_completion; - if (*filename == '/' || (ptr = set_device (filename)) || incomplete) + if (! is_filename) + { + /* Print the completions of builtin commands. */ + struct builtin **builtin; + + if (! is_completion) + grub_printf (" Possible commands are:"); + + for (builtin = builtin_table; (*builtin); builtin++) + { + /* If *BUILTIN cannot be run in the command-line, skip it. */ + if (! ((*builtin)->flags & BUILTIN_CMDLINE)) + continue; + + if (substring (buf, (*builtin)->name) <= 0) + print_a_completion ((*builtin)->name); + } + + if (is_completion && *unique_string) + { + if (unique == 1) + { + char *u = unique_string + grub_strlen (unique_string); + + *u++ = ' '; + *u = 0; + } + + grub_strcpy (buf, unique_string); + } + + do_completion = 0; + return unique - 1; + } + + if (*buf == '/' || (ptr = set_device (buf)) || incomplete) { errnum = 0; - if (*filename != '/' && (incomplete || !*ptr)) + if (*buf != '/' && (incomplete || ! *ptr)) { - if (!part_choice) + if (! part_choice) { /* disk completions */ int disk_no, i, j; struct geometry geom; - printf (" Possible disks are: "); + if (! is_completion) + grub_printf (" Possible disks are: "); for (i = (ptr && (*(ptr-2) == 'h' && *(ptr-1) == 'd') ? 1 : 0); i < (ptr && (*(ptr-2) == 'f' && *(ptr-1) == 'd') ? 1 : 2); @@ -1035,8 +1082,8 @@ print_completions (char *filename) for (j = 0; j < 8; j++) { disk_no = (i * 0x80) + j; - if ((disk_choice || disk_no == current_drive) && - ! get_diskinfo (disk_no, &geom)) + if ((disk_choice || disk_no == current_drive) + && ! get_diskinfo (disk_no, &geom)) { char dev_name[4]; @@ -1049,32 +1096,36 @@ print_completions (char *filename) } } - ptr = filename; - while (*ptr != '(') - ptr--; - ptr++; - { - char *u = unique_string; - while ((*ptr++ = *u++)) - ; - ptr--; - } - ptr--; - if ((*(ptr - 2) == 'h') && (*(ptr - 1) == 'd') - && ('0' <= *ptr && *ptr <= '8')) - *(ptr + 1) = ',', *(ptr + 2) = '\0'; - if ((*(ptr - 2) == 'f') && (*(ptr - 1) == 'd') - && ('0' <= *ptr && *ptr <= '8')) - *(ptr + 1) = ')', *(ptr + 2) = '\0'; - - putchar ('\n'); + if (is_completion && *unique_string) + { + ptr = buf; + while (*ptr != '(') + ptr--; + ptr++; + { + char *u = unique_string; + while ((*ptr++ = *u++)) + ; + ptr--; + } + ptr--; + if ((*(ptr - 2) == 'h') && (*(ptr - 1) == 'd') + && ('0' <= *ptr && *ptr <= '8')) + *(ptr + 1) = ',', *(ptr + 2) = '\0'; + if ((*(ptr - 2) == 'f') && (*(ptr - 1) == 'd') + && ('0' <= *ptr && *ptr <= '8')) + *(ptr + 1) = ')', *(ptr + 2) = '\0'; + + grub_putchar ('\n'); + } } else { /* partition completions */ if (part_choice == PART_DISK) { - printf (" Possible partitions are:\n"); + if (! is_completion) + grub_printf (" Possible partitions are:\n"); real_open_partition (1); } else @@ -1084,7 +1135,7 @@ print_completions (char *filename) check_and_print_mount (); /* FIXME: Can talk about linux only, do we need to know about syntax here? */ - ptr = filename; + ptr = buf; while (*ptr) ptr++; if (*(ptr - 1) != ')') @@ -1098,28 +1149,36 @@ print_completions (char *filename) else if (*ptr == '/') { /* filename completions */ - printf (" Possible files are:"); - dir (filename); - { - char *u = unique_string; + if (! is_completion) + grub_printf (" Possible files are:"); + + dir (buf); + + if (is_completion && *unique_string) + { + ptr += grub_strlen (ptr); + while (*ptr != '/') + ptr--; + ptr++; + + if (unique == 1) + { + char *u = unique_string + grub_strlen (unique_string); + + *u++ = ' '; + *u = 0; + } - if (*u) - { - while (*ptr++) - ; - while (*ptr != '/') - ptr--; - ptr++; - while ((*ptr++ = *u++)) - ; - } - } + grub_strcpy (ptr, unique_string); + } } else errnum = ERR_BAD_FILENAME; } print_error (); + do_completion = 0; + return unique - 1; } #endif /* STAGE1_5 */ diff --git a/stage2/shared.h b/stage2/shared.h index d6b6bb352..6c2969cf8 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -105,9 +105,17 @@ extern char *grub_scratch_mem; #define HISTORY_SIZE 5 #define HISTORY_BUFLEN (MAX_CMDLINE * HISTORY_SIZE) +/* The buffer for the completion. */ +#define COMPLETION_BUF (HISTORY_BUF + HISTORY_BUFLEN) +#define COMPLETION_BUFLEN MAX_CMDLINE + +/* The buffer for the unique string. */ +#define UNIQUE_BUF (COMPLETION_BUF + COMPLETION_BUFLEN) +#define UNIQUE_BUFLEN MAX_CMDLINE + /* The buffer for the menu entries. */ -#define MENU_BUF (HISTORY_BUF + HISTORY_BUFLEN) -#define MENU_BUFLEN (0x8000 + PASSWORD_BUF - HISTORY_BUF) +#define MENU_BUF (UNIQUE_BUF + UNIQUE_BUFLEN) +#define MENU_BUFLEN (0x8000 + PASSWORD_BUF - UNIQUE_BUF) /* * Linux setup parameters @@ -659,7 +667,7 @@ void print_fsys_type (void); /* Display device and filename completions. */ void print_a_completion (char *filename); -void print_completions (char *filename); +int print_completions (int is_filename, int is_completion); /* Copies the current partition data to the desired address. */ void copy_current_part_entry (char *buf);