From 454e26626c55fa74a1939a47de08305aacf81b54 Mon Sep 17 00:00:00 2001 From: okuji Date: Wed, 30 Aug 2000 07:00:16 +0000 Subject: [PATCH] add a timeout to --hold for the grub shell, fix a compilation error with gcc-2.7.2.3, and the command-line interface is switched to single-line editing mode. --- ChangeLog | 26 +++ NEWS | 7 + configure | 134 +++++++++------ configure.in | 13 +- grub/main.c | 14 +- stage2/char_io.c | 418 ++++++++++++++++++++++++++++++++++------------- stage2/shared.h | 2 + 7 files changed, 445 insertions(+), 169 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8be744673..b453a9083 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2000-08-30 OKUJI Yoshinori + + * configure.in (CPPFLAGS): Remove -Wundef by default. Add the + option only if the C compiler supports it, because GCC 2.7.x + doesn't support it. + * grub/main.c (longopts): The type of the argument for "hold" is + changed to OPTIONAL_ARGUMENT. + (main): If --hold is specified, check if OPTARG is zero. If so, + set HOLD to -1, otherwise, set it to the digit OPTARG. + If HOLD is greater than zero, decrease it once per loop. + +2000-08-30 OKUJI Yoshinori + + The command-line interface is switched to single-line editing + mode. + + * stage2/char_io.c [!STAGE1_5] (get_cmdline): Extensively + rewritten. The nested functions cl_print and cl_kill_to_end are + removed, cl_refresh, cl_backward, cl_forward and cl_delete are + added, and, cl_init and cl_insert are rewritten from scratch. + See the source code, for more information. I don't think this + kind of changes can be represented in ChangeLog. + [!STAGE1_5] (CMDLINE_WIDTH): New macro. + [!STAGE1_5] (CMDLINE_MARGIN): Likewise. + * stage2/shared.h (TERMINAL_DUMB): Likewise. + 2000-08-28 OKUJI Yoshinori * grub/asmstub.c (console_putchar) [HAVE_LIBCURSES]: If diff --git a/NEWS b/NEWS index a4e8c990f..07d22d4e4 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,13 @@ New in 0.5.96 - XXXX-XX-XX: new commands, "serial" and "terminal" in the command-line and the menu. See the manual, for more details. * Preserve the possible magic number used by Windows NT in a MBR. +* The command-line interface is switched to single-line editing mode. +* Only for developers: the configure script accepts + `--enable-serial-speed-simulation', which is useful when you want to + simulate the speed of a serial device on a psuedo terminal. +* Also only for developers: you can specify an optional argument to the + option `--hold' for the grub shell. The argument means how many + seconds the grub shell should wait until diving into the main routine. New in 0.5.95 - 2000-06-27: * NetBSD ELF kernel support is added. You have to specify the new option diff --git a/configure b/configure index cc7a5d85a..ad8823ddf 100644 --- a/configure +++ b/configure @@ -1592,13 +1592,49 @@ fi # Enforce coding standards. CPPFLAGS="$CPPFLAGS -Wall -Wmissing-prototypes -Wunused -Wshadow" -CPPFLAGS="$CPPFLAGS -Wpointer-arith -Wundef" +CPPFLAGS="$CPPFLAGS -Wpointer-arith" + +echo $ac_n "checking whether -Wundef works""... $ac_c" 1>&6 +echo "configure:1599: checking whether -Wundef works" >&5 +if eval "test \"`echo '$''{'undef_flag'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + saved_CPPFLAGS=$CPPFLAGS + CPPFLAGS="-Wundef" + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + undef_flag=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + undef_flag=no +fi +rm -f conftest* + CPPFLAGS=$saved_CPPFLAGS + +fi + +echo "$ac_t""$undef_flag" 1>&6 + +if test "x$undef_flag" = xyes; then + CPPFLAGS="$CPPFLAGS -Wundef" +fi if test "x$with_binutils" != x; then # Extract the first word of "objcopy", so it can be a program name with args. set dummy objcopy; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1602: checking for $ac_word" >&5 +echo "configure:1638: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_OBJCOPY'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1634,7 +1670,7 @@ else # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args. set dummy ${ac_tool_prefix}objcopy; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1638: checking for $ac_word" >&5 +echo "configure:1674: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_OBJCOPY'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1668,7 +1704,7 @@ fi # Defined in acinclude.m4. echo $ac_n "checking if C symbols get an underscore after compilation""... $ac_c" 1>&6 -echo "configure:1672: checking if C symbols get an underscore after compilation" >&5 +echo "configure:1708: checking if C symbols get an underscore after compilation" >&5 if eval "test \"`echo '$''{'grub_cv_asm_uscore'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1681,7 +1717,7 @@ func (int *list) } EOF -if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'; { (eval echo configure:1685: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.s; then +if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'; { (eval echo configure:1721: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.s; then true else { echo "configure: error: ${CC-cc} failed to produce assembly code" 1>&2; exit 1; } @@ -1707,7 +1743,7 @@ fi echo "$ac_t""$grub_cv_asm_uscore" 1>&6 echo $ac_n "checking whether ${OBJCOPY} works for absolute addresses""... $ac_c" 1>&6 -echo "configure:1711: checking whether ${OBJCOPY} works for absolute addresses" >&5 +echo "configure:1747: checking whether ${OBJCOPY} works for absolute addresses" >&5 if eval "test \"`echo '$''{'grub_cv_prog_objcopy_absolute'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1719,21 +1755,21 @@ cmain (void) } EOF -if { (eval echo configure:1723: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then : +if { (eval echo configure:1759: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then : else { echo "configure: error: ${CC-cc} cannot compile C source code" 1>&2; exit 1; } fi grub_cv_prog_objcopy_absolute=yes for link_addr in 2000 8000 7C00; do - if { ac_try='${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec'; { (eval echo configure:1729: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : + if { ac_try='${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec'; { (eval echo configure:1765: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : else { echo "configure: error: ${CC-cc} cannot link at address $link_addr" 1>&2; exit 1; } fi - if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'; { (eval echo configure:1733: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : + if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'; { (eval echo configure:1769: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : else { echo "configure: error: ${OBJCOPY-objcopy} cannot create binary files" 1>&2; exit 1; } fi - if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'; { (eval echo configure:1737: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'; { (eval echo configure:1773: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then mv -f conftest conftest.old else grub_cv_prog_objcopy_absolute=no @@ -1750,7 +1786,7 @@ fi echo $ac_n "checking whether addr32 must be in the same line as the instruction""... $ac_c" 1>&6 -echo "configure:1754: checking whether addr32 must be in the same line as the instruction" >&5 +echo "configure:1790: checking whether addr32 must be in the same line as the instruction" >&5 if eval "test \"`echo '$''{'grub_cv_asm_prefix_requirement'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1759,7 +1795,7 @@ else l1: addr32 movb %al, l1 EOF -if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1763: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1799: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then grub_cv_asm_prefix_requirement=yes else grub_cv_asm_prefix_requirement=no @@ -1791,7 +1827,7 @@ echo "$ac_t""$grub_cv_asm_prefix_requirement" 1>&6 echo $ac_n "checking for .code16 addr32 assembler support""... $ac_c" 1>&6 -echo "configure:1795: checking for .code16 addr32 assembler support" >&5 +echo "configure:1831: checking for .code16 addr32 assembler support" >&5 if eval "test \"`echo '$''{'grub_cv_asm_addr32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1806,7 +1842,7 @@ else sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s fi -if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1810: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1846: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then grub_cv_asm_addr32=yes else grub_cv_asm_addr32=no @@ -1823,7 +1859,7 @@ fi echo $ac_n "checking whether an absolute indirect call/jump must not be prefixed with an asterisk""... $ac_c" 1>&6 -echo "configure:1827: checking whether an absolute indirect call/jump must not be prefixed with an asterisk" >&5 +echo "configure:1863: checking whether an absolute indirect call/jump must not be prefixed with an asterisk" >&5 if eval "test \"`echo '$''{'grub_cv_asm_absolute_without_asterisk'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1834,7 +1870,7 @@ offset: .word 0 EOF -if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1838: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then +if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1874: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then grub_cv_asm_absolute_without_asterisk=no else grub_cv_asm_absolute_without_asterisk=yes @@ -1855,19 +1891,19 @@ echo "$ac_t""$grub_cv_asm_absolute_without_asterisk" 1>&6 echo $ac_n "checking if start is defined by the compiler""... $ac_c" 1>&6 -echo "configure:1859: checking if start is defined by the compiler" >&5 +echo "configure:1895: checking if start is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_start_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1907: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_start_symbol=yes else @@ -1891,19 +1927,19 @@ echo "$ac_t""$grub_cv_check_start_symbol" 1>&6 echo $ac_n "checking if _start is defined by the compiler""... $ac_c" 1>&6 -echo "configure:1895: checking if _start is defined by the compiler" >&5 +echo "configure:1931: checking if _start is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_uscore_start_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_uscore_start_symbol=yes else @@ -1932,19 +1968,19 @@ fi echo $ac_n "checking if __bss_start is defined by the compiler""... $ac_c" 1>&6 -echo "configure:1936: checking if __bss_start is defined by the compiler" >&5 +echo "configure:1972: checking if __bss_start is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_uscore_uscore_bss_start_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1984: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_uscore_uscore_bss_start_symbol=yes else @@ -1968,19 +2004,19 @@ echo "$ac_t""$grub_cv_check_uscore_uscore_bss_start_symbol" 1>&6 echo $ac_n "checking if _edata is defined by the compiler""... $ac_c" 1>&6 -echo "configure:1972: checking if _edata is defined by the compiler" >&5 +echo "configure:2008: checking if _edata is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_uscore_edata_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2020: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_uscore_edata_symbol=yes else @@ -2004,19 +2040,19 @@ echo "$ac_t""$grub_cv_check_uscore_edata_symbol" 1>&6 echo $ac_n "checking if edata is defined by the compiler""... $ac_c" 1>&6 -echo "configure:2008: checking if edata is defined by the compiler" >&5 +echo "configure:2044: checking if edata is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_edata_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2056: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_edata_symbol=yes else @@ -2046,19 +2082,19 @@ fi echo $ac_n "checking if end is defined by the compiler""... $ac_c" 1>&6 -echo "configure:2050: checking if end is defined by the compiler" >&5 +echo "configure:2086: checking if end is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_end_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2098: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_end_symbol=yes else @@ -2082,19 +2118,19 @@ echo "$ac_t""$grub_cv_check_end_symbol" 1>&6 echo $ac_n "checking if _end is defined by the compiler""... $ac_c" 1>&6 -echo "configure:2086: checking if _end is defined by the compiler" >&5 +echo "configure:2122: checking if _end is defined by the compiler" >&5 if eval "test \"`echo '$''{'grub_cv_check_uscore_end_symbol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2134: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* grub_cv_check_uscore_end_symbol=yes else @@ -2132,7 +2168,7 @@ fi # Get the filename or the whole disk and open it. # Known to work on NetBSD. echo $ac_n "checking for opendisk in -lutil""... $ac_c" 1>&6 -echo "configure:2136: checking for opendisk in -lutil" >&5 +echo "configure:2172: checking for opendisk in -lutil" >&5 ac_lib_var=`echo util'_'opendisk | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2140,7 +2176,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lutil $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2179,7 +2215,7 @@ fi # Unless the user specify --without-curses, check for curses. if test "x$with_curses" != "xno"; then echo $ac_n "checking for wgetch in -lncurses""... $ac_c" 1>&6 -echo "configure:2183: checking for wgetch in -lncurses" >&5 +echo "configure:2219: checking for wgetch in -lncurses" >&5 ac_lib_var=`echo ncurses'_'wgetch | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2187,7 +2223,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lncurses $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2221,7 +2257,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for wgetch in -lcurses""... $ac_c" 1>&6 -echo "configure:2225: checking for wgetch in -lcurses" >&5 +echo "configure:2261: checking for wgetch in -lcurses" >&5 ac_lib_var=`echo curses'_'wgetch | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2229,7 +2265,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lcurses $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2280: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2275,17 +2311,17 @@ for ac_hdr in string.h strings.h ncurses/curses.h ncurses.h curses.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2279: checking for $ac_hdr" >&5 +echo "configure:2315: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2289: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2325: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* diff --git a/configure.in b/configure.in index 55225fa68..3301910b2 100644 --- a/configure.in +++ b/configure.in @@ -94,7 +94,18 @@ AC_SUBST(GRUB_CFLAGS) # Enforce coding standards. CPPFLAGS="$CPPFLAGS -Wall -Wmissing-prototypes -Wunused -Wshadow" -CPPFLAGS="$CPPFLAGS -Wpointer-arith -Wundef" +CPPFLAGS="$CPPFLAGS -Wpointer-arith" + +AC_CACHE_CHECK([whether -Wundef works], undef_flag, [ + saved_CPPFLAGS=$CPPFLAGS + CPPFLAGS="-Wundef" + AC_TRY_COMPILE(, , undef_flag=yes, undef_flag=no) + CPPFLAGS=$saved_CPPFLAGS +]) + +if test "x$undef_flag" = xyes; then + CPPFLAGS="$CPPFLAGS -Wundef" +fi if test "x$with_binutils" != x; then dnl AC_PATH_TOOL(OBJCOPY, objcopy, , "$with_binutils:$PATH") diff --git a/grub/main.c b/grub/main.c index a829a1b80..eccf485a7 100644 --- a/grub/main.c +++ b/grub/main.c @@ -66,7 +66,7 @@ static struct option longopts[] = {"config-file", required_argument, 0, OPT_CONFIG_FILE}, {"device-map", required_argument, 0, OPT_DEVICE_MAP}, {"help", no_argument, 0, OPT_HELP}, - {"hold", no_argument, 0, OPT_HOLD}, + {"hold", optional_argument, 0, OPT_HOLD}, {"install-partition", required_argument, 0, OPT_INSTALL_PARTITION}, {"no-config-file", no_argument, 0, OPT_NO_CONFIG_FILE}, {"no-curses", no_argument, 0, OPT_NO_CURSES}, @@ -153,7 +153,10 @@ main (int argc, char **argv) break; case OPT_HOLD: - hold = 1; + if (! optarg) + hold = -1; + else + hold = atoi (optarg); break; case OPT_CONFIG_FILE: @@ -224,7 +227,12 @@ main (int argc, char **argv) printf ("Run \"gdb %s %d\", and set HOLD to zero.\n", program_name, (int) getpid ()); while (hold) - sleep (1); + { + if (hold > 0) + hold--; + + sleep (1); + } /* Transfer control to the stage2 simulator. */ exit (grub_stage2 ()); diff --git a/stage2/char_io.c b/stage2/char_io.c index 955be86fd..08c9d25e1 100644 --- a/stage2/char_io.c +++ b/stage2/char_io.c @@ -222,11 +222,47 @@ int get_cmdline (char *prompt, char *cmdline, int maxlen, int echo_char, int readline) { - int ystart, yend, xend, lpos, c; + /* This is a rather complicated function. So explain the concept. + + A command-line consists of ``section''s. A section is a part of the + line which may be displayed on the screen, but a section is never + displayed with another section simultaneously. + + Each section is basically 77 or less characters, but the exception + is the first section, which is 78 or less characters, because the + starting point is special. See below. + + The first section contains a prompt and a command-line (or the + first part of a command-line when it is too long to be fit in the + screen). So, in the first section, the number of command-line + characters displayed is 78 minus the length of the prompt (or + less). If the command-line has more characters, `>' is put at the + position 78 (zero-origin), to inform the user of the hidden + characters. + + Other sections always have `<' at the first position, since there + is absolutely a section before each section. If there is a section + after another section, this section consists of 77 characters and + `>' at the last position. The last section has 77 or less + characters and doesn't have `>'. + + Each section other than the last shares some characters with the + previous section. This region is called ``margin''. If the cursor + is put at the magin which is shared by the first section and the + second, the first section is displayed. Otherwise, a displayed + section is switched to another section, only if the cursor is put + outside that section. */ + + /* XXX: These should be defined in shared.h, but I leave these here, + until this code is freezed. */ +#define CMDLINE_WIDTH 78 +#define CMDLINE_MARGIN 10 + + int xpos, lpos, c, section; /* The length of PROMPT. */ - int plen = 0; + int plen; /* The length of the command-line. */ - int llen = 0; + int llen; /* The index for the history. */ int history = -1; /* The working buffer for the command-line. */ @@ -234,90 +270,276 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, /* The kill buffer. */ char *kill_buf = (char *) KILL_BUF; - /* nested function definition for code simplicity */ - static void cl_print (char *str, int real_echo_char) + /* Nested function definitions for code simplicity. */ + + /* The forward declarations of nested functions are prefixed + with `auto'. */ + auto void cl_refresh (int full, int len); + auto void cl_backward (int count); + auto void cl_forward (int count); + auto void cl_insert (const char *str); + auto void cl_delete (int count); + auto void cl_init (void); + + /* Move the cursor backward. */ + void cl_backward (int count) { - while (*str != 0) + lpos -= count; + + /* If the cursor is in the first section, display the first section + instead of the second. */ + if (section == 1 && plen + lpos < CMDLINE_WIDTH) + cl_refresh (1, 0); + else if (xpos - count < 1) + cl_refresh (1, 0); + else { - putchar (real_echo_char ? real_echo_char : *str); - str++; - if (++xend > 78) + int i; + + xpos -= count; + + if (! (terminal & TERMINAL_DUMB)) { - xend = 0; - putchar (' '); - if (yend == (getxy () & 0xff)) - ystart--; + if (terminal & TERMINAL_CONSOLE) + { + int y = getxy () & 0xFF; + + gotoxy (xpos, y); + return; + } +# ifdef SUPPORT_SERIAL + else if (terminal & TERMINAL_SERIAL) + { + /* Ugly optimization. */ + if (count > 4) + { + grub_printf ("\e[%dD", count); + return; + } + } +# endif /* SUPPORT_SERIAL */ + } + + for (i = 0; i < count; i++) + grub_putchar ('\b'); + } + } + + /* Move the cursor forward. */ + void cl_forward (int count) + { + lpos += count; + + /* If the cursor goes outside, scroll the screen to the right. */ + if (xpos + count >= CMDLINE_WIDTH) + cl_refresh (1, 0); + else + { + int i; + + xpos += count; + + if (! (terminal & TERMINAL_DUMB)) + { + if (terminal & TERMINAL_CONSOLE) + { + int y = getxy () & 0xFF; + + gotoxy (xpos, y); + return; + } +# ifdef SUPPORT_SERIAL + else if (terminal & TERMINAL_SERIAL) + { + /* Ugly optimization. */ + if (count > 4) + { + grub_printf ("\e[%dC", count); + return; + } + } +# endif /* SUPPORT_SERIAL */ + } + + for (i = lpos - count; i < lpos; i++) + { + if (! echo_char) + grub_putchar (buf[i]); else - yend++; + grub_putchar (echo_char); } } } - /* nested function definition for code simplicity */ - static void cl_setcpos (void) - { - yend = ((lpos + plen) / 79) + ystart; - xend = ((lpos + plen) % 79); - gotoxy (xend, yend); - } - - /* nested function definition for initial command-line printing */ - static void cl_init () - { - /* distinguish us from other lines and error messages! */ - putchar ('\n'); - - /* print full line and set position here */ - ystart = (getxy () & 0xff); - yend = ystart; - xend = 0; - cl_print (prompt, 0); - cl_print (buf, echo_char); - cl_setcpos (); - } - - /* nested function definition for erasing to the end of the line */ - static void cl_kill_to_end () + /* Refresh the screen. If FULL is true, redraw the full line, otherwise, + only LEN characters from LPOS. */ + void cl_refresh (int full, int len) { int i; - buf[lpos] = 0; - for (i = lpos; i <= llen; i++) + int start; + int pos = xpos; + + if (full) { - if (i && ((i + plen) % 79) == 0) - putchar (' '); - putchar (' '); + /* Recompute the section number. */ + if (lpos + plen < CMDLINE_WIDTH) + section = 0; + else + section = ((lpos + plen - CMDLINE_WIDTH) + / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1); + + /* From the start to the end. */ + len = CMDLINE_WIDTH; + pos = 0; + grub_putchar ('\r'); + + /* If SECTION is the first section, print the prompt, otherwise, + print `<'. */ + if (section == 0) + { + grub_printf ("%s", prompt); + len -= plen; + pos += plen; + } + else + { + grub_putchar ('<'); + len--; + pos++; + } } - llen = lpos; - cl_setcpos (); + + /* Compute the index to start writing BUF and the resulting position + on the screen. */ + if (section == 0) + { + int offset = 0; + + if (! full) + offset = xpos - plen; + + start = 0; + xpos = lpos + plen; + start += offset; + } + else + { + int offset = 0; + + if (! full) + offset = xpos - 1; + + start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + + CMDLINE_WIDTH - plen - CMDLINE_MARGIN); + xpos = lpos + 1 - start; + start += offset; + } + + /* Print BUF. If ECHO_CHAR is not zero, put it instead. */ + for (i = start; i < start + len && i < llen; i++) + { + if (! echo_char) + grub_putchar (buf[i]); + else + grub_putchar (echo_char); + + pos++; + } + + /* Fill up the rest of the line with spaces. */ + for (; i < start + len; i++) + { + grub_putchar (' '); + pos++; + } + + /* If the cursor is at the last position, put `>' or a space, + depending on if there are more characters in BUF. */ + if (pos == CMDLINE_WIDTH) + { + if (start + len < llen) + grub_putchar ('>'); + else + grub_putchar (' '); + + pos++; + } + + /* Back to XPOS. */ + if (! (terminal & TERMINAL_DUMB)) + { + if (terminal & TERMINAL_CONSOLE) + { + int y = getxy () & 0xFF; + + gotoxy (xpos, y); + return; + } +# ifdef SUPPORT_SERIAL + else if (terminal & TERMINAL_SERIAL) + { + /* Ugly optimization. */ + if (pos - xpos > 4) + { + grub_printf ("\e[%dD", pos - xpos); + return; + } + } +# endif /* SUPPORT_SERIAL */ + } + + for (i = 0; i < pos - xpos; i++) + grub_putchar ('\b'); } - static void cl_insert (const char *str) + /* Initialize the command-line. */ + void cl_init (void) + { + /* Distinguish us from other lines and error messages! */ + grub_putchar ('\n'); + + /* Print full line and set position here. */ + cl_refresh (1, 0); + } + + /* Insert STR to BUF. */ + void cl_insert (const char *str) { int l = grub_strlen (str); if (llen + l < maxlen) { if (lpos == llen) - { - grub_memmove (buf + lpos, str, l + 1); - cl_setcpos (); - cl_print (buf + lpos, echo_char); - lpos += l; - cl_setcpos (); - } + grub_memmove (buf + lpos, str, l + 1); else { grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1); grub_memmove (buf + lpos, str, l); - cl_setcpos (); - cl_print (buf + lpos, echo_char); - lpos += l; - cl_setcpos (); } + llen += l; + lpos += l; + if (xpos + l >= CMDLINE_WIDTH) + cl_refresh (1, 0); + else if (xpos + l + llen - lpos > CMDLINE_WIDTH) + cl_refresh (0, CMDLINE_WIDTH - xpos); + else + cl_refresh (0, l + llen - lpos); } } + /* Delete COUNT characters in BUF. */ + void cl_delete (int count) + { + grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1); + llen -= count; + + if (xpos + llen + count - lpos > CMDLINE_WIDTH) + cl_refresh (0, CMDLINE_WIDTH - xpos); + else + cl_refresh (0, llen + count - lpos); + } + plen = grub_strlen (prompt); llen = grub_strlen (cmdline); @@ -395,14 +617,10 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, if (ret > 0) { - /* There is more than one candidates, so print + /* There are more than one candidates, so print the list. */ - /* 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); errnum = ERR_NONE; } @@ -417,26 +635,18 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, } break; case 1: /* C-a go to beginning of line */ - lpos = 0; - cl_setcpos (); + cl_backward (lpos); break; case 5: /* C-e go to end of line */ - lpos = llen; - cl_setcpos (); + cl_forward (llen - lpos); break; case 6: /* C-f forward one character */ if (lpos < llen) - { - lpos++; - cl_setcpos (); - } + cl_forward (1); break; case 2: /* C-b backward one character */ if (lpos > 0) - { - lpos--; - cl_setcpos (); - } + cl_backward (1); break; case 21: /* C-u kill to beginning of line */ if (lpos == 0) @@ -444,21 +654,21 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, /* Copy the string being deleted to KILL_BUF. */ grub_memmove (kill_buf, buf, lpos); kill_buf[lpos] = 0; - grub_memmove (buf, buf + lpos, llen - lpos + 1); - lpos = llen - lpos; - cl_setcpos (); - cl_kill_to_end (); - lpos = 0; - cl_setcpos (); - cl_print (buf, echo_char); - cl_setcpos (); + { + /* XXX: Not very clever. */ + + int count = lpos; + + cl_backward (lpos); + cl_delete (count); + } break; case 11: /* C-k kill to end of line */ if (lpos == llen) break; /* Copy the string being deleted to KILL_BUF. */ grub_memmove (kill_buf, buf + lpos, llen - lpos + 1); - cl_kill_to_end (); + cl_delete (llen - lpos); break; case 25: /* C-y yank the kill buffer */ cl_insert (kill_buf); @@ -482,14 +692,10 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, break; } - lpos = 0; - cl_setcpos (); - cl_kill_to_end (); grub_strcpy (buf, p); llen = grub_strlen (buf); lpos = llen; - cl_print (buf, 0); - cl_setcpos (); + cl_refresh (1, 0); } break; case 14: /* C-n fetch the next command */ @@ -509,14 +715,10 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, if (! p) p = cmdline; - lpos = 0; - cl_setcpos (); - cl_kill_to_end (); grub_strcpy (buf, p); llen = grub_strlen (buf); lpos = llen; - cl_print (buf, 0); - cl_setcpos (); + cl_refresh (1, 0); } break; } @@ -532,28 +734,16 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, case 4: /* C-d delete character under cursor */ if (lpos == llen) break; - lpos++; - /* fallthrough is on purpose! */ + cl_delete (1); + break; case 8: /* C-h backspace */ -#ifdef GRUB_UTIL +# ifdef GRUB_UTIL case 127: /* also backspace */ -#endif +# endif if (lpos > 0) { - int i; - grub_memmove (buf + lpos - 1, buf + lpos, llen - lpos + 1); - i = lpos; - lpos = llen - 1; - cl_setcpos (); - putchar (' '); - lpos = i - 1; /* restore lpos and decrement */ - llen--; - cl_setcpos (); - if (lpos != llen) - { - cl_print (buf + lpos, echo_char); - cl_setcpos (); - } + cl_backward (1); + cl_delete (1); } break; default: /* insert printable character into line */ @@ -568,11 +758,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, } } - /* Move the cursor to the end of the command. */ - lpos = llen; - cl_setcpos (); grub_putchar ('\n'); - gotoxy (0, getxy () & 0xff); /* If ECHO_CHAR is NUL, remove the leading spaces. */ lpos = 0; diff --git a/stage2/shared.h b/stage2/shared.h index c4596733a..05ff1b802 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -742,6 +742,8 @@ extern int terminal; #define TERMINAL_CONSOLE (1 << 0) /* keyboard and screen */ #define TERMINAL_SERIAL (1 << 1) /* serial console */ +#define TERMINAL_DUMB (1 << 16) /* dumb terminal */ + void init_builtins (void); void init_config (void); char *skip_to (int after_equal, char *cmdline);