grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

regression in hiddenmenu (Re: [2158] 2009-05-02 Bean <address@hidden>)


From: Robert Millan
Subject: regression in hiddenmenu (Re: [2158] 2009-05-02 Bean <address@hidden>)
Date: Sun, 28 Jun 2009 14:35:26 +0200
User-agent: Mutt/1.5.18 (2008-05-17)

Hi,

This commit accidentally broke "hiddenmenu" functionality
(http://grub.enbug.org/Hiddenmenu).  Instead of displaying the sleep
prompt without clearing the screen, and then clearing the screen and
drawing the menu, it first clears the screen, draws the menu and then
displays the sleep prompt.

I haven't followed much on what this change does;  if I understood
correctly, the scripting engine has been moved to a module (sh.mod),
which due to asciibetical order is processed after normal.mod, which
seems to be the cause for this problem.

I can suggest a few possible solutions:

  - Rename either (kludge! kludge!)

  - Put sh.mod back in kernel.

  - Use runtime dependencies to ensure sh is loaded first.

  - Make normal.mod not start automatically, but instead be started
    with a command from grub.cfg (this could be a new command or just
    triggered by "menuentry").


On Sat, May 02, 2009 at 07:49:35PM +0000, Bean wrote:
> Revision: 2158
>           http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2158
> Author:   bean
> Date:     2009-05-02 19:49:34 +0000 (Sat, 02 May 2009)
> Log Message:
> -----------
> 2009-05-02  Bean  <address@hidden>
> 
>       * conf/common.rmk (grub_script.tab.c): Change normal/parser.y to
>       script/sh/parser.y.
>       (pkglib_MODULES): Add normal.mod and sh.mod.
>       (normal_SOURCES): New variable.
>       (normal_mod_CFLAGS): Likewise.
>       (normal_mod_LDFLAGS): Likewise.
>       (sh_mod_SOURCES): Likewise.
>       (sh_mod_CFLAGS): Likewise.
>       (sh_mod_LDFLAGS): Likewise.
> 
>       * conf/i386-pc.rmk (normal/lexer.c_DEPENDENCIES): Changed to
>       script/sh/lexer.c_DEPENDENCIES.
>       (kernel_img_SOURCES): Remove kern/rescue.c, and kern/reader.c,
>       kern/rescue_reader.c and kern/rescue_parser.c.
>       (kernel_img_HEADERS): Remove rescue.h, add reader.h.
>       (grub_emu_SOURCES): Change source files.
>       (pkglib_MODULES): Remove normal.mod.
>       (normal_SOURCES): Removed.
>       (normal_mod_CFLAGS): Likewise.
>       (normal_mod_LDFLAGS): Likewise.
>       * conf/i386-coreboot.rmk: Likewise.
>       * conf/i386-efi.rmk: Likewise.
>       * conf/i386-ieee1276.rmk: Likewise.
>       * conf/powerpc-ieee1275.rmk: Likewise.
>       * conf/sparc64-ieee1275.rmk: Likewise.
>       * conf/x86_64-efi.rmk: Likewise.
> 
>       * include/grub/command.h (grub_command_execute): New inline function.
> 
>       * include/grub/menu.h (grub_menu_entry): Removed commands field.
> 
>       * include/grub/normal.h: Remove <grub/setjmp.h>.
>       (grub_fs_module_list): Moved to normal/autofs.c.
>       (grub_exit_env): Removed.
>       (grub_command_execute): Likewise.
>       (grub_normal_menu_addentry): Renamed to grub_menu_addentry, removed
>       parameter script.
>       (read_command_list): New function declaration.
>       (read_fs_list): Likewise.
> 
>       * include/parser.h: Include <grub/reader.h>.
>       (grub_parser_split_cmdline): Change type of getline parameter.
>       (grub_parser): New structure.
>       (grub_parser_class): New variable.
>       (grub_parser_execute): New function declaration.
>       (grub_register_rescue_parser): Likewise.
>       (grub_parser_register): New inline function.
>       (grub_parser_unregister): Likewise.
>       (grub_parser_get_current): Likewise.
>       (grub_parser_set_current): Likewise.
> 
>       * include/grub/reader.h: New file.
>       * kern/reader.c: Likewise.
>       * kern/rescue_parser.c: Likewise.
>       * kern/rescue_reader.c: Likewise.
>       * normal/autofs.c: Likewise.
>       * normal/dyncmd.c: Likewise.
> 
>       * include/grub/rescue.h: Removed.
>       * normal/command.h: Likewise.
> 
>       * include/grub/script.h: Moved to ...
>       * include/grub/script_sh.h: ... Moved here.
>       * normal/execute.c: Moved to ...
>       * script/sh/execute.c: ... Moved here.
>       * normal/function.c: Moved to ...
>       * script/sh/function.c: ... Moved here.
>       * normal/lexer.c: Moved to ...
>       * script/sh/lexer.c: ... Moved here.
>       * normal/parser.y: Moved to ...
>       * script/sh/parser.y: ... Moved here.
>       * normal/script.c: Moved to ...
>       * script/sh/script.c: ... Moved here.
> 
>       * normal/main.c: Remove <grub/rescue.h> and <grub/script.h>, include
>       <grub/reader.h>.
>       (grub_exit_env): Removed.
>       (fs_module_list): Moved to normal/autofs.c.
>       (grub_file_getline): Don't handle comment here.
>       (free_menu): Skip removed field entry->commands.
>       (grub_normal_menu_addentry): Removed as grub_menu_entry, removed
>       script parameter.
>       (read_config_file): Removed nested parameter, change getline function.
>       (grub_enter_normal_mode): Removed.
>       (grub_dyncmd_dispatcher): Moved to normal/dyncmd.c.
>       (read_command_list): Likewise.
>       (autoload_fs_module): Moved to normal/autofs.c.
>       (read_fs_list): Likewise.
>       (reader_nested): New variable.
>       (grub_normal_execute): Run parser.sh to switch to sh parser.
>       (grub_cmd_rescue): Removed.
>       (cmd_normal): Removed.
>       (grub_cmd_normal): Unregister itself at the beginning. Don't register
>       rescue command.
>       (grub_cmdline_run): New function.
>       (grub_normal_reader_init): Likewise.
>       (grub_normal_read_line): Likewise.
>       (grub_env_write_pager): Likewise.
>       (cmdline): New variable.
>       (grub_normal_reader): Likewise.
>       (GRUB_MOD_INIT): Register normal reader and set as current, register
>       pager hook, register normal command with grub_register_command_prio,
>       so that it won't show up in command.lst.
>       (GRUB_MOD_FINI): Unregister normal reader, unhook pager, clear
>       grub_fs_autoload_hook.
> 
>       * normal/menu.c: Remove <grub/script.h>, add <grub/command.h>.
>       (grub_menu_execute_entry): Replace grub_script_execute with
>       grub_parser_execute, change parameter to grub_command_execute.
> 
>       * normal/menu_text.c: Remove <grub/script.h>.
> 
>       * normal/menu_entry.c: Remove <grub/script.h>, add <grub/command.h>
>       and <grub/parser.h>.
>       (run): Change editor_getline to use new parser interface. Change
>       parameter to grub_command_execute.
> 
>       * kern/main.c: Remove <grub/rescue.h>, include <grub/command.h>,
>       <grub/reader.h> and <grub/parser.h>.
>       (grub_load_normal_mode): Execute normal command.
>       (grub_main): Call grub_register_core_commands,
>       grub_register_rescue_parser and grub_register_rescue_reader, use
>       grub_reader_loop to enter input loop.
> 
>       * kern/parser.c (grub_parser_spli_cmdline): Change type of getline
>       parameter.
>       (grub_parser_class): New variable.
>       (grub_parser_execute): New function.
> 
>       * loader/i386/multiboot.c: Remove <grub/rescue.h>.
>       * loader/multiboot2.c: Likewise.
>       * loader/sparc64/ieee1275/linux.c: Likewise.
> 
>       * util/grub-emu.c (read_command_list): New dummy function.
> 
> Modified Paths:
> --------------
>     trunk/grub2/ChangeLog
>     trunk/grub2/conf/common.rmk
>     trunk/grub2/conf/i386-coreboot.rmk
>     trunk/grub2/conf/i386-efi.rmk
>     trunk/grub2/conf/i386-ieee1275.rmk
>     trunk/grub2/conf/i386-pc.rmk
>     trunk/grub2/conf/powerpc-ieee1275.rmk
>     trunk/grub2/conf/sparc64-ieee1275.rmk
>     trunk/grub2/conf/x86_64-efi.rmk
>     trunk/grub2/include/grub/command.h
>     trunk/grub2/include/grub/menu.h
>     trunk/grub2/include/grub/normal.h
>     trunk/grub2/include/grub/parser.h
>     trunk/grub2/kern/main.c
>     trunk/grub2/kern/parser.c
>     trunk/grub2/loader/i386/multiboot.c
>     trunk/grub2/loader/multiboot2.c
>     trunk/grub2/loader/sparc64/ieee1275/linux.c
>     trunk/grub2/normal/cmdline.c
>     trunk/grub2/normal/main.c
>     trunk/grub2/normal/menu.c
>     trunk/grub2/normal/menu_entry.c
>     trunk/grub2/normal/menu_text.c
>     trunk/grub2/util/grub-emu.c
> 
> Added Paths:
> -----------
>     trunk/grub2/include/grub/reader.h
>     trunk/grub2/include/grub/script_sh.h
>     trunk/grub2/kern/reader.c
>     trunk/grub2/kern/rescue_parser.c
>     trunk/grub2/kern/rescue_reader.c
>     trunk/grub2/normal/autofs.c
>     trunk/grub2/normal/dyncmd.c
>     trunk/grub2/script/
>     trunk/grub2/script/sh/
>     trunk/grub2/script/sh/execute.c
>     trunk/grub2/script/sh/function.c
>     trunk/grub2/script/sh/lexer.c
>     trunk/grub2/script/sh/main.c
>     trunk/grub2/script/sh/parser.y
>     trunk/grub2/script/sh/script.c
> 
> Removed Paths:
> -------------
>     trunk/grub2/include/grub/rescue.h
>     trunk/grub2/include/grub/script.h
>     trunk/grub2/kern/rescue.c
>     trunk/grub2/normal/command.c
>     trunk/grub2/normal/execute.c
>     trunk/grub2/normal/function.c
>     trunk/grub2/normal/lexer.c
>     trunk/grub2/normal/parser.y
>     trunk/grub2/normal/script.c
> 
> Modified: trunk/grub2/ChangeLog
> ===================================================================
> --- trunk/grub2/ChangeLog     2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/ChangeLog     2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,3 +1,140 @@
> +2009-05-02  Bean  <address@hidden>
> +
> +     * conf/common.rmk (grub_script.tab.c): Change normal/parser.y to
> +     script/sh/parser.y.
> +     (pkglib_MODULES): Add normal.mod and sh.mod.
> +     (normal_SOURCES): New variable.
> +     (normal_mod_CFLAGS): Likewise.
> +     (normal_mod_LDFLAGS): Likewise.
> +     (sh_mod_SOURCES): Likewise.
> +     (sh_mod_CFLAGS): Likewise.
> +     (sh_mod_LDFLAGS): Likewise.
> +
> +     * conf/i386-pc.rmk (normal/lexer.c_DEPENDENCIES): Changed to
> +     script/sh/lexer.c_DEPENDENCIES.
> +     (kernel_img_SOURCES): Remove kern/rescue.c, and kern/reader.c,
> +     kern/rescue_reader.c and kern/rescue_parser.c.
> +     (kernel_img_HEADERS): Remove rescue.h, add reader.h.
> +     (grub_emu_SOURCES): Change source files.
> +     (pkglib_MODULES): Remove normal.mod.
> +     (normal_SOURCES): Removed.
> +     (normal_mod_CFLAGS): Likewise.
> +     (normal_mod_LDFLAGS): Likewise.
> +     * conf/i386-coreboot.rmk: Likewise.
> +     * conf/i386-efi.rmk: Likewise.
> +     * conf/i386-ieee1276.rmk: Likewise.
> +     * conf/powerpc-ieee1275.rmk: Likewise.
> +     * conf/sparc64-ieee1275.rmk: Likewise.
> +     * conf/x86_64-efi.rmk: Likewise.
> +
> +     * include/grub/command.h (grub_command_execute): New inline function.
> +
> +     * include/grub/menu.h (grub_menu_entry): Removed commands field.
> +
> +     * include/grub/normal.h: Remove <grub/setjmp.h>.
> +     (grub_fs_module_list): Moved to normal/autofs.c.
> +     (grub_exit_env): Removed.
> +     (grub_command_execute): Likewise.
> +     (grub_normal_menu_addentry): Renamed to grub_menu_addentry, removed
> +     parameter script.
> +     (read_command_list): New function declaration.
> +     (read_fs_list): Likewise.
> +
> +     * include/parser.h: Include <grub/reader.h>.
> +     (grub_parser_split_cmdline): Change type of getline parameter.
> +     (grub_parser): New structure.
> +     (grub_parser_class): New variable.
> +     (grub_parser_execute): New function declaration.
> +     (grub_register_rescue_parser): Likewise.
> +     (grub_parser_register): New inline function.
> +     (grub_parser_unregister): Likewise.
> +     (grub_parser_get_current): Likewise.
> +     (grub_parser_set_current): Likewise.
> +
> +     * include/grub/reader.h: New file.
> +     * kern/reader.c: Likewise.
> +     * kern/rescue_parser.c: Likewise.
> +     * kern/rescue_reader.c: Likewise.
> +     * normal/autofs.c: Likewise.
> +     * normal/dyncmd.c: Likewise.
> +
> +     * include/grub/rescue.h: Removed.
> +     * normal/command.h: Likewise.
> +
> +     * include/grub/script.h: Moved to ...
> +     * include/grub/script_sh.h: ... Moved here.
> +     * normal/execute.c: Moved to ...
> +     * script/sh/execute.c: ... Moved here.
> +     * normal/function.c: Moved to ...
> +     * script/sh/function.c: ... Moved here.
> +     * normal/lexer.c: Moved to ...
> +     * script/sh/lexer.c: ... Moved here.
> +     * normal/parser.y: Moved to ...
> +     * script/sh/parser.y: ... Moved here.
> +     * normal/script.c: Moved to ...
> +     * script/sh/script.c: ... Moved here.
> +
> +     * normal/main.c: Remove <grub/rescue.h> and <grub/script.h>, include
> +     <grub/reader.h>.
> +     (grub_exit_env): Removed.
> +     (fs_module_list): Moved to normal/autofs.c.
> +     (grub_file_getline): Don't handle comment here.
> +     (free_menu): Skip removed field entry->commands.
> +     (grub_normal_menu_addentry): Removed as grub_menu_entry, removed
> +     script parameter.
> +     (read_config_file): Removed nested parameter, change getline function.
> +     (grub_enter_normal_mode): Removed.
> +     (grub_dyncmd_dispatcher): Moved to normal/dyncmd.c.
> +     (read_command_list): Likewise.
> +     (autoload_fs_module): Moved to normal/autofs.c.
> +     (read_fs_list): Likewise.
> +     (reader_nested): New variable.
> +     (grub_normal_execute): Run parser.sh to switch to sh parser.
> +     (grub_cmd_rescue): Removed.
> +     (cmd_normal): Removed.
> +     (grub_cmd_normal): Unregister itself at the beginning. Don't register
> +     rescue command.
> +     (grub_cmdline_run): New function.
> +     (grub_normal_reader_init): Likewise.
> +     (grub_normal_read_line): Likewise.
> +     (grub_env_write_pager): Likewise.
> +     (cmdline): New variable.
> +     (grub_normal_reader): Likewise.
> +     (GRUB_MOD_INIT): Register normal reader and set as current, register
> +     pager hook, register normal command with grub_register_command_prio,
> +     so that it won't show up in command.lst.
> +     (GRUB_MOD_FINI): Unregister normal reader, unhook pager, clear
> +     grub_fs_autoload_hook.
> +
> +     * normal/menu.c: Remove <grub/script.h>, add <grub/command.h>.
> +     (grub_menu_execute_entry): Replace grub_script_execute with
> +     grub_parser_execute, change parameter to grub_command_execute.
> +
> +     * normal/menu_text.c: Remove <grub/script.h>.
> +
> +     * normal/menu_entry.c: Remove <grub/script.h>, add <grub/command.h>
> +     and <grub/parser.h>.
> +     (run): Change editor_getline to use new parser interface. Change
> +     parameter to grub_command_execute.
> +
> +     * kern/main.c: Remove <grub/rescue.h>, include <grub/command.h>,
> +     <grub/reader.h> and <grub/parser.h>.
> +     (grub_load_normal_mode): Execute normal command.
> +     (grub_main): Call grub_register_core_commands,
> +     grub_register_rescue_parser and grub_register_rescue_reader, use
> +     grub_reader_loop to enter input loop.
> +
> +     * kern/parser.c (grub_parser_spli_cmdline): Change type of getline
> +     parameter.
> +     (grub_parser_class): New variable.
> +     (grub_parser_execute): New function.
> +
> +     * loader/i386/multiboot.c: Remove <grub/rescue.h>.
> +     * loader/multiboot2.c: Likewise.
> +     * loader/sparc64/ieee1275/linux.c: Likewise.
> +
> +     * util/grub-emu.c (read_command_list): New dummy function.
> +
>  2009-05-02  Robert Millan  <address@hidden>
>  
>       * util/deviceiter.c (grub_util_iterate_devices): Increase max drive
> 
> Modified: trunk/grub2/conf/common.rmk
> ===================================================================
> --- trunk/grub2/conf/common.rmk       2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/conf/common.rmk       2009-05-02 19:49:34 UTC (rev 2158)
> @@ -56,8 +56,8 @@
>  endif
>  
>  # For the parser.
> -grub_script.tab.c grub_script.tab.h: normal/parser.y
> -     $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
> +grub_script.tab.c grub_script.tab.h: script/sh/parser.y
> +     $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/script/sh/parser.y
>  DISTCLEANFILES += grub_script.tab.c grub_script.tab.h
>  
>  # For grub-emu.
> @@ -343,7 +343,7 @@
>       loopback.mod fs_uuid.mod configfile.mod echo.mod        \
>       terminfo.mod test.mod blocklist.mod hexdump.mod         \
>       read.mod sleep.mod loadenv.mod crc.mod parttool.mod     \
> -     pcpart.mod memrw.mod boot.mod
> +     pcpart.mod memrw.mod boot.mod normal.mod sh.mod
>  
>  # For boot.mod.
>  boot_mod_SOURCES = commands/boot.c
> @@ -470,6 +470,21 @@
>  memrw_mod_CFLAGS = $(COMMON_CFLAGS)
>  memrw_mod_LDFLAGS = $(COMMON_LDFLAGS)
>  
> +# For normal.mod.
> +normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
> +     normal/autofs.c normal/handler.c \
> +     normal/color.c normal/completion.c normal/datetime.c normal/menu.c \
> +     normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \
> +     normal/misc.c
> +normal_mod_CFLAGS = $(COMMON_CFLAGS)
> +normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For sh.mod.
> +sh_mod_SOURCES = script/sh/main.c script/sh/script.c script/sh/execute.c \
> +     script/sh/function.c script/sh/lexer.c grub_script.tab.c
> +sh_mod_CFLAGS = $(COMMON_CFLAGS)
> +sh_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
>  # Common Video Subsystem specific modules.
>  pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod        
> \
>       png.mod font.mod gfxterm.mod
> 
> Modified: trunk/grub2/conf/i386-coreboot.rmk
> ===================================================================
> --- trunk/grub2/conf/i386-coreboot.rmk        2009-05-02 16:55:35 UTC (rev 
> 2157)
> +++ trunk/grub2/conf/i386-coreboot.rmk        2009-05-02 19:49:34 UTC (rev 
> 2158)
> @@ -5,7 +5,7 @@
>  COMMON_LDFLAGS       = -m32 -nostdlib
>  
>  # Used by various components.  These rules need to precede them.
> -normal/lexer.c_DEPENDENCIES = grub_script.tab.h
> +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h
>  
>  # Images.
>  pkglib_PROGRAMS = kernel.elf
> @@ -16,7 +16,8 @@
>       kern/i386/multiboot_mmap.c \
>       kern/main.c kern/device.c \
>       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
> -     kern/misc.c kern/mm.c kern/rescue.c kern/term.c \
> +     kern/misc.c kern/mm.c kern/reader.c kern/term.c \
> +     kern/rescue_parser.c kern/rescue_reader.c \
>       kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
>       kern/i386/dl.c kern/parser.c kern/partition.c \
>       kern/i386/tsc.c kern/i386/pit.c \
> @@ -28,7 +29,7 @@
>       symlist.c
>  kernel_elf_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
>       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
> -     partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
> +     partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \
>       machine/boot.h machine/console.h machine/init.h \
>       machine/memory.h machine/loader.h list.h handler.h command.h
>  kernel_elf_CFLAGS = $(COMMON_CFLAGS)
> @@ -100,7 +101,7 @@
>  grub_install_SOURCES = util/i386/pc/grub-install.in
>  
>  # Modules.
> -pkglib_MODULES = linux.mod normal.mod multiboot.mod  \
> +pkglib_MODULES = linux.mod multiboot.mod             \
>       aout.mod play.mod serial.mod ata.mod            \
>       memdisk.mod pci.mod lspci.mod reboot.mod        \
>       halt.mod datetime.mod date.mod datehook.mod     \
> @@ -111,27 +112,6 @@
>  linux_mod_CFLAGS = $(COMMON_CFLAGS)
>  linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
>  
> -#
> -# Only arch dependant part of normal.mod will be here. Common part for
> -# all architecures of normal.mod is at start and should be kept at sync
> -# with other makefiles.
> -# 
> -# Please put arch dependant part of normal.mod at the end of list to
> -# keep it simpler to update to different architectures.
> -#
> -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/handler.c      
> \
> -     normal/completion.c normal/datetime.c normal/execute.c          \
> -     normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
> -     normal/menu_text.c                                              \
> -     normal/color.c                                                  \
> -     normal/menu_viewer.c normal/menu_entry.c                        \
> -     normal/misc.c grub_script.tab.c                                 \
> -     normal/script.c                                                 \
> -     normal/i386/setjmp.S
> -normal_mod_CFLAGS = $(COMMON_CFLAGS)
> -normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
> -normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
> -
>  # For reboot.mod.
>  reboot_mod_SOURCES = commands/reboot.c kern/i386/reboot.c
>  reboot_mod_CFLAGS = $(COMMON_CFLAGS)
> 
> Modified: trunk/grub2/conf/i386-efi.rmk
> ===================================================================
> --- trunk/grub2/conf/i386-efi.rmk     2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/conf/i386-efi.rmk     2009-05-02 19:49:34 UTC (rev 2158)
> @@ -5,7 +5,7 @@
>  COMMON_LDFLAGS = -melf_i386 -nostdlib
>  
>  # Used by various components.  These rules need to precede them.
> -normal/lexer.c_DEPENDENCIES = grub_script.tab.h
> +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h
>  
>  # Utilities.
>  bin_UTILITIES = grub-mkimage
> @@ -80,7 +80,7 @@
>  grub_install_SOURCES = util/i386/efi/grub-install.in
>  
>  # Modules.
> -pkglib_MODULES = kernel.mod normal.mod chain.mod appleldr.mod \
> +pkglib_MODULES = kernel.mod chain.mod appleldr.mod \
>       linux.mod halt.mod reboot.mod pci.mod lspci.mod \
>       datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod
>  
> @@ -88,7 +88,8 @@
>  kernel_mod_EXPORTS = no
>  kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \
>       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
> -     kern/misc.c kern/mm.c kern/rescue.c kern/term.c \
> +     kern/misc.c kern/mm.c kern/reader.c kern/term.c \
> +     kern/rescue_parser.c kern/rescue_reader.c \
>       kern/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
>       kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
>       term/efi/console.c disk/efi/efidisk.c \
> @@ -98,7 +99,7 @@
>       kern/generic/millisleep.c
>  kernel_mod_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
>       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
> -     partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
> +     partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \
>       efi/efi.h efi/time.h efi/disk.h list.h handler.h command.h
>  kernel_mod_CFLAGS = $(COMMON_CFLAGS)
>  kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
> @@ -114,27 +115,6 @@
>  kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h 
> genkernsyms.sh
>       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
>  
> -#
> -# Only arch dependant part of normal.mod will be here. Common part for
> -# all architecures of normal.mod is at start and should be kept at sync
> -# with other makefiles.
> -# 
> -# Please put arch dependant part of normal.mod at the end of list to
> -# keep it simpler to update to different architectures.
> -#
> -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/handler.c      
> \
> -     normal/completion.c normal/datetime.c normal/execute.c          \
> -     normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
> -     normal/menu_text.c                                              \
> -     normal/color.c                                                  \
> -     normal/menu_viewer.c normal/menu_entry.c                        \
> -     normal/misc.c grub_script.tab.c                                 \
> -     normal/script.c                                                 \
> -     normal/i386/setjmp.S
> -normal_mod_CFLAGS = $(COMMON_CFLAGS)
> -normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
> -normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
> -
>  # For chain.mod.
>  chain_mod_SOURCES = loader/efi/chainloader.c
>  chain_mod_CFLAGS = $(COMMON_CFLAGS)
> 
> Modified: trunk/grub2/conf/i386-ieee1275.rmk
> ===================================================================
> --- trunk/grub2/conf/i386-ieee1275.rmk        2009-05-02 16:55:35 UTC (rev 
> 2157)
> +++ trunk/grub2/conf/i386-ieee1275.rmk        2009-05-02 19:49:34 UTC (rev 
> 2158)
> @@ -5,7 +5,7 @@
>  COMMON_LDFLAGS       = -nostdlib -static -lgcc
>  
>  # Used by various components.  These rules need to precede them.
> -normal/lexer.c_DEPENDENCIES = grub_script.tab.h
> +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h
>  
>  # Images.
>  pkglib_PROGRAMS = kernel.elf
> @@ -17,7 +17,8 @@
>       kern/ieee1275/cmain.c kern/ieee1275/openfw.c \
>       kern/main.c kern/device.c \
>       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
> -     kern/misc.c kern/mm.c kern/rescue.c kern/term.c \
> +     kern/misc.c kern/mm.c kern/reader.c kern/term.c \
> +     kern/rescue_parser.c kern/rescue_reader.c \
>       kern/i386/dl.c kern/parser.c kern/partition.c \
>       kern/env.c \
>       kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
> @@ -28,7 +29,7 @@
>       symlist.c
>  kernel_elf_HEADERS = cache.h device.h disk.h dl.h elf.h elfload.h \
>       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
> -     partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
> +     partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \
>       ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h \
>       list.h handler.h command.h
>  kernel_elf_CFLAGS = $(COMMON_CFLAGS)
> @@ -101,32 +102,11 @@
>  grub_install_SOURCES = util/ieee1275/grub-install.in
>  
>  # Modules.
> -pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod          \
> -     multiboot.mod aout.mod serial.mod linux.mod     \
> +pkglib_MODULES = halt.mod reboot.mod suspend.mod             \
> +     multiboot.mod aout.mod serial.mod linux.mod             \
>       nand.mod memdisk.mod pci.mod lspci.mod datetime.mod     \
>       date.mod datehook.mod lsmmap.mod
>  
> -#
> -# Only arch dependant part of normal.mod will be here. Common part for
> -# all architecures of normal.mod is at start and should be kept at sync
> -# with other makefiles.
> -# 
> -# Please put arch dependant part of normal.mod at the end of list to
> -# keep it simpler to update to different architectures.
> -#
> -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/handler.c      
> \
> -     normal/completion.c normal/datetime.c normal/execute.c          \
> -     normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
> -     normal/menu_text.c                                              \
> -     normal/color.c                                                  \
> -     normal/menu_viewer.c normal/menu_entry.c                        \
> -     normal/misc.c grub_script.tab.c                                 \
> -     normal/script.c                                                 \
> -     normal/i386/setjmp.S
> -normal_mod_CFLAGS = $(COMMON_CFLAGS)
> -normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
> -normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
> -
>  # For multiboot.mod.
>  multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \
>                       loader/i386/multiboot_helper.S \
> 
> Modified: trunk/grub2/conf/i386-pc.rmk
> ===================================================================
> --- trunk/grub2/conf/i386-pc.rmk      2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/conf/i386-pc.rmk      2009-05-02 19:49:34 UTC (rev 2158)
> @@ -7,7 +7,7 @@
>  COMMON_LDFLAGS = -m32 -nostdlib
>  
>  # Used by various components.  These rules need to precede them.
> -normal/lexer.c_DEPENDENCIES = grub_script.tab.h
> +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h
>  
>  # Images.
>  pkglib_IMAGES = boot.img diskboot.img kernel.img pxeboot.img lnxboot.img \
> @@ -46,7 +46,8 @@
>  # For kernel.img.
>  kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \
>       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
> -     kern/misc.c kern/mm.c kern/rescue.c kern/term.c \
> +     kern/misc.c kern/mm.c kern/reader.c kern/term.c \
> +     kern/rescue_parser.c kern/rescue_reader.c \
>       kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
>       kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
>       kern/parser.c kern/partition.c \
> @@ -58,7 +59,7 @@
>       symlist.c
>  kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
>       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
> -     partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
> +     partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \
>       machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
>       machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \
>       machine/kernel.h machine/pxe.h list.h handler.h command.h
> @@ -131,16 +132,17 @@
>       io/gzio.c                                                       \
>       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
>       kern/err.c kern/list.c kern/handler.c                           \
> -     kern/command.c kern/corecmd.c commands/extcmd.c                 \
> -     normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
> -     commands/boot.c kern/main.c kern/misc.c kern/parser.c           \
> -     grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
> -     lib/arg.c normal/cmdline.c normal/command.c normal/datetime.c   \
> -     normal/function.c normal/handler.c      \
> +     kern/command.c kern/corecmd.c commands/extcmd.c kern/file.c     \
> +     kern/fs.c commands/boot.c kern/main.c kern/misc.c kern/parser.c \
> +     kern/partition.c kern/reader.c kern/term.c                      \
> +     kern/rescue_reader.c kern/rescue_parser.c                       \
> +     lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c      \
> +     normal/handler.c normal/autofs.c                                \
>       normal/completion.c normal/main.c normal/color.c                \
>       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
>       normal/menu_text.c                                              \
> -     normal/misc.c normal/script.c                                   \
> +     script/sh/main.c script/sh/execute.c script/sh/function.c       \
> +     script/sh/lexer.c script/sh/script.c grub_script.tab.c          \
>       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
>       partmap/acorn.c partmap/gpt.c                                   \
>       \
> @@ -176,7 +178,7 @@
>  # For grub-mkrescue.
>  grub_mkrescue_SOURCES = util/i386/pc/grub-mkrescue.in
>  
> -pkglib_MODULES = biosdisk.mod chain.mod normal.mod \
> +pkglib_MODULES = biosdisk.mod chain.mod \
>       multiboot.mod reboot.mod halt.mod       \
>       vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod     \
>       ata.mod vga.mod memdisk.mod pci.mod lspci.mod   \
> @@ -204,27 +206,6 @@
>  linux_mod_CFLAGS = $(COMMON_CFLAGS)
>  linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
>  
> -#
> -# Only arch dependant part of normal.mod will be here. Common part for
> -# all architecures of normal.mod is at start and should be kept at sync
> -# with other makefiles.
> -# 
> -# Please put arch dependant part of normal.mod at the end of list to
> -# keep it simpler to update to different architectures.
> -#
> -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/datetime.c \
> -     normal/completion.c normal/execute.c normal/handler.c           \
> -     normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
> -     normal/menu_text.c                                              \
> -     normal/color.c                                                  \
> -     normal/menu_viewer.c normal/menu_entry.c                        \
> -     normal/misc.c grub_script.tab.c                                 \
> -     normal/script.c                                                 \
> -     normal/i386/setjmp.S
> -normal_mod_CFLAGS = $(COMMON_CFLAGS)
> -normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
> -normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
> -
>  # For reboot.mod.
>  reboot_mod_SOURCES = commands/reboot.c
>  reboot_mod_CFLAGS = $(COMMON_CFLAGS)
> 
> Modified: trunk/grub2/conf/powerpc-ieee1275.rmk
> ===================================================================
> --- trunk/grub2/conf/powerpc-ieee1275.rmk     2009-05-02 16:55:35 UTC (rev 
> 2157)
> +++ trunk/grub2/conf/powerpc-ieee1275.rmk     2009-05-02 19:49:34 UTC (rev 
> 2158)
> @@ -6,7 +6,7 @@
>  COMMON_LDFLAGS += -nostdlib
>  
>  # Used by various components.  These rules need to precede them.
> -normal/lexer.c_DEPENDENCIES = grub_script.tab.h
> +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h
>  
>  # Images.
>  
> @@ -14,7 +14,7 @@
>  DEFSYMFILES += kernel_syms.lst
>  
>  kernel_elf_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
> -     env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h rescue.h \
> +     env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h reader.h \
>       symbol.h term.h time.h types.h powerpc/libgcc.h loader.h partition.h \
>       pc_partition.h ieee1275/ieee1275.h machine/kernel.h handler.h list.h \
>       command.h
> @@ -82,7 +82,8 @@
>  kernel_elf_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \
>       kern/ieee1275/ieee1275.c kern/main.c kern/device.c              \
>       kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
> -     kern/misc.c kern/mm.c kern/rescue.c kern/term.c         \
> +     kern/misc.c kern/mm.c kern/reader.c kern/term.c         \
> +     kern/rescue_parser.c kern/rescue_reader.c \
>       kern/list.c kern/handler.c kern/command.c kern/corecmd.c        \
>       kern/ieee1275/init.c                                            \
>       kern/ieee1275/mmap.c                                            \
> @@ -109,7 +110,6 @@
>  # Modules.
>  pkglib_MODULES = halt.mod \
>       linux.mod \
> -     normal.mod \
>       reboot.mod \
>       suspend.mod \
>          multiboot.mod \
> @@ -121,27 +121,6 @@
>  linux_mod_CFLAGS = $(COMMON_CFLAGS)
>  linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
>  
> -#
> -# Only arch dependant part of normal.mod will be here. Common part for
> -# all architecures of normal.mod is at start and should be kept at sync
> -# with other makefiles.
> -# 
> -# Please put arch dependant part of normal.mod at the end of list to
> -# keep it simpler to update to different architectures.
> -#
> -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/datetime.c \
> -     normal/completion.c normal/execute.c normal/handler.c           \
> -     normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
> -     normal/menu_text.c                                              \
> -     normal/color.c                                                  \
> -     normal/menu_viewer.c normal/menu_entry.c                        \
> -     normal/misc.c grub_script.tab.c                                 \
> -     normal/script.c                                                 \
> -     normal/powerpc/setjmp.S
> -normal_mod_CFLAGS = $(COMMON_CFLAGS)
> -normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
> -normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
> -
>  # For suspend.mod
>  suspend_mod_SOURCES = commands/ieee1275/suspend.c
>  suspend_mod_CFLAGS = $(COMMON_CFLAGS)
> 
> Modified: trunk/grub2/conf/sparc64-ieee1275.rmk
> ===================================================================
> --- trunk/grub2/conf/sparc64-ieee1275.rmk     2009-05-02 16:55:35 UTC (rev 
> 2157)
> +++ trunk/grub2/conf/sparc64-ieee1275.rmk     2009-05-02 19:49:34 UTC (rev 
> 2158)
> @@ -6,7 +6,7 @@
>  COMMON_LDFLAGS = -melf64_sparc -nostdlib -mno-relax
>  
>  # Used by various components.  These rules need to precede them.
> -normal/lexer.c_DEPENDENCIES = grub_script.tab.h
> +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h
>  
>  # Images.
>  pkglib_IMAGES = boot.img diskboot.img kernel.img
> @@ -28,14 +28,15 @@
>  
>  kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
>       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
> -     partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
> +     partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \
>       list.h handler.h command.h \
>       sparc64/libgcc.h ieee1275/ieee1275.h machine/kernel.h \
>       sparc64/ieee1275/ieee1275.h
>  kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c      
> \
>       kern/ieee1275/ieee1275.c kern/main.c kern/device.c              \
>       kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
> -     kern/misc.c kern/mm.c kern/rescue.c kern/term.c                 \
> +     kern/misc.c kern/mm.c kern/reader.c kern/term.c                 \
> +     kern/rescue_parser.c kern/rescue_reader.c \
>       kern/list.c kern/handler.c kern/command.c kern/corecmd.c        \
>       kern/sparc64/ieee1275/ieee1275.c                                \
>       kern/sparc64/ieee1275/init.c                                    \
> @@ -142,7 +143,6 @@
>  # Modules.
>  pkglib_MODULES = halt.mod \
>       linux.mod \
> -     normal.mod \
>       reboot.mod \
>       memdisk.mod \
>       lsmmap.mod
> @@ -152,27 +152,6 @@
>  linux_mod_CFLAGS = $(COMMON_CFLAGS)
>  linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
>  
> -#
> -# Only arch dependant part of normal.mod will be here. Common part for
> -# all architecures of normal.mod is at start and should be kept at sync
> -# with other makefiles.
> -# 
> -# Please put arch dependant part of normal.mod at the end of list to
> -# keep it simpler to update to different architectures.
> -#
> -normal_mod_SOURCES = lib/arg.c normal/cmdline.c normal/command.c     \
> -     normal/datetime.c normal/completion.c normal/execute.c          \
> -     normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
> -     normal/handler.c normal/menu_text.c                             \
> -     normal/color.c                                                  \
> -     normal/menu_viewer.c normal/menu_entry.c                        \
> -     normal/misc.c grub_script.tab.c                                 \
> -     normal/script.c                                                 \
> -     normal/sparc64/setjmp.S
> -normal_mod_CFLAGS = $(COMMON_CFLAGS)
> -normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
> -normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
> -
>  # For reboot.mod.
>  reboot_mod_SOURCES = commands/reboot.c
>  reboot_mod_CFLAGS = $(COMMON_CFLAGS)
> 
> Modified: trunk/grub2/conf/x86_64-efi.rmk
> ===================================================================
> --- trunk/grub2/conf/x86_64-efi.rmk   2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/conf/x86_64-efi.rmk   2009-05-02 19:49:34 UTC (rev 2158)
> @@ -5,10 +5,7 @@
>  COMMON_LDFLAGS = -melf_x86_64 -nostdlib
>  
>  # Used by various components.  These rules need to precede them.
> -normal/execute.c_DEPENDENCIES = grub_script.tab.h
> -normal/command.c_DEPENDENCIES = grub_script.tab.h
> -normal/function.c_DEPENDENCIES = grub_script.tab.h
> -normal/lexer.c_DEPENDENCIES = grub_script.tab.h
> +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h
>  
>  # Utilities.
>  bin_UTILITIES = grub-mkimage
> @@ -81,7 +78,7 @@
>  grub_install_SOURCES = util/i386/efi/grub-install.in
>  
>  # Modules.
> -pkglib_MODULES = kernel.mod normal.mod chain.mod appleldr.mod \
> +pkglib_MODULES = kernel.mod chain.mod appleldr.mod \
>       halt.mod reboot.mod linux.mod pci.mod lspci.mod \
>       datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod
>  
> @@ -90,7 +87,8 @@
>  kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \
>       kern/main.c kern/device.c \
>       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
> -     kern/misc.c kern/mm.c kern/rescue.c kern/term.c \
> +     kern/misc.c kern/mm.c kern/reader.c kern/term.c \
> +     kern/rescue_parser.c kern/rescue_reader.c \
>       kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
>       kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
>       kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
> @@ -99,7 +97,7 @@
>       term/efi/console.c disk/efi/efidisk.c
>  kernel_mod_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
>       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
> -     partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
> +     partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \
>       efi/efi.h efi/time.h efi/disk.h machine/loader.h list.h handler.h \
>       command.h
>  kernel_mod_CFLAGS = $(COMMON_CFLAGS)
> @@ -116,27 +114,6 @@
>  kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h 
> genkernsyms.sh
>       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
>  
> -#
> -# Only arch dependant part of normal.mod will be here. Common part for
> -# all architecures of normal.mod is at start and should be kept at sync
> -# with other makefiles.
> -# 
> -# Please put arch dependant part of normal.mod at the end of list to
> -# keep it simpler to update to different architectures.
> -#
> -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/handler.c      
> \
> -     normal/completion.c normal/datetime.c normal/execute.c          \
> -     normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
> -     normal/menu_text.c                                              \
> -     normal/color.c                                                  \
> -     normal/menu_viewer.c normal/menu_entry.c                        \
> -     normal/misc.c grub_script.tab.c                                 \
> -     normal/script.c                                                 \
> -     normal/x86_64/setjmp.S
> -normal_mod_CFLAGS = $(COMMON_CFLAGS)
> -normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
> -normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
> -
>  # For chain.mod.
>  chain_mod_SOURCES = loader/efi/chainloader.c
>  chain_mod_CFLAGS = $(COMMON_CFLAGS)
> @@ -197,5 +174,4 @@
>  fixvideo_mod_CFLAGS = $(COMMON_CFLAGS)
>  fixvideo_mod_LDFLAGS = $(COMMON_LDFLAGS)
>  
> -include $(srcdir)/conf/i386.mk
>  include $(srcdir)/conf/common.mk
> 
> Modified: trunk/grub2/include/grub/command.h
> ===================================================================
> --- trunk/grub2/include/grub/command.h        2009-05-02 16:55:35 UTC (rev 
> 2157)
> +++ trunk/grub2/include/grub/command.h        2009-05-02 19:49:34 UTC (rev 
> 2158)
> @@ -106,6 +106,15 @@
>    return grub_named_list_find (GRUB_AS_NAMED_LIST (grub_command_list), name);
>  }
>  
> +static inline grub_err_t
> +grub_command_execute (const char *name, int argc, char **argv)
> +{
> +  grub_command_t cmd;
> +
> +  cmd = grub_command_find (name);
> +  return (cmd) ? cmd->func (cmd, argc, argv) : GRUB_ERR_FILE_NOT_FOUND;
> +}
> +
>  static inline int
>  grub_command_iterate (int (*func) (grub_command_t))
>  {
> 
> Modified: trunk/grub2/include/grub/menu.h
> ===================================================================
> --- trunk/grub2/include/grub/menu.h   2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/include/grub/menu.h   2009-05-02 19:49:34 UTC (rev 2158)
> @@ -38,9 +38,6 @@
>       E.classes->next is the first class if it is not NULL.  */
>    struct grub_menu_entry_class *classes;
>  
> -  /* The commands associated with this menu entry.  */
> -  struct grub_script *commands;
> -
>    /* The sourcecode of the menu entry, used by the editor.  */
>    const char *sourcecode;
>  
> 
> Modified: trunk/grub2/include/grub/normal.h
> ===================================================================
> --- trunk/grub2/include/grub/normal.h 2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/include/grub/normal.h 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -20,7 +20,6 @@
>  #ifndef GRUB_NORMAL_HEADER
>  #define GRUB_NORMAL_HEADER   1
>  
> -#include <grub/setjmp.h>
>  #include <grub/symbol.h>
>  #include <grub/err.h>
>  #include <grub/env.h>
> @@ -42,17 +41,6 @@
>    };
>  typedef enum grub_completion_type grub_completion_type_t;
>  
> -/* This is used to store the names of filesystem modules for auto-loading.  
> */
> -struct grub_fs_module_list
> -{
> -  char *name;
> -  struct grub_fs_module_list *next;
> -};
> -typedef struct grub_fs_module_list *grub_fs_module_list_t;
> -
> -/* To exit from the normal mode.  */
> -extern grub_jmp_buf grub_exit_env;
> -
>  extern struct grub_menu_viewer grub_normal_text_menu_viewer;
>  
>  /* Callback structure menu viewers can use to provide user feedback when
> @@ -86,19 +74,14 @@
>  grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
>  int grub_menu_get_timeout (void);
>  void grub_menu_set_timeout (int timeout);
> -void grub_cmdline_run (int nested);
>  int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
>                     int echo_char, int readline);
>  grub_err_t grub_set_history (int newsize);
> -int grub_command_execute (char *cmdline, int interactive);
>  void grub_normal_init_page (void);
>  void grub_menu_init_page (int nested, int edit);
>  char *grub_normal_do_completion (char *buf, int *restore,
>                                void (*hook) (const char *item, 
> grub_completion_type_t type, int count));
>  grub_err_t grub_normal_print_device_info (const char *name);
> -grub_err_t grub_normal_menu_addentry (int argc, const char **args,
> -                                   struct grub_script *script,
> -                                   const char *sourcecode);
>  char *grub_env_write_color_normal (struct grub_env_var *var, const char 
> *val);
>  char *grub_env_write_color_highlight (struct grub_env_var *var, const char 
> *val);
>  void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
> @@ -107,6 +90,11 @@
>  char *grub_file_getline (grub_file_t file);
>  void read_handler_list (void);
>  void free_handler_list (void);
> +void read_command_list (void);
> +void read_fs_list (void);
> +void grub_cmdline_run (int nested);
> +grub_err_t grub_menu_addentry (int argc, const char **args,
> +                            const char *sourcecode);
>  
>  #ifdef GRUB_UTIL
>  void grub_normal_init (void);
> 
> Modified: trunk/grub2/include/grub/parser.h
> ===================================================================
> --- trunk/grub2/include/grub/parser.h 2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/include/grub/parser.h 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,7 +1,7 @@
>  /* parser.h - prototypes for the command line parser.  */
>  /*
>   *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2005,2007  Free Software Foundation, Inc.
> + *  Copyright (C) 2005,2007,2009  Free Software Foundation, Inc.
>   *
>   *  GRUB is free software: you can redistribute it and/or modify
>   *  it under the terms of the GNU General Public License as published by
> @@ -22,6 +22,7 @@
>  
>  #include <grub/types.h>
>  #include <grub/err.h>
> +#include <grub/reader.h>
>  
>  /* All the states for the command line.  */
>  typedef enum
> @@ -61,7 +62,56 @@
>  
>  grub_err_t
>  EXPORT_FUNC (grub_parser_split_cmdline) (const char *cmdline,
> -                                      grub_err_t (*getline) (char **),
> +                                      grub_reader_getline_t getline,
>                                        int *argc, char ***argv);
>  
> +struct grub_parser
> +{
> +  /* The next parser.  */
> +  struct grub_parser *next;
> +
> +  /* The parser name.  */
> +  const char *name;
> +
> +  /* Initialize the parser.  */
> +  grub_err_t (*init) (void);
> +
> +  /* Clean up the parser.  */
> +  grub_err_t (*fini) (void);
> +
> +  grub_err_t (*parse_line) (char *line, grub_reader_getline_t getline);
> +};
> +typedef struct grub_parser *grub_parser_t;
> +
> +extern struct grub_handler_class EXPORT_VAR(grub_parser_class);
> +grub_err_t EXPORT_FUNC(grub_parser_execute) (char *source);
> +
> +static inline void
> +grub_parser_register (const char *name __attribute__ ((unused)),
> +                   grub_parser_t parser)
> +{
> +  grub_handler_register (&grub_parser_class, GRUB_AS_HANDLER (parser));
> +}
> +
> +static inline void
> +grub_parser_unregister (grub_parser_t parser)
> +{
> +  grub_handler_unregister (&grub_parser_class, GRUB_AS_HANDLER (parser));
> +}
> +
> +static inline grub_parser_t
> +grub_parser_get_current (void)
> +{
> +  return (grub_parser_t) grub_parser_class.cur_handler;
> +}
> +
> +static inline grub_err_t
> +grub_parser_set_current (grub_parser_t parser)
> +{
> +  return grub_handler_set_current (&grub_parser_class,
> +                                GRUB_AS_HANDLER (parser));
> +}
> +
> +void grub_register_rescue_parser (void);
> +
>  #endif /* ! GRUB_PARSER_HEADER */
> 
> Added: trunk/grub2/include/grub/reader.h
> ===================================================================
> --- trunk/grub2/include/grub/reader.h                         (rev 0)
> +++ trunk/grub2/include/grub/reader.h 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,79 @@
> +/* reader.h - prototypes for command line reader.  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_READER_HEADER
> +#define GRUB_READER_HEADER   1
> +
> +#include <grub/types.h>
> +#include <grub/err.h>
> +#include <grub/handler.h>
> +
> +typedef grub_err_t (*grub_reader_getline_t) (char **, int);
> +
> +struct grub_reader
> +{
> +  /* The next reader.  */
> +  struct grub_parser *next;
> +
> +  /* The reader name.  */
> +  const char *name;
> +
> +  /* Initialize the reader.  */
> +  grub_err_t (*init) (void);
> +
> +  /* Clean up the reader.  */
> +  grub_err_t (*fini) (void);
> +
> +  grub_reader_getline_t read_line;
> +};
> +typedef struct grub_reader *grub_reader_t;
> +
> +extern struct grub_handler_class EXPORT_VAR(grub_reader_class);
> +
> +grub_err_t EXPORT_FUNC(grub_reader_loop) (grub_reader_getline_t getline);
> +
> +static inline void
> +grub_reader_register (const char *name __attribute__ ((unused)),
> +                   grub_reader_t reader)
> +{
> +  grub_handler_register (&grub_reader_class, GRUB_AS_HANDLER (reader));
> +}
> +
> +static inline void
> +grub_reader_unregister (grub_reader_t reader)
> +{
> +  grub_handler_unregister (&grub_reader_class, GRUB_AS_HANDLER (reader));
> +}
> +
> +static inline grub_reader_t
> +grub_reader_get_current (void)
> +{
> +  return (grub_reader_t) grub_reader_class.cur_handler;
> +}
> +
> +static inline grub_err_t
> +grub_reader_set_current (grub_reader_t reader)
> +{
> +  return grub_handler_set_current (&grub_reader_class,
> +                                GRUB_AS_HANDLER (reader));
> +}
> +
> +void grub_register_rescue_reader (void);
> +
> +#endif /* ! GRUB_READER_HEADER */
> 
> Deleted: trunk/grub2/include/grub/rescue.h
> ===================================================================
> --- trunk/grub2/include/grub/rescue.h 2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/include/grub/rescue.h 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,27 +0,0 @@
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2002,2007  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#ifndef GRUB_RESCUE_HEADER
> -#define GRUB_RESCUE_HEADER   1
> -
> -#include <grub/symbol.h>
> -
> -/* Enter rescue mode.  */
> -void grub_enter_rescue_mode (void);
> -
> -#endif /* ! GRUB_RESCUE_HEADER */
> 
> Deleted: trunk/grub2/include/grub/script.h
> ===================================================================
> --- trunk/grub2/include/grub/script.h 2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/include/grub/script.h 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,287 +0,0 @@
> -/* script.h  */
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2005,2007,2009  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#ifndef GRUB_SCRIPT_HEADER
> -#define GRUB_SCRIPT_HEADER   1
> -
> -#include <grub/types.h>
> -#include <grub/err.h>
> -#include <grub/parser.h>
> -
> -struct grub_script_mem;
> -
> -/* The generic header for each scripting command or structure.  */
> -struct grub_script_cmd
> -{
> -  /* This function is called to execute the command.  */
> -  grub_err_t (*exec) (struct grub_script_cmd *cmd);
> -
> -  /* The next command.  This can be used by the parent to form a chain
> -     of commands.  */
> -  struct grub_script_cmd *next;
> -};
> -
> -struct grub_script
> -{
> -  struct grub_script_mem *mem;
> -  struct grub_script_cmd *cmd;
> -};
> -
> -typedef enum
> -{
> -  GRUB_SCRIPT_ARG_TYPE_STR,
> -  GRUB_SCRIPT_ARG_TYPE_VAR
> -} grub_script_arg_type_t;
> -
> -/* A part of an argument.  */
> -struct grub_script_arg
> -{
> -  grub_script_arg_type_t type;
> -
> -  char *str;
> -
> -  /* Next argument part.  */
> -  struct grub_script_arg *next;
> -};
> -
> -/* A complete argument.  It consists of a list of one or more `struct
> -   grub_script_arg's.  */
> -struct grub_script_arglist
> -{
> -  struct grub_script_arglist *next;
> -  struct grub_script_arg *arg;
> -  /* Only stored in the first link.  */
> -  int argcount;
> -};
> -
> -/* A single command line.  */
> -struct grub_script_cmdline
> -{
> -  struct grub_script_cmd cmd;
> -
> -  /* The arguments for this command.  */
> -  struct grub_script_arglist *arglist;
> -
> -  /* The command name of this command.  XXX: Perhaps an argument
> -     should be used for this so we can use variables as command
> -     name.  */
> -  char *cmdname;
> -};
> -
> -/* A block of commands, this can be used to group commands.  */
> -struct grub_script_cmdblock
> -{
> -  struct grub_script_cmd cmd;
> -
> -  /* A chain of commands.  */
> -  struct grub_script_cmd *cmdlist;
> -};
> -
> -/* An if statement.  */
> -struct grub_script_cmdif
> -{
> -  struct grub_script_cmd cmd;
> -
> -  /* The command used to check if the 'if' is true or false.  */
> -  struct grub_script_cmd *exec_to_evaluate;
> -
> -  /* The code executed in case the result of 'if' was true.  */
> -  struct grub_script_cmd *exec_on_true;
> -
> -  /* The code executed in case the result of 'if' was false.  */
> -  struct grub_script_cmd *exec_on_false;
> -};
> -
> -/* A menu entry generate statement.  */
> -struct grub_script_cmd_menuentry
> -{
> -  struct grub_script_cmd cmd;
> -
> -  /* The arguments for this menu entry.  */
> -  struct grub_script_arglist *arglist;
> -
> -  /* The sourcecode the entry will be generated from.  */
> -  const char *sourcecode;
> -
> -  /* Options.  XXX: Not used yet.  */
> -  int options;
> -};
> -
> -/* State of the lexer as passed to the lexer.  */
> -struct grub_lexer_param
> -{
> -  /* Set to 0 when the lexer is done.  */
> -  int done;
> -
> -  /* State of the state machine.  */
> -  grub_parser_state_t state;
> -
> -  /* Function used by the lexer to get a new line when more input is
> -     expected, but not available.  */
> -  grub_err_t (*getline) (char **);
> -
> -  /* A reference counter.  If this is >0 it means that the parser
> -     expects more tokens and `getline' should be called to fetch more.
> -     Otherwise the lexer can stop processing if the current buffer is
> -     depleted.  */
> -  int refs;
> -
> -  /* The character stream that has to be parsed.  */
> -  char *script;
> -  char *newscript; /* XXX */
> -
> -  /* While walking through the databuffer, `record' the characters to
> -     this other buffer.  It can be used to edit the menu entry at a
> -     later moment.  */
> -
> -  /* If true, recording is enabled.  */
> -  int record;
> -
> -  /* Points to the recording.  */
> -  char *recording;
> -
> -  /* index in the RECORDING.  */ 
> -  int recordpos;
> -
> -  /* Size of RECORDING.  */
> -  int recordlen;
> -};
> -
> -/* State of the parser as passes to the parser.  */
> -struct grub_parser_param
> -{
> -  /* Keep track of the memory allocated for this specific
> -     function.  */
> -  struct grub_script_mem *func_mem;
> -
> -  /* When set to 0, no errors have occured during parsing.  */
> -  int err;
> -
> -  /* The memory that was used while parsing and scanning.  */
> -  struct grub_script_mem *memused;
> -
> -  /* The result of the parser.  */
> -  struct grub_script_cmd *parsed;
> -
> -  struct grub_lexer_param *lexerstate;
> -};
> -
> -struct grub_script_arglist *
> -grub_script_create_arglist (struct grub_parser_param *state);
> -
> -struct grub_script_arglist *
> -grub_script_add_arglist (struct grub_parser_param *state,
> -                      struct grub_script_arglist *list,
> -                      struct grub_script_arg *arg);
> -struct grub_script_cmd *
> -grub_script_create_cmdline (struct grub_parser_param *state,
> -                         char *cmdname,
> -                         struct grub_script_arglist *arglist);
> -struct grub_script_cmd *
> -grub_script_create_cmdblock (struct grub_parser_param *state);
> -
> -struct grub_script_cmd *
> -grub_script_create_cmdif (struct grub_parser_param *state,
> -                       struct grub_script_cmd *exec_to_evaluate,
> -                       struct grub_script_cmd *exec_on_true,
> -                       struct grub_script_cmd *exec_on_false);
> -
> -struct grub_script_cmd *
> -grub_script_create_cmdmenu (struct grub_parser_param *state,
> -                         struct grub_script_arglist *arglist,
> -                         char *sourcecode,
> -                         int options);
> -
> -struct grub_script_cmd *
> -grub_script_add_cmd (struct grub_parser_param *state,
> -                  struct grub_script_cmdblock *cmdblock,
> -                  struct grub_script_cmd *cmd);
> -struct grub_script_arg *
> -grub_script_arg_add (struct grub_parser_param *state,
> -                  struct grub_script_arg *arg,
> -                  grub_script_arg_type_t type, char *str);
> -
> -struct grub_script *grub_script_parse (char *script,
> -                                    grub_err_t (*getline) (char **));
> -void grub_script_free (struct grub_script *script);
> -struct grub_script *grub_script_create (struct grub_script_cmd *cmd,
> -                                     struct grub_script_mem *mem);
> -
> -struct grub_lexer_param *grub_script_lexer_init (char *s,
> -                                              grub_err_t (*getline) (char 
> **));
> -void grub_script_lexer_ref (struct grub_lexer_param *);
> -void grub_script_lexer_deref (struct grub_lexer_param *);
> -void grub_script_lexer_record_start (struct grub_lexer_param *);
> -char *grub_script_lexer_record_stop (struct grub_lexer_param *);
> -
> -/* Functions to track allocated memory.  */
> -struct grub_script_mem *grub_script_mem_record (struct grub_parser_param 
> *state);
> -struct grub_script_mem *grub_script_mem_record_stop (struct 
> grub_parser_param *state, 
> -                                                  struct grub_script_mem 
> *restore);
> -void *grub_script_malloc (struct grub_parser_param *state, grub_size_t size);
> -
> -/* Functions used by bison.  */
> -union YYSTYPE;
> -int grub_script_yylex (union YYSTYPE *, struct grub_parser_param *);
> -int grub_script_yyparse (struct grub_parser_param *);
> -void grub_script_yyerror (struct grub_parser_param *, char const *);
> -
> -/* Commands to execute, don't use these directly.  */
> -grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd);
> -grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd);
> -grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd);
> -grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd);
> -
> -/* Execute any GRUB pre-parsed command or script.  */
> -grub_err_t grub_script_execute (struct grub_script *script);
> -
> -/* This variable points to the parsed command.  This is used to
> -   communicate with the bison code.  */
> -extern struct grub_script_cmd *grub_script_parsed;
> -
> -
> -
> -/* The function description.  */
> -struct grub_script_function
> -{
> -  /* The name.  */
> -  char *name;
> -
> -  /* The script function.  */
> -  struct grub_script *func;
> -
> -  /* The flags.  */
> -  unsigned flags;
> -
> -  /* The next element.  */
> -  struct grub_script_function *next;
> -
> -  int references;
> -};
> -typedef struct grub_script_function *grub_script_function_t;
> -
> -grub_script_function_t grub_script_function_create (char *functionname,
> -                                                 struct grub_script *cmd);
> -void grub_script_function_remove (const char *name);
> -grub_script_function_t grub_script_function_find (char *functionname);
> -int grub_script_function_iterate (int (*iterate) (grub_script_function_t));
> -int grub_script_function_call (grub_script_function_t func,
> -                            int argc, char **args);
> -
> -#endif /* ! GRUB_SCRIPT_HEADER */
> 
> Copied: trunk/grub2/include/grub/script_sh.h (from rev 2157, 
> trunk/grub2/include/grub/script.h)
> ===================================================================
> --- trunk/grub2/include/grub/script_sh.h                              (rev 0)
> +++ trunk/grub2/include/grub/script_sh.h      2009-05-02 19:49:34 UTC (rev 
> 2158)
> @@ -0,0 +1,287 @@
> +/* normal_parser.h  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2005,2007,2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_NORMAL_PARSER_HEADER
> +#define GRUB_NORMAL_PARSER_HEADER    1
> +
> +#include <grub/types.h>
> +#include <grub/err.h>
> +#include <grub/parser.h>
> +
> +struct grub_script_mem;
> +
> +/* The generic header for each scripting command or structure.  */
> +struct grub_script_cmd
> +{
> +  /* This function is called to execute the command.  */
> +  grub_err_t (*exec) (struct grub_script_cmd *cmd);
> +
> +  /* The next command.  This can be used by the parent to form a chain
> +     of commands.  */
> +  struct grub_script_cmd *next;
> +};
> +
> +struct grub_script
> +{
> +  struct grub_script_mem *mem;
> +  struct grub_script_cmd *cmd;
> +};
> +
> +typedef enum
> +{
> +  GRUB_SCRIPT_ARG_TYPE_STR,
> +  GRUB_SCRIPT_ARG_TYPE_VAR
> +} grub_script_arg_type_t;
> +
> +/* A part of an argument.  */
> +struct grub_script_arg
> +{
> +  grub_script_arg_type_t type;
> +
> +  char *str;
> +
> +  /* Next argument part.  */
> +  struct grub_script_arg *next;
> +};
> +
> +/* A complete argument.  It consists of a list of one or more `struct
> +   grub_script_arg's.  */
> +struct grub_script_arglist
> +{
> +  struct grub_script_arglist *next;
> +  struct grub_script_arg *arg;
> +  /* Only stored in the first link.  */
> +  int argcount;
> +};
> +
> +/* A single command line.  */
> +struct grub_script_cmdline
> +{
> +  struct grub_script_cmd cmd;
> +
> +  /* The arguments for this command.  */
> +  struct grub_script_arglist *arglist;
> +
> +  /* The command name of this command.  XXX: Perhaps an argument
> +     should be used for this so we can use variables as command
> +     name.  */
> +  char *cmdname;
> +};
> +
> +/* A block of commands, this can be used to group commands.  */
> +struct grub_script_cmdblock
> +{
> +  struct grub_script_cmd cmd;
> +
> +  /* A chain of commands.  */
> +  struct grub_script_cmd *cmdlist;
> +};
> +
> +/* An if statement.  */
> +struct grub_script_cmdif
> +{
> +  struct grub_script_cmd cmd;
> +
> +  /* The command used to check if the 'if' is true or false.  */
> +  struct grub_script_cmd *exec_to_evaluate;
> +
> +  /* The code executed in case the result of 'if' was true.  */
> +  struct grub_script_cmd *exec_on_true;
> +
> +  /* The code executed in case the result of 'if' was false.  */
> +  struct grub_script_cmd *exec_on_false;
> +};
> +
> +/* A menu entry generate statement.  */
> +struct grub_script_cmd_menuentry
> +{
> +  struct grub_script_cmd cmd;
> +
> +  /* The arguments for this menu entry.  */
> +  struct grub_script_arglist *arglist;
> +
> +  /* The sourcecode the entry will be generated from.  */
> +  const char *sourcecode;
> +
> +  /* Options.  XXX: Not used yet.  */
> +  int options;
> +};
> +
> +/* State of the lexer as passed to the lexer.  */
> +struct grub_lexer_param
> +{
> +  /* Set to 0 when the lexer is done.  */
> +  int done;
> +
> +  /* State of the state machine.  */
> +  grub_parser_state_t state;
> +
> +  /* Function used by the lexer to get a new line when more input is
> +     expected, but not available.  */
> +  grub_reader_getline_t getline;
> +
> +  /* A reference counter.  If this is >0 it means that the parser
> +     expects more tokens and `getline' should be called to fetch more.
> +     Otherwise the lexer can stop processing if the current buffer is
> +     depleted.  */
> +  int refs;
> +
> +  /* The character stream that has to be parsed.  */
> +  char *script;
> +  char *newscript; /* XXX */
> +
> +  /* While walking through the databuffer, `record' the characters to
> +     this other buffer.  It can be used to edit the menu entry at a
> +     later moment.  */
> +
> +  /* If true, recording is enabled.  */
> +  int record;
> +
> +  /* Points to the recording.  */
> +  char *recording;
> +
> +  /* index in the RECORDING.  */
> +  int recordpos;
> +
> +  /* Size of RECORDING.  */
> +  int recordlen;
> +};
> +
> +/* State of the parser as passes to the parser.  */
> +struct grub_parser_param
> +{
> +  /* Keep track of the memory allocated for this specific
> +     function.  */
> +  struct grub_script_mem *func_mem;
> +
> +  /* When set to 0, no errors have occured during parsing.  */
> +  int err;
> +
> +  /* The memory that was used while parsing and scanning.  */
> +  struct grub_script_mem *memused;
> +
> +  /* The result of the parser.  */
> +  struct grub_script_cmd *parsed;
> +
> +  struct grub_lexer_param *lexerstate;
> +};
> +
> +struct grub_script_arglist *
> +grub_script_create_arglist (struct grub_parser_param *state);
> +
> +struct grub_script_arglist *
> +grub_script_add_arglist (struct grub_parser_param *state,
> +                      struct grub_script_arglist *list,
> +                      struct grub_script_arg *arg);
> +struct grub_script_cmd *
> +grub_script_create_cmdline (struct grub_parser_param *state,
> +                         char *cmdname,
> +                         struct grub_script_arglist *arglist);
> +struct grub_script_cmd *
> +grub_script_create_cmdblock (struct grub_parser_param *state);
> +
> +struct grub_script_cmd *
> +grub_script_create_cmdif (struct grub_parser_param *state,
> +                       struct grub_script_cmd *exec_to_evaluate,
> +                       struct grub_script_cmd *exec_on_true,
> +                       struct grub_script_cmd *exec_on_false);
> +
> +struct grub_script_cmd *
> +grub_script_create_cmdmenu (struct grub_parser_param *state,
> +                         struct grub_script_arglist *arglist,
> +                         char *sourcecode,
> +                         int options);
> +
> +struct grub_script_cmd *
> +grub_script_add_cmd (struct grub_parser_param *state,
> +                  struct grub_script_cmdblock *cmdblock,
> +                  struct grub_script_cmd *cmd);
> +struct grub_script_arg *
> +grub_script_arg_add (struct grub_parser_param *state,
> +                  struct grub_script_arg *arg,
> +                  grub_script_arg_type_t type, char *str);
> +
> +struct grub_script *grub_script_parse (char *script,
> +                                    grub_reader_getline_t getline);
> +void grub_script_free (struct grub_script *script);
> +struct grub_script *grub_script_create (struct grub_script_cmd *cmd,
> +                                     struct grub_script_mem *mem);
> +
> +struct grub_lexer_param *grub_script_lexer_init (char *s,
> +                                              grub_reader_getline_t getline);
> +void grub_script_lexer_ref (struct grub_lexer_param *);
> +void grub_script_lexer_deref (struct grub_lexer_param *);
> +void grub_script_lexer_record_start (struct grub_lexer_param *);
> +char *grub_script_lexer_record_stop (struct grub_lexer_param *);
> +
> +/* Functions to track allocated memory.  */
> +struct grub_script_mem *grub_script_mem_record (struct grub_parser_param 
> *state);
> +struct grub_script_mem *grub_script_mem_record_stop (struct 
> grub_parser_param *state,
> +                                                  struct grub_script_mem 
> *restore);
> +void *grub_script_malloc (struct grub_parser_param *state, grub_size_t size);
> +
> +/* Functions used by bison.  */
> +union YYSTYPE;
> +int grub_script_yylex (union YYSTYPE *, struct grub_parser_param *);
> +int grub_script_yyparse (struct grub_parser_param *);
> +void grub_script_yyerror (struct grub_parser_param *, char const *);
> +
> +/* Commands to execute, don't use these directly.  */
> +grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd);
> +grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd);
> +grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd);
> +grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd);
> +
> +/* Execute any GRUB pre-parsed command or script.  */
> +grub_err_t grub_script_execute (struct grub_script *script);
> +
> +/* This variable points to the parsed command.  This is used to
> +   communicate with the bison code.  */
> +extern struct grub_script_cmd *grub_script_parsed;
> +
> +
> +
> +/* The function description.  */
> +struct grub_script_function
> +{
> +  /* The name.  */
> +  char *name;
> +
> +  /* The script function.  */
> +  struct grub_script *func;
> +
> +  /* The flags.  */
> +  unsigned flags;
> +
> +  /* The next element.  */
> +  struct grub_script_function *next;
> +
> +  int references;
> +};
> +typedef struct grub_script_function *grub_script_function_t;
> +
> +grub_script_function_t grub_script_function_create (char *functionname,
> +                                                 struct grub_script *cmd);
> +void grub_script_function_remove (const char *name);
> +grub_script_function_t grub_script_function_find (char *functionname);
> +int grub_script_function_iterate (int (*iterate) (grub_script_function_t));
> +int grub_script_function_call (grub_script_function_t func,
> +                            int argc, char **args);
> +
> +#endif /* ! GRUB_NORMAL_PARSER_HEADER */
> 
> Modified: trunk/grub2/kern/main.c
> ===================================================================
> --- trunk/grub2/kern/main.c   2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/kern/main.c   2009-05-02 19:49:34 UTC (rev 2158)
> @@ -22,11 +22,13 @@
>  #include <grub/symbol.h>
>  #include <grub/dl.h>
>  #include <grub/term.h>
> -#include <grub/rescue.h>
>  #include <grub/file.h>
>  #include <grub/device.h>
>  #include <grub/env.h>
>  #include <grub/mm.h>
> +#include <grub/command.h>
> +#include <grub/reader.h>
> +#include <grub/parser.h>
>  
>  void
>  grub_module_iterate (int (*hook) (struct grub_module_header *header))
> @@ -120,6 +122,9 @@
>    
>    /* Something went wrong.  Print errors here to let user know why we're 
> entering rescue mode.  */
>    grub_print_error ();
> +  grub_errno = 0;
> +
> +  grub_command_execute ("normal", 0, 0);
>  }
>  
>  /* The main routine.  */
> @@ -144,9 +149,10 @@
>    grub_env_export ("prefix");
>    grub_set_root_dev ();
>  
> -  /* Load the normal mode module.  */
> +  grub_register_core_commands ();
> +  grub_register_rescue_parser ();
> +  grub_register_rescue_reader ();
> +  
>    grub_load_normal_mode ();
> -  
> -  /* Enter the rescue mode.  */
> -  grub_enter_rescue_mode ();
> +  grub_reader_loop (0);
>  }
> 
> Modified: trunk/grub2/kern/parser.c
> ===================================================================
> --- trunk/grub2/kern/parser.c 2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/kern/parser.c 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,7 +1,7 @@
>  /* parser.c - the part of the parser that can return partial tokens */
>  /*
>   *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2005,2007  Free Software Foundation, Inc.
> + *  Copyright (C) 2005,2007,2009  Free Software Foundation, Inc.
>   *
>   *  GRUB is free software: you can redistribute it and/or modify
>   *  it under the terms of the GNU General Public License as published by
> @@ -100,7 +100,7 @@
>  
>  
>  grub_err_t
> -grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char 
> **),
> +grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t 
> getline,
>                          int *argc, char ***argv)
>  {
>    grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
> @@ -152,7 +152,7 @@
>        if (! *rd)
>       {
>         if (getline)
> -         getline (&rd);
> +         getline (&rd, 1);
>         else break;
>       }
>  
> @@ -227,3 +227,45 @@
>  
>    return 0;
>  }
> +
> +struct grub_handler_class grub_parser_class =
> +  {
> +    .name = "parser"
> +  };
> +
> +grub_err_t
> +grub_parser_execute (char *source)
> +{
> +  auto grub_err_t getline (char **line, int cont);
> +  grub_err_t getline (char **line, int cont __attribute__ ((unused)))
> +    {
> +      char *p;
> +
> +      if (! source)
> +     {
> +       *line = 0;
> +       return 0;
> +     }
> +
> +      p = grub_strchr (source, '\n');
> +      if (p)
> +     *(p++) = 0;
> +
> +      *line = grub_strdup (source);
> +      source = p;
> +      return 0;
> +    }
> +
> +  while (source)
> +    {
> +      char *line;
> +      grub_parser_t parser;
> +
> +      getline (&line, 0);
> +      parser = grub_parser_get_current ();
> +      parser->parse_line (line, getline);
> +      grub_free (line);
> +    }
> +
> +  return grub_errno;
> +}
> 
> Added: trunk/grub2/kern/reader.c
> ===================================================================
> --- trunk/grub2/kern/reader.c                         (rev 0)
> +++ trunk/grub2/kern/reader.c 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,49 @@
> +/* reader.c - reader support */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/types.h>
> +#include <grub/mm.h>
> +#include <grub/reader.h>
> +#include <grub/parser.h>
> +
> +struct grub_handler_class grub_reader_class =
> +  {
> +    .name = "reader"
> +  };
> +
> +grub_err_t
> +grub_reader_loop (grub_reader_getline_t getline)
> +{
> +  while (1)
> +    {
> +      char *line;
> +      grub_reader_getline_t func;
> +
> +      /* Print an error, if any.  */
> +      grub_print_error ();
> +      grub_errno = GRUB_ERR_NONE;
> +
> +      func = (getline) ? : grub_reader_get_current ()->read_line;
> +      if ((func (&line, 0)) || (! line))
> +     return grub_errno;
> +
> +      grub_parser_get_current ()->parse_line (line, func);
> +      grub_free (line);
> +    }
> +}
> 
> Deleted: trunk/grub2/kern/rescue.c
> ===================================================================
> --- trunk/grub2/kern/rescue.c 2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/kern/rescue.c 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,163 +0,0 @@
> -/* rescue.c - rescue mode */
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2002,2003,2005,2007  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <grub/kernel.h>
> -#include <grub/rescue.h>
> -#include <grub/term.h>
> -#include <grub/misc.h>
> -#include <grub/disk.h>
> -#include <grub/file.h>
> -#include <grub/mm.h>
> -#include <grub/err.h>
> -#include <grub/loader.h>
> -#include <grub/dl.h>
> -#include <grub/partition.h>
> -#include <grub/env.h>
> -#include <grub/parser.h>
> -#include <grub/list.h>
> -#include <grub/command.h>
> -
> -#define GRUB_RESCUE_BUF_SIZE 256
> -#define GRUB_RESCUE_MAX_ARGS 20
> -
> -static char linebuf[GRUB_RESCUE_BUF_SIZE];
> -
> -/* Prompt to input a command and read the line.  */
> -static void
> -grub_rescue_get_command_line (const char *prompt)
> -{
> -  int c;
> -  int pos = 0;
> -  
> -  grub_printf (prompt);
> -  grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE);
> -  
> -  while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r')
> -    {
> -      if (grub_isprint (c))
> -     {
> -       if (pos < GRUB_RESCUE_BUF_SIZE - 1)
> -         {
> -           linebuf[pos++] = c;
> -           grub_putchar (c);
> -         }
> -     }
> -      else if (c == '\b')
> -     {
> -       if (pos > 0)
> -         {
> -           linebuf[--pos] = 0;
> -           grub_putchar (c);
> -           grub_putchar (' ');
> -           grub_putchar (c);
> -         }
> -     }
> -      grub_refresh ();
> -    }
> -
> -  grub_putchar ('\n');
> -  grub_refresh ();
> -}
> -
> -static void
> -attempt_normal_mode (void)
> -{
> -  grub_command_t cmd;
> -
> -  cmd = grub_command_find ("normal");
> -  if (cmd)
> -    (cmd->func) (cmd, 0, 0);
> -}
> -
> -/* Enter the rescue mode.  */
> -void
> -grub_enter_rescue_mode (void)
> -{
> -  auto grub_err_t getline (char **line);
> -  
> -  grub_err_t getline (char **line)
> -    {
> -      grub_rescue_get_command_line ("> ");
> -      *line = linebuf;
> -      return 0;
> -    }
> -
> -  grub_register_core_commands ();
> -
> -  /* First of all, attempt to execute the normal mode.  */
> -  attempt_normal_mode ();
> -
> -  grub_printf ("Entering rescue mode...\n");
> -  
> -  while (1)
> -    {
> -      char *line = linebuf;
> -      char *name;
> -      int n;
> -      grub_command_t cmd;
> -      char **args;
> -
> -      /* Print an error, if any.  */
> -      grub_print_error ();
> -      grub_errno = GRUB_ERR_NONE;
> -
> -      /* Get a command line.  */
> -      grub_rescue_get_command_line ("grub rescue> ");
> -      if (line[0] == 0)
> -     continue;
> -
> -      if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0)
> -     continue;
> -
> -      /* In case of an assignment set the environment accordingly
> -      instead of calling a function.  */
> -      if (n == 0 && grub_strchr (line, '='))
> -     {
> -       char *val = grub_strchr (args[0], '=');
> -       val[0] = 0;
> -       grub_env_set (args[0], val + 1);
> -       val[0] = '=';
> -          grub_free (args[0]);
> -       continue;
> -     }
> -
> -      /* Get the command name.  */
> -      name = args[0];
> -
> -      /* If nothing is specified, restart.  */
> -      if (*name == '\0')
> -     {
> -       grub_free (args[0]);
> -       continue;
> -     }
> -      
> -      cmd = grub_command_find (name);
> -      if (cmd)
> -     {
> -       (cmd->func) (cmd, n, &args[1]);
> -     }
> -      else
> -     {
> -       grub_printf ("Unknown command `%s'\n", name);
> -       grub_printf ("Try `help' for usage\n");
> -     }
> -
> -      grub_free (args[0]);
> -    }
> -}
> 
> Added: trunk/grub2/kern/rescue_parser.c
> ===================================================================
> --- trunk/grub2/kern/rescue_parser.c                          (rev 0)
> +++ trunk/grub2/kern/rescue_parser.c  2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,84 @@
> +/* rescue_parser.c - rescue mode parser  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/types.h>
> +#include <grub/mm.h>
> +#include <grub/env.h>
> +#include <grub/parser.h>
> +#include <grub/misc.h>
> +#include <grub/command.h>
> +
> +static grub_err_t
> +grub_rescue_parse_line (char *line, grub_reader_getline_t getline)
> +{
> +  char *name;
> +  int n;
> +  grub_command_t cmd;
> +  char **args;
> +
> +  if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0)
> +    return grub_errno;
> +
> +  /* In case of an assignment set the environment accordingly
> +     instead of calling a function.  */
> +  if (n == 0 && grub_strchr (line, '='))
> +    {
> +      char *val = grub_strchr (args[0], '=');
> +      val[0] = 0;
> +      grub_env_set (args[0], val + 1);
> +      val[0] = '=';
> +      goto quit;
> +    }
> +
> +  /* Get the command name.  */
> +  name = args[0];
> +
> +  /* If nothing is specified, restart.  */
> +  if (*name == '\0')
> +    goto quit;
> +
> +  cmd = grub_command_find (name);
> +  if (cmd)
> +    {
> +      (cmd->func) (cmd, n, &args[1]);
> +    }
> +  else
> +    {
> +      grub_printf ("Unknown command `%s'\n", name);
> +      grub_printf ("Try `help' for usage\n");
> +    }
> +
> + quit:
> +  grub_free (args[0]);
> +  grub_free (args);
> +
> +  return grub_errno;
> +}
> +
> +static struct grub_parser grub_rescue_parser =
> +  {
> +    .name = "rescue",
> +    .parse_line = grub_rescue_parse_line
> +  };
> +
> +void
> +grub_register_rescue_parser (void)
> +{
> +  grub_parser_register ("rescue", &grub_rescue_parser);
> +}
> 
> Added: trunk/grub2/kern/rescue_reader.c
> ===================================================================
> --- trunk/grub2/kern/rescue_reader.c                          (rev 0)
> +++ trunk/grub2/kern/rescue_reader.c  2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,88 @@
> +/* rescue_reader.c - rescue mode reader  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/types.h>
> +#include <grub/reader.h>
> +#include <grub/misc.h>
> +#include <grub/term.h>
> +
> +#define GRUB_RESCUE_BUF_SIZE 256
> +
> +static char linebuf[GRUB_RESCUE_BUF_SIZE];
> +
> +static grub_err_t
> +grub_rescue_init (void)
> +{
> +  grub_printf ("Entering rescue mode...\n");
> +  return 0;
> +}
> +
> +/* Prompt to input a command and read the line.  */
> +static grub_err_t
> +grub_rescue_read_line (char **line, int cont)
> +{
> +  int c;
> +  int pos = 0;
> +
> +  grub_printf ((cont) ? "> " : "grub rescue> ");
> +  grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE);
> +
> +  while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r')
> +    {
> +      if (grub_isprint (c))
> +     {
> +       if (pos < GRUB_RESCUE_BUF_SIZE - 1)
> +         {
> +           linebuf[pos++] = c;
> +           grub_putchar (c);
> +         }
> +     }
> +      else if (c == '\b')
> +     {
> +       if (pos > 0)
> +         {
> +           linebuf[--pos] = 0;
> +           grub_putchar (c);
> +           grub_putchar (' ');
> +           grub_putchar (c);
> +         }
> +     }
> +      grub_refresh ();
> +    }
> +
> +  grub_putchar ('\n');
> +  grub_refresh ();
> +
> +  *line = grub_strdup (linebuf);
> +
> +  return 0;
> +}
> +
> +static struct grub_reader grub_rescue_reader =
> +  {
> +    .name = "rescue",
> +    .init = grub_rescue_init,
> +    .read_line = grub_rescue_read_line
> +  };
> +
> +void
> +grub_register_rescue_reader (void)
> +{
> +  grub_reader_register ("rescue", &grub_rescue_reader);
> +}
> 
> Modified: trunk/grub2/loader/i386/multiboot.c
> ===================================================================
> --- trunk/grub2/loader/i386/multiboot.c       2009-05-02 16:55:35 UTC (rev 
> 2157)
> +++ trunk/grub2/loader/i386/multiboot.c       2009-05-02 19:49:34 UTC (rev 
> 2158)
> @@ -37,7 +37,6 @@
>  #include <grub/aout.h>
>  #include <grub/file.h>
>  #include <grub/err.h>
> -#include <grub/rescue.h>
>  #include <grub/dl.h>
>  #include <grub/mm.h>
>  #include <grub/misc.h>
> 
> Modified: trunk/grub2/loader/multiboot2.c
> ===================================================================
> --- trunk/grub2/loader/multiboot2.c   2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/loader/multiboot2.c   2009-05-02 19:49:34 UTC (rev 2158)
> @@ -24,7 +24,6 @@
>  #include <grub/elfload.h>
>  #include <grub/file.h>
>  #include <grub/err.h>
> -#include <grub/rescue.h>
>  #include <grub/dl.h>
>  #include <grub/mm.h>
>  #include <grub/misc.h>
> 
> Modified: trunk/grub2/loader/sparc64/ieee1275/linux.c
> ===================================================================
> --- trunk/grub2/loader/sparc64/ieee1275/linux.c       2009-05-02 16:55:35 UTC 
> (rev 2157)
> +++ trunk/grub2/loader/sparc64/ieee1275/linux.c       2009-05-02 19:49:34 UTC 
> (rev 2158)
> @@ -22,7 +22,6 @@
>  #include <grub/loader.h>
>  #include <grub/dl.h>
>  #include <grub/mm.h>
> -#include <grub/rescue.h>
>  #include <grub/misc.h>
>  #include <grub/ieee1275/ieee1275.h>
>  #include <grub/machine/loader.h>
> 
> Added: trunk/grub2/normal/autofs.c
> ===================================================================
> --- trunk/grub2/normal/autofs.c                               (rev 0)
> +++ trunk/grub2/normal/autofs.c       2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,134 @@
> +/* autofs.c - support auto-loading from fs.lst */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/mm.h>
> +#include <grub/dl.h>
> +#include <grub/env.h>
> +#include <grub/misc.h>
> +#include <grub/fs.h>
> +#include <grub/normal.h>
> +
> +/* This is used to store the names of filesystem modules for auto-loading.  
> */
> +struct grub_fs_module_list
> +{
> +  char *name;
> +  struct grub_fs_module_list *next;
> +};
> +typedef struct grub_fs_module_list *grub_fs_module_list_t;
> +
> +static grub_fs_module_list_t fs_module_list = 0;
> +
> +/* The auto-loading hook for filesystems.  */
> +static int
> +autoload_fs_module (void)
> +{
> +  grub_fs_module_list_t p;
> +
> +  while ((p = fs_module_list) != 0)
> +    {
> +      if (! grub_dl_get (p->name) && grub_dl_load (p->name))
> +     return 1;
> +
> +      fs_module_list = p->next;
> +      grub_free (p->name);
> +      grub_free (p);
> +    }
> +
> +  return 0;
> +}
> +
> +/* Read the file fs.lst for auto-loading.  */
> +void
> +read_fs_list (void)
> +{
> +  const char *prefix;
> +  static int first_time = 1;
> +
> +  /* Make sure that this function does not get executed twice.  */
> +  if (! first_time)
> +    return;
> +  first_time = 0;
> +
> +  prefix = grub_env_get ("prefix");
> +  if (prefix)
> +    {
> +      char *filename;
> +
> +      filename = grub_malloc (grub_strlen (prefix) + sizeof ("/fs.lst"));
> +      if (filename)
> +     {
> +       grub_file_t file;
> +
> +       grub_sprintf (filename, "%s/fs.lst", prefix);
> +       file = grub_file_open (filename);
> +       if (file)
> +         {
> +           while (1)
> +             {
> +               char *buf;
> +               char *p;
> +               char *q;
> +               grub_fs_module_list_t fs_mod;
> +
> +               buf = grub_file_getline (file);
> +               if (! buf)
> +                 break;
> +
> +               p = buf;
> +               q = buf + grub_strlen (buf) - 1;
> +
> +               /* Ignore space.  */
> +               while (grub_isspace (*p))
> +                 p++;
> +
> +               while (p < q && grub_isspace (*q))
> +                 *q-- = '\0';
> +
> +               /* If the line is empty, skip it.  */
> +               if (p >= q)
> +                 continue;
> +
> +               fs_mod = grub_malloc (sizeof (*fs_mod));
> +               if (! fs_mod)
> +                 continue;
> +
> +               fs_mod->name = grub_strdup (p);
> +               if (! fs_mod->name)
> +                 {
> +                   grub_free (fs_mod);
> +                   continue;
> +                 }
> +
> +               fs_mod->next = fs_module_list;
> +               fs_module_list = fs_mod;
> +             }
> +
> +           grub_file_close (file);
> +         }
> +
> +       grub_free (filename);
> +     }
> +    }
> +
> +  /* Ignore errors.  */
> +  grub_errno = GRUB_ERR_NONE;
> +
> +  /* Set the hook.  */
> +  grub_fs_autoload_hook = autoload_fs_module;
> +}
> 
> Modified: trunk/grub2/normal/cmdline.c
> ===================================================================
> --- trunk/grub2/normal/cmdline.c      2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/cmdline.c      2009-05-02 19:49:34 UTC (rev 2158)
> @@ -132,37 +132,6 @@
>    hist_lines[pos] = grub_strdup (s);
>  }
>  
> -void
> -grub_cmdline_run (int nested)
> -{
> -  grub_normal_init_page ();
> -  grub_setcursor (1);
> -  
> -  grub_printf ("\
> - [ Minimal BASH-like line editing is supported. For the first word, TAB\n\
> -   lists possible command completions. Anywhere else TAB lists possible\n\
> -   device/file completions.%s ]\n\n",
> -            nested ? " ESC at any time exits." : "");
> -  
> -  while (1)
> -    {
> -      static char cmdline[GRUB_MAX_CMDLINE];
> -
> -      grub_print_error ();
> -      grub_errno = GRUB_ERR_NONE;
> -      cmdline[0] = '\0';
> -      
> -      if (! grub_cmdline_get ("grub> ", cmdline, sizeof (cmdline), 0, 1)
> -       && nested)
> -     return;
> -
> -      if (! *cmdline)
> -     continue;
> -
> -      grub_command_execute (cmdline, 1);
> -    }
> -}
> -
>  /* A completion hook to print items.  */
>  static void
>  print_completion (const char *item, grub_completion_type_t type, int count)
> 
> Deleted: trunk/grub2/normal/command.c
> ===================================================================
> --- trunk/grub2/normal/command.c      2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/command.c      2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,70 +0,0 @@
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2003,2005,2006,2007  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <grub/normal.h>
> -#include <grub/misc.h>
> -#include <grub/mm.h>
> -#include <grub/err.h>
> -#include <grub/term.h>
> -#include <grub/env.h>
> -#include <grub/dl.h>
> -#include <grub/parser.h>
> -#include <grub/script.h>
> -#include <grub/list.h>
> -#include <grub/command.h>
> -
> -int
> -grub_command_execute (char *cmdline, int interactive)
> -{
> -  auto grub_err_t cmdline_get (char **s);
> -  grub_err_t cmdline_get (char **s)
> -    {
> -      *s = grub_malloc (GRUB_MAX_CMDLINE);
> -      *s[0] = '\0';
> -      return grub_cmdline_get (">", *s, GRUB_MAX_CMDLINE, 0, 1);
> -    }
> -
> -  grub_err_t ret = 0;
> -  char *pager;
> -  struct grub_script *parsed_script;
> -  
> -  /* Enable the pager if the environment pager is set to 1.  */
> -  if (interactive)
> -    pager = grub_env_get ("pager");
> -  else
> -    pager = NULL;
> -  if (pager && (! grub_strcmp (pager, "1")))
> -    grub_set_more (1);
> -
> -  /* Parse the script.  */
> -  parsed_script = grub_script_parse (cmdline, cmdline_get);
> -
> -  if (parsed_script)
> -    {
> -      /* Execute the command(s).  */
> -      grub_script_execute (parsed_script);
> -
> -      /* The parsed script was executed, throw it away.  */
> -      grub_script_free (parsed_script);
> -    }
> -
> -  if (pager && (! grub_strcmp (pager, "1")))
> -    grub_set_more (0);
> -
> -  return ret;
> -}
> 
> Added: trunk/grub2/normal/dyncmd.c
> ===================================================================
> --- trunk/grub2/normal/dyncmd.c                               (rev 0)
> +++ trunk/grub2/normal/dyncmd.c       2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,158 @@
> +/* dyncmd.c - support dynamic command */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/dl.h>
> +#include <grub/mm.h>
> +#include <grub/env.h>
> +#include <grub/misc.h>
> +#include <grub/command.h>
> +#include <grub/normal.h>
> +
> +static grub_err_t
> +grub_dyncmd_dispatcher (struct grub_command *cmd,
> +                     int argc, char **args)
> +{
> +  char *modname = cmd->data;
> +  grub_dl_t mod;
> +  grub_err_t ret;
> +
> +  mod = grub_dl_load (modname);
> +  if (mod)
> +    {
> +      char *name;
> +
> +      grub_free (modname);
> +      grub_dl_ref (mod);
> +
> +      name = (char *) cmd->name;
> +      grub_unregister_command (cmd);
> +
> +      cmd = grub_command_find (name);
> +      if (cmd)
> +     ret = (cmd->func) (cmd, argc, args);
> +      else
> +     ret = grub_errno;
> +
> +      grub_free (name);
> +    }
> +  else
> +    ret = grub_errno;
> +
> +  return ret;
> +}
> +
> +/* Read the file command.lst for auto-loading.  */
> +void
> +read_command_list (void)
> +{
> +  const char *prefix;
> +  static int first_time = 1;
> +
> +  /* Make sure that this function does not get executed twice.  */
> +  if (! first_time)
> +    return;
> +  first_time = 0;
> +
> +  prefix = grub_env_get ("prefix");
> +  if (prefix)
> +    {
> +      char *filename;
> +
> +      filename = grub_malloc (grub_strlen (prefix) + sizeof 
> ("/command.lst"));
> +      if (filename)
> +     {
> +       grub_file_t file;
> +
> +       grub_sprintf (filename, "%s/command.lst", prefix);
> +       file = grub_file_open (filename);
> +       if (file)
> +         {
> +           char *buf = 0;
> +           for (;; grub_free(buf))
> +             {
> +               char *p, *name, *modname;
> +               grub_command_t cmd;
> +               int prio = 0;
> +
> +               buf = grub_file_getline (file);
> +
> +               if (! buf)
> +                 break;
> +
> +               name = buf;
> +               if (*name == '*')
> +                 {
> +                   name++;
> +                   prio++;
> +                 }
> +
> +               if (! grub_isgraph (name[0]))
> +                 continue;
> +
> +               p = grub_strchr (name, ':');
> +               if (! p)
> +                 continue;
> +
> +               *p = '\0';
> +               while (*++p == ' ')
> +                 ;
> +
> +               if (! grub_isgraph (*p))
> +                 continue;
> +
> +               if (grub_dl_get (p))
> +                 continue;
> +
> +               name = grub_strdup (name);
> +               if (! name)
> +                 continue;
> +
> +               modname = grub_strdup (p);
> +               if (! modname)
> +                 {
> +                   grub_free (name);
> +                   continue;
> +                 }
> +
> +               cmd = grub_register_command_prio (name,
> +                                                 grub_dyncmd_dispatcher,
> +                                                 0, "not loaded", prio);
> +               if (! cmd)
> +                 {
> +                   grub_free (name);
> +                   grub_free (modname);
> +                   continue;
> +                 }
> +               cmd->flags |= GRUB_COMMAND_FLAG_DYNCMD;
> +               cmd->data = modname;
> +
> +               /* Update the active flag.  */
> +               grub_command_find (name);
> +             }
> +
> +           grub_file_close (file);
> +         }
> +
> +       grub_free (filename);
> +     }
> +    }
> +
> +  /* Ignore errors.  */
> +  grub_errno = GRUB_ERR_NONE;
> +}
> 
> Deleted: trunk/grub2/normal/execute.c
> ===================================================================
> --- trunk/grub2/normal/execute.c      2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/execute.c      2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,251 +0,0 @@
> -/* execute.c -- Execute a GRUB script.  */
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2005,2007,2008,2009  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <grub/misc.h>
> -#include <grub/mm.h>
> -#include <grub/normal.h>
> -#include <grub/env.h>
> -#include <grub/script.h>
> -#include <grub/lib/arg.h>
> -
> -static grub_err_t
> -grub_script_execute_cmd (struct grub_script_cmd *cmd)
> -{
> -  if (cmd == 0)
> -    return 0;
> -
> -  return cmd->exec (cmd);
> -}
> -
> -/* Parse ARG and return the textual representation.  Add strings are
> -   concatenated and all values of the variables are filled in.  */
> -static char *
> -grub_script_execute_argument_to_string (struct grub_script_arg *arg)
> -{
> -  int size = 0;
> -  char *val;
> -  char *chararg;
> -  struct grub_script_arg *argi;
> -
> -  /* First determine the size of the argument.  */
> -  for (argi = arg; argi; argi = argi->next)
> -    {
> -      if (argi->type == 1)
> -     {
> -       val = grub_env_get (argi->str);
> -       if (val)
> -         size += grub_strlen (val);
> -     }
> -      else
> -     size += grub_strlen (argi->str);
> -    }
> -
> -  /* Create the argument.  */
> -  chararg = grub_malloc (size + 1);
> -  if (! chararg)
> -    return 0;
> -
> -  *chararg = '\0';
> -  /* First determine the size of the argument.  */
> -  for (argi = arg; argi; argi = argi->next)
> -    {
> -      if (argi->type == 1)
> -     {
> -       val = grub_env_get (argi->str);
> -       if (val)
> -         grub_strcat (chararg, val);
> -     }
> -      else
> -     grub_strcat (chararg, argi->str);
> -    }
> -
> -  return chararg;
> -}
> -
> -/* Execute a single command line.  */
> -grub_err_t
> -grub_script_execute_cmdline (struct grub_script_cmd *cmd)
> -{
> -  struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd;
> -  struct grub_script_arglist *arglist;
> -  char **args = 0;
> -  int i = 0;
> -  grub_command_t grubcmd;
> -  grub_err_t ret = 0;
> -  int argcount = 0;
> -  grub_script_function_t func = 0;
> -  char errnobuf[6];
> -
> -  /* Lookup the command.  */
> -  grubcmd = grub_command_find (cmdline->cmdname);
> -  if (! grubcmd)
> -    {
> -      /* Ignore errors.  */
> -      grub_errno = GRUB_ERR_NONE;
> -
> -      /* It's not a GRUB command, try all functions.  */
> -      func = grub_script_function_find (cmdline->cmdname);
> -      if (! func)
> -     {
> -       /* As a last resort, try if it is an assignment.  */
> -       char *assign = grub_strdup (cmdline->cmdname);
> -       char *eq = grub_strchr (assign, '=');
> -
> -       if (eq)
> -         {
> -           /* Create two strings and set the variable.  */
> -           *eq = '\0';
> -           eq++;
> -           grub_env_set (assign, eq);
> -
> -           /* This was set because the command was not found.  */
> -           grub_errno = GRUB_ERR_NONE;
> -         }
> -       grub_free (assign);
> -       return 0;
> -     }
> -    }
> -
> -  if (cmdline->arglist)
> -    {
> -      argcount = cmdline->arglist->argcount;
> -
> -      /* Create argv from the arguments.  */
> -      args = grub_malloc (sizeof (char *) * argcount);
> -      for (arglist = cmdline->arglist; arglist; arglist = arglist->next)
> -     {
> -       char *str;
> -       str = grub_script_execute_argument_to_string (arglist->arg);
> -       args[i++] = str;
> -     }
> -    }
> -
> -  /* Execute the GRUB command or function.  */
> -  if (grubcmd)
> -    ret = (grubcmd->func) (grubcmd, argcount, args);
> -  else
> -    ret = grub_script_function_call (func, argcount, args);
> -
> -  /* Free arguments.  */
> -  for (i = 0; i < argcount; i++)
> -    grub_free (args[i]);
> -  grub_free (args);
> -
> -  grub_sprintf (errnobuf, "%d", ret);
> -  grub_env_set ("?", errnobuf);
> -
> -  return ret;
> -}
> -
> -/* Execute a block of one or more commands.  */
> -grub_err_t
> -grub_script_execute_cmdblock (struct grub_script_cmd *cmd)
> -{
> -  struct grub_script_cmdblock *cmdblock = (struct grub_script_cmdblock *) 
> cmd;
> -
> -  /* Loop over every command and execute it.  */
> -  for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next)
> -    grub_script_execute_cmd (cmd);
> -
> -  return 0;
> -}
> -
> -/* Execute an if statement.  */
> -grub_err_t
> -grub_script_execute_cmdif (struct grub_script_cmd *cmd)
> -{
> -  struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd;
> -  char *result;
> -
> -  /* Check if the commands results in a true or a false.  The value is
> -     read from the env variable `?'.  */
> -  grub_script_execute_cmd (cmdif->exec_to_evaluate);
> -  result = grub_env_get ("?");
> -
> -  /* Execute the `if' or the `else' part depending on the value of
> -     `?'.  */
> -  if (result && ! grub_strcmp (result, "0"))
> -    return grub_script_execute_cmd (cmdif->exec_on_true);
> -  else
> -    return grub_script_execute_cmd (cmdif->exec_on_false);
> -}
> -
> -/* Execute the menu entry generate statement.  */
> -grub_err_t
> -grub_script_execute_menuentry (struct grub_script_cmd *cmd)
> -{
> -  struct grub_script_cmd_menuentry *cmd_menuentry;
> -  struct grub_script_arglist *arglist;
> -  struct grub_script *script;
> -  char **args = 0;
> -  int argcount = 0;
> -  int i = 0;
> -
> -  cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;
> -
> -  if (cmd_menuentry->arglist)
> -    {
> -      argcount = cmd_menuentry->arglist->argcount;
> -
> -      /* Create argv from the arguments.  */
> -      args = grub_malloc (sizeof (char *) * argcount);
> -
> -      if (! args)
> -     {
> -       return grub_errno;
> -     }
> -
> -      for (arglist = cmd_menuentry->arglist; arglist; arglist = 
> arglist->next)
> -     {
> -       char *str;
> -       str = grub_script_execute_argument_to_string (arglist->arg);
> -       args[i++] = str;
> -     }
> -    }
> -
> -  /* Parse the menu entry *again*.  */
> -  script = grub_script_parse ((char *) cmd_menuentry->sourcecode, 0);
> -
> -  /* Add new menu entry.  */
> -  if (script)
> -    {
> -      grub_normal_menu_addentry (argcount, (const char **)args,
> -                              script, cmd_menuentry->sourcecode);
> -    }
> -
> -  /* Free arguments.  */
> -  for (i = 0; i < argcount; i++)
> -    grub_free (args[i]);
> -  grub_free (args);
> -
> -  return grub_errno;
> -}
> -
> -
> -
> -/* Execute any GRUB pre-parsed command or script.  */
> -grub_err_t
> -grub_script_execute (struct grub_script *script)
> -{
> -  if (script == 0)
> -    return 0;
> -
> -  return grub_script_execute_cmd (script->cmd);
> -}
> -
> 
> Deleted: trunk/grub2/normal/function.c
> ===================================================================
> --- trunk/grub2/normal/function.c     2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/function.c     2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,125 +0,0 @@
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2005,2007  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <grub/misc.h>
> -#include <grub/script.h>
> -#include <grub/parser.h>
> -#include <grub/mm.h>
> -
> -static grub_script_function_t grub_script_function_list;
> -
> -grub_script_function_t
> -grub_script_function_create (char *functionname, struct grub_script *cmd)
> -{
> -  grub_script_function_t func;
> -  grub_script_function_t *p;
> -  
> -  func = (grub_script_function_t) grub_malloc (sizeof (*func));
> -  if (! func)
> -    return 0;
> -
> -  func->name = grub_strdup (functionname);
> -  if (! func->name)
> -    {
> -      grub_free (func);
> -      return 0;
> -    }
> -  
> -  func->func = cmd;
> -
> -  /* Keep the list sorted for simplicity.  */
> -  p = &grub_script_function_list;
> -  while (*p)
> -    {
> -      if (grub_strcmp ((*p)->name, functionname) >= 0)
> -     break;
> -
> -      p = &((*p)->next);
> -    }
> -
> -  /* If the function already exists, overwrite the old function.  */
> -  if (*p && grub_strcmp ((*p)->name, functionname) == 0)
> -    {
> -      grub_script_function_t q;
> -
> -      q = *p;
> -      grub_script_free (q->func);
> -      q->func = cmd;
> -      grub_free (func);
> -      func = q;
> -    }
> -  else
> -    {
> -      func->next = *p;
> -      *p = func;
> -    }
> -
> -  return func;
> -}
> -
> -void
> -grub_script_function_remove (const char *name)
> -{
> -  grub_script_function_t *p, q;
> -
> -  for (p = &grub_script_function_list, q = *p; q; p = &(q->next), q = 
> q->next)
> -    if (grub_strcmp (name, q->name) == 0)
> -      {
> -        *p = q->next;
> -     grub_free (q->name);
> -     grub_script_free (q->func);
> -        grub_free (q);
> -        break;
> -      }
> -}
> -
> -grub_script_function_t
> -grub_script_function_find (char *functionname)
> -{
> -  grub_script_function_t func;
> -
> -  for (func = grub_script_function_list; func; func = func->next)
> -    if (grub_strcmp (functionname, func->name) == 0)
> -      break;
> -
> -  if (! func)
> -    grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", 
> functionname);
> -
> -  return func;
> -}
> -
> -int
> -grub_script_function_iterate (int (*iterate) (grub_script_function_t))
> -{
> -  grub_script_function_t func;
> -  
> -  for (func = grub_script_function_list; func; func = func->next)
> -    if (iterate (func))
> -      return 1;
> -  
> -  return 0;
> -}
> -
> -int
> -grub_script_function_call (grub_script_function_t func,
> -                        int argc __attribute__((unused)),
> -                        char **args __attribute__((unused)))
> -{
> -  /* XXX: Arguments are not supported yet.  */
> -  return grub_script_execute (func->func);
> -}
> 
> Deleted: trunk/grub2/normal/lexer.c
> ===================================================================
> --- trunk/grub2/normal/lexer.c        2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/lexer.c        2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,364 +0,0 @@
> -/* lexer.c - The scripting lexer.  */
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2005,2006,2007,2008  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <grub/parser.h>
> -#include <grub/misc.h>
> -#include <grub/mm.h>
> -#include <grub/script.h>
> -
> -#include "grub_script.tab.h"
> -
> -static int
> -check_varstate (grub_parser_state_t state)
> -{
> -  return (state == GRUB_PARSER_STATE_VARNAME
> -       || state == GRUB_PARSER_STATE_VAR
> -       || state == GRUB_PARSER_STATE_QVAR
> -       || state == GRUB_PARSER_STATE_VARNAME2
> -       || state == GRUB_PARSER_STATE_QVARNAME
> -       || state == GRUB_PARSER_STATE_QVARNAME2);
> -}
> -
> -static int
> -check_textstate (grub_parser_state_t state)
> -{
> -  return (state == GRUB_PARSER_STATE_TEXT
> -       || state == GRUB_PARSER_STATE_QUOTE
> -       || state == GRUB_PARSER_STATE_DQUOTE);
> -}
> -
> -struct grub_lexer_param *
> -grub_script_lexer_init (char *script, grub_err_t (*getline) (char **))
> -{
> -  struct grub_lexer_param *param;
> -
> -  param = grub_malloc (sizeof (*param));
> -  if (! param)
> -    return 0;
> -
> -  param->state = GRUB_PARSER_STATE_TEXT;
> -  param->getline = getline;
> -  param->refs = 0;
> -  param->done = 0;
> -  param->newscript = 0;
> -  param->script = script;
> -  param->record = 0;
> -  param->recording = 0;
> -  param->recordpos = 0;
> -  param->recordlen = 0;
> -
> -  return param;
> -}
> -
> -void
> -grub_script_lexer_ref (struct grub_lexer_param *state)
> -{
> -  state->refs++;
> -}
> -
> -void
> -grub_script_lexer_deref (struct grub_lexer_param *state)
> -{
> -  state->refs--;
> -}
> -
> -/* Start recording all characters passing through the lexer.  */
> -void
> -grub_script_lexer_record_start (struct grub_lexer_param *state)
> -{
> -  state->record = 1;
> -  state->recordlen = 100;
> -  state->recording = grub_malloc (state->recordlen);
> -  state->recordpos = 0;
> -}
> -
> -char *
> -grub_script_lexer_record_stop (struct grub_lexer_param *state)
> -{
> -  state->record = 0;
> -
> -  /* Delete the last character, it is a `}'.  */
> -  if (state->recordpos > 0)
> -    {
> -      if (state->recording[--state->recordpos] != '}')
> -     {
> -       grub_printf ("Internal error while parsing menu entry");
> -       for (;;); /* XXX */
> -     }
> -      state->recording[state->recordpos] = '\0';
> -    }
> -
> -  return state->recording;
> -}
> -
> -/* When recording is enabled, record the character C as the next item
> -   in the character stream.  */
> -static void
> -recordchar (struct grub_lexer_param *state, char c)
> -{
> -  if (state->recordpos == state->recordlen)
> -    {
> -      char *old = state->recording;
> -      state->recordlen += 100;
> -      state->recording = grub_realloc (state->recording, state->recordlen);
> -      if (! state->recording)
> -     {
> -       grub_free (old);
> -       state->record = 0;
> -     }
> -    }
> -  state->recording[state->recordpos++] = c;
> -}
> -
> -/* Fetch the next character for the lexer.  */
> -static void
> -nextchar (struct grub_lexer_param *state)
> -{
> -  if (state->record)
> -    recordchar (state, *state->script);
> -  state->script++;
> -}
> -
> -int
> -grub_script_yylex2 (union YYSTYPE *yylval,
> -                 struct grub_parser_param *parsestate);
> -
> -int
> -grub_script_yylex (union YYSTYPE *yylval, struct grub_parser_param 
> *parsestate)
> -{
> -  int r = -1;
> -
> -  while (r == -1)
> -    {
> -      r = grub_script_yylex2 (yylval, parsestate);
> -      if (r == ' ')
> -     r = -1;
> -    }
> -  return r;
> -}
> -
> -int
> -grub_script_yylex2 (union YYSTYPE *yylval, struct grub_parser_param 
> *parsestate)
> -{
> -  grub_parser_state_t newstate;
> -  char use;
> -  char *buffer;
> -  char *bp;
> -  struct grub_lexer_param *state = parsestate->lexerstate;
> -
> -  if (state->done)
> -    return 0;
> -
> -  if (! *state->script)
> -    {
> -      /* Check if more tokens are requested by the parser.  */
> -      if ((state->refs
> -        || state->state == GRUB_PARSER_STATE_ESC)
> -       && state->getline)
> -     {
> -       while (!state->script || ! grub_strlen (state->script))
> -         {
> -           grub_free (state->newscript);
> -           state->newscript = 0;
> -           state->getline (&state->newscript);
> -           state->script = state->newscript;
> -           if (! state->script)
> -             return 0;
> -         }
> -       grub_dprintf ("scripting", "token=`\\n'\n");
> -       recordchar (state, '\n');
> -       if (state->state != GRUB_PARSER_STATE_ESC)
> -         return '\n';
> -     }
> -      else
> -     {
> -       grub_free (state->newscript);
> -       state->newscript = 0;
> -       state->done = 1;
> -       grub_dprintf ("scripting", "token=`\\n'\n");
> -       return '\n';
> -     }
> -    }
> -
> -  newstate = grub_parser_cmdline_state (state->state, *state->script, &use);
> -
> -  /* Check if it is a text.  */
> -  if (check_textstate (newstate))
> -    {
> -      /* In case the string is not quoted, this can be a one char
> -      length symbol.  */
> -      if (newstate == GRUB_PARSER_STATE_TEXT)
> -     {
> -       switch (*state->script)
> -         {
> -         case ' ':
> -           while (*state->script)
> -             {
> -               newstate = grub_parser_cmdline_state (state->state,
> -                                                     *state->script, &use);
> -               if (! (state->state == GRUB_PARSER_STATE_TEXT
> -                      && *state->script == ' '))
> -                 {
> -                   grub_dprintf ("scripting", "token=` '\n");
> -                   return ' ';
> -                 }
> -               state->state = newstate;
> -               nextchar (state);
> -             }
> -           grub_dprintf ("scripting", "token=` '\n");
> -           return ' ';
> -         case '{':
> -         case '}':
> -         case ';':
> -         case '\n':
> -           {
> -             char c;
> -             grub_dprintf ("scripting", "token=`%c'\n", *state->script);
> -             c = *state->script;;
> -             nextchar (state);
> -             return c;
> -           }
> -         }
> -     }
> -
> -      /* XXX: Use a better size.  */
> -      buffer = grub_script_malloc (parsestate, 2048);
> -      if (! buffer)
> -     return 0;
> -
> -      bp = buffer;
> -
> -      /* Read one token, possible quoted.  */
> -      while (*state->script)
> -     {
> -       newstate = grub_parser_cmdline_state (state->state,
> -                                             *state->script, &use);
> -
> -       /* Check if a variable name starts.  */
> -       if (check_varstate (newstate))
> -         break;
> -
> -       /* If the string is not quoted or escaped, stop processing
> -          when a special token was found.  It will be recognized
> -          next time when this function is called.  */
> -       if (newstate == GRUB_PARSER_STATE_TEXT
> -           && state->state != GRUB_PARSER_STATE_ESC)
> -         {
> -           int breakout = 0;
> -
> -           switch (use)
> -             {
> -             case ' ':
> -             case '{':
> -             case '}':
> -             case ';':
> -             case '\n':
> -               breakout = 1;
> -             }
> -           if (breakout)
> -             break;
> -           *(bp++) = use;
> -         }
> -       else if (use)
> -         *(bp++) = use;
> -
> -       state->state = newstate;
> -       nextchar (state);
> -     }
> -
> -      /* A string of text was read in.  */
> -      *bp = '\0';
> -      grub_dprintf ("scripting", "token=`%s'\n", buffer);
> -      yylval->string = buffer;
> -
> -      /* Detect some special tokens.  */
> -      if (! grub_strcmp (buffer, "while"))
> -     return GRUB_PARSER_TOKEN_WHILE;
> -      else if (! grub_strcmp (buffer, "if"))
> -     return GRUB_PARSER_TOKEN_IF;
> -      else if (! grub_strcmp (buffer, "function"))
> -     return GRUB_PARSER_TOKEN_FUNCTION;
> -      else if (! grub_strcmp (buffer, "menuentry"))
> -     return GRUB_PARSER_TOKEN_MENUENTRY;
> -      else if (! grub_strcmp (buffer, "@"))
> -     return GRUB_PARSER_TOKEN_MENUENTRY;
> -      else if (! grub_strcmp (buffer, "else"))
> -     return GRUB_PARSER_TOKEN_ELSE;
> -      else if (! grub_strcmp (buffer, "then"))
> -     return GRUB_PARSER_TOKEN_THEN;
> -      else if (! grub_strcmp (buffer, "fi"))
> -     return GRUB_PARSER_TOKEN_FI;
> -      else
> -     return GRUB_PARSER_TOKEN_NAME;
> -    }
> -  else if (newstate == GRUB_PARSER_STATE_VAR
> -        || newstate == GRUB_PARSER_STATE_QVAR)
> -    {
> -      /* XXX: Use a better size.  */
> -      buffer = grub_script_malloc (parsestate, 2096);
> -      if (! buffer)
> -     return 0;
> -
> -      bp = buffer;
> -
> -      /* This is a variable, read the variable name.  */
> -      while (*state->script)
> -     {
> -       newstate = grub_parser_cmdline_state (state->state,
> -                                             *state->script, &use);
> -
> -       /* Check if this character is not part of the variable name
> -          anymore.  */
> -       if (! (check_varstate (newstate)))
> -         {
> -           if (state->state == GRUB_PARSER_STATE_VARNAME2
> -               || state->state == GRUB_PARSER_STATE_QVARNAME2)
> -             nextchar (state);
> -           state->state = newstate;
> -           break;
> -         }
> -
> -       if (use)
> -         *(bp++) = use;
> -       nextchar (state);
> -       state->state = newstate;
> -     }
> -
> -      *bp = '\0';
> -      state->state = newstate;
> -      yylval->string = buffer;
> -      grub_dprintf ("scripting", "vartoken=`%s'\n", buffer);
> -
> -      return GRUB_PARSER_TOKEN_VAR;
> -    }
> -  else
> -    {
> -      /* There is either text or a variable name.  In the case you
> -      arrive here there is a serious problem with the lexer.  */
> -      grub_error (GRUB_ERR_BAD_ARGUMENT, "Internal error\n");
> -      return 0;
> -    }
> -}
> -
> -void
> -grub_script_yyerror (struct grub_parser_param *lex __attribute__ ((unused)),
> -                  char const *err)
> -{
> -  grub_printf ("%s\n", err);
> -}
> 
> Modified: trunk/grub2/normal/main.c
> ===================================================================
> --- trunk/grub2/normal/main.c 2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/main.c 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -20,20 +20,15 @@
>  #include <grub/kernel.h>
>  #include <grub/normal.h>
>  #include <grub/dl.h>
> -#include <grub/rescue.h>
>  #include <grub/misc.h>
>  #include <grub/file.h>
>  #include <grub/mm.h>
>  #include <grub/term.h>
>  #include <grub/env.h>
>  #include <grub/parser.h>
> -#include <grub/script.h>
> +#include <grub/reader.h>
>  #include <grub/menu_viewer.h>
>  
> -grub_jmp_buf grub_exit_env;
> -
> -static grub_fs_module_list_t fs_module_list = 0;
> -
>  #define GRUB_DEFAULT_HISTORY_SIZE    50
>  
>  /* Read a line from the file FILE.  */
> @@ -43,7 +38,6 @@
>    char c;
>    int pos = 0;
>    int literal = 0;
> -  int comment = 0;
>    char *cmdline;
>    int max_len = 64;
>  
> @@ -84,16 +78,9 @@
>        if (c == '\\')
>       literal = 1;
>  
> -      if (comment)
> +      if (pos == 0)
>       {
> -       if (c == '\n')
> -         comment = 0;
> -     }
> -      else if (pos == 0)
> -     {
> -       if (c == '#')
> -         comment = 1;
> -       else if (! grub_isspace (c))
> +       if (! grub_isspace (c))
>           cmdline[pos++] = c;
>       }
>        else
> @@ -138,7 +125,6 @@
>      {
>        grub_menu_entry_t next_entry = entry->next;
>  
> -      grub_script_free (entry->commands);
>        grub_free ((void *) entry->title);
>        grub_free ((void *) entry->sourcecode);
>        entry = next_entry;
> @@ -164,8 +150,8 @@
>  }
>  
>  grub_err_t
> -grub_normal_menu_addentry (int argc, const char **args,
> -                           struct grub_script *script, const char 
> *sourcecode)
> +grub_menu_addentry (int argc, const char **args,
> +                 const char *sourcecode)
>  {
>    const char *menutitle = 0;
>    const char *menusourcecode;
> @@ -237,7 +223,7 @@
>             /* Handle invalid argument.  */
>             failed = 1;
>             grub_error (GRUB_ERR_MENU,
> -                          "invalid argument for menuentry: %s", args[i]);
> +                       "invalid argument for menuentry: %s", args[i]);
>             break;
>           }
>       }
> @@ -251,7 +237,7 @@
>       {
>         failed = 1;
>         grub_error (GRUB_ERR_MENU,
> -                      "too many titles for menuentry: %s", args[i]);
> +                   "too many titles for menuentry: %s", args[i]);
>         break;
>       }
>      }
> @@ -287,7 +273,6 @@
>        return grub_errno;
>      }
>  
> -  (*last)->commands = script;
>    (*last)->title = menutitle;
>    (*last)->classes = classes_head;
>    (*last)->next = 0;
> @@ -299,35 +284,72 @@
>  }
>  
>  static grub_menu_t
> -read_config_file (const char *config, int nested)
> +read_config_file (const char *config)
>  {
>    grub_file_t file;
> -  auto grub_err_t getline (char **line);
> -  int currline = 0;
> -  int errors = 0;
> +  grub_parser_t old_parser = 0;
>    
> -  grub_err_t getline (char **line)
> +  auto grub_err_t getline (char **line, int cont);
> +  grub_err_t getline (char **line, int cont __attribute__ ((unused)))
>      {
> -      currline++;
> +      while (1)
> +     {
> +       char *buf;
>  
> -      *line = grub_file_getline (file);
> -      if (! *line)
> -     return grub_errno;
> +       *line = buf = grub_file_getline (file);
> +       if (! buf)
> +         return grub_errno;
>  
> +       if (buf[0] == '#')
> +         {
> +           if (buf[1] == '!')
> +             {
> +               grub_parser_t parser;
> +               grub_named_list_t list;
> +
> +               buf += 2;
> +               while (grub_isspace (*buf))
> +                 buf++;
> +
> +               if (! old_parser)
> +                 old_parser = grub_parser_get_current ();
> +
> +               list = GRUB_AS_NAMED_LIST (grub_parser_class.handler_list);
> +               parser = grub_named_list_find (list, buf);
> +               if (parser)
> +                 grub_parser_set_current (parser);
> +               else
> +                 {
> +                   char cmd_name[8 + grub_strlen (buf)];
> +
> +                   /* Perhaps it's not loaded yet, try the autoload
> +                      command.  */
> +                   grub_strcpy (cmd_name, "parser.");
> +                   grub_strcat (cmd_name, buf);
> +                   grub_command_execute (cmd_name, 0, 0);
> +                 }
> +             }
> +           grub_free (*line);
> +         }
> +       else
> +         break;
> +     }
> +
>        return GRUB_ERR_NONE;
>      }
>  
>    grub_menu_t newmenu;
>  
>    newmenu = grub_env_get_data_slot ("menu");
> -
> -  if (nested || ! newmenu)
> +  if (! newmenu)
>      {
>        newmenu = grub_malloc (sizeof (*newmenu));
>        if (! newmenu)
>       return 0;
>        newmenu->size = 0;
>        newmenu->entry_list = 0;
> +
> +      grub_env_set_data_slot ("menu", newmenu);
>      }
>  
>    /* Try to open the config file.  */
> @@ -335,58 +357,15 @@
>    if (! file)
>      return 0;
>  
> -  grub_env_set_data_slot ("menu", newmenu);
> -
> -  while (1)
> -    {
> -      struct grub_script *parsed_script;
> -      int startline;
> -      char *cmdline;
> -
> -      cmdline = grub_file_getline (file);
> -      if (!cmdline)
> -     break;
> -
> -      startline = ++currline;
> -
> -      /* Execute the script, line for line.  */
> -      parsed_script = grub_script_parse (cmdline, getline);
> -
> -      grub_free (cmdline);
> -
> -      if (! parsed_script)
> -     {
> -       grub_printf ("(line %d-%d)\n", startline, currline);
> -       errors++;
> -       continue;
> -     }
> -
> -      /* Execute the command(s).  */
> -      grub_script_execute (parsed_script);
> -
> -      /* Ignore errors.  */
> -      grub_errno = GRUB_ERR_NONE;
> -
> -      /* The parsed script was executed, throw it away.  */
> -      grub_script_free (parsed_script);
> -    }
> -
> +  grub_reader_loop (getline);
>    grub_file_close (file);
>  
> -  if (errors > 0)
> -    grub_wait_after_message ();
> +  if (old_parser)
> +    grub_parser_set_current (old_parser);
>  
>    return newmenu;
>  }
>  
> -/* This starts the normal mode.  */
> -void
> -grub_enter_normal_mode (const char *config)
> -{
> -  if (grub_setjmp (grub_exit_env) == 0)
> -    grub_normal_execute (config, 0, 0);
> -}
> -
>  /* Initialize the screen.  */
>  void
>  grub_normal_init_page (void)
> @@ -409,238 +388,8 @@
>  #undef TITLE
>  }
>  
> -static grub_err_t
> -grub_dyncmd_dispatcher (struct grub_command *cmd,
> -                     int argc, char **args)
> -{
> -  char *modname = cmd->data;
> -  grub_dl_t mod;
> -  grub_err_t ret;
> +static int reader_nested;
>  
> -  mod = grub_dl_load (modname);
> -  if (mod)
> -    {
> -      char *name;
> -
> -      grub_free (modname);
> -      grub_dl_ref (mod);
> -
> -      name = (char *) cmd->name;
> -      grub_unregister_command (cmd);
> -
> -      cmd = grub_command_find (name);
> -      if (cmd)
> -     ret = (cmd->func) (cmd, argc, args);
> -      else
> -     ret = grub_errno;
> -
> -      grub_free (name);
> -    }
> -  else
> -    ret = grub_errno;
> -
> -  return ret;
> -}
> -
> -/* Read the file command.lst for auto-loading.  */
> -static void
> -read_command_list (void)
> -{
> -  const char *prefix;
> -  static int first_time = 1;
> -
> -  /* Make sure that this function does not get executed twice.  */
> -  if (! first_time)
> -    return;
> -  first_time = 0;
> -    
> -  prefix = grub_env_get ("prefix");
> -  if (prefix)
> -    {
> -      char *filename;
> -
> -      filename = grub_malloc (grub_strlen (prefix) + sizeof 
> ("/command.lst"));
> -      if (filename)
> -     {
> -       grub_file_t file;
> -       
> -       grub_sprintf (filename, "%s/command.lst", prefix);
> -       file = grub_file_open (filename);
> -       if (file)
> -         {
> -           char *buf = 0;
> -           for (;; grub_free(buf))
> -             {
> -               char *p, *name, *modname;
> -               grub_command_t cmd;
> -               int prio = 0;
> -
> -               buf = grub_file_getline (file);
> -
> -               if (! buf)
> -                 break;
> -               
> -               name = buf;
> -               if (*name == '*')
> -                 {
> -                   name++;
> -                   prio++;
> -                 }
> -
> -               if (! grub_isgraph (name[0]))
> -                 continue;
> -
> -               p = grub_strchr (name, ':');
> -               if (! p)
> -                 continue;
> -
> -               *p = '\0';
> -               while (*++p == ' ')
> -                 ;
> -
> -               if (! grub_isgraph (*p))
> -                 continue;
> -
> -               if (grub_dl_get (p))
> -                 continue;
> -
> -               name = grub_strdup (name);
> -               if (! name)
> -                 continue;
> -
> -               modname = grub_strdup (p);
> -               if (! modname)
> -                 {
> -                   grub_free (name);
> -                   continue;
> -                 }
> -
> -               cmd = grub_register_command_prio (name,
> -                                                 grub_dyncmd_dispatcher,
> -                                                 0, "not loaded", prio);
> -               if (! cmd)
> -                 {
> -                   grub_free (name);
> -                   grub_free (modname);
> -                   continue;
> -                 }
> -               cmd->flags |= GRUB_COMMAND_FLAG_DYNCMD;
> -               cmd->data = modname;
> -
> -               /* Update the active flag.  */
> -               grub_command_find (name);
> -             }
> -
> -           grub_file_close (file);
> -         }
> -
> -       grub_free (filename);
> -     }
> -    }
> -
> -  /* Ignore errors.  */
> -  grub_errno = GRUB_ERR_NONE;
> -}
> -
> -/* The auto-loading hook for filesystems.  */
> -static int
> -autoload_fs_module (void)
> -{
> -  grub_fs_module_list_t p;
> -
> -  while ((p = fs_module_list) != 0)
> -    {
> -      if (! grub_dl_get (p->name) && grub_dl_load (p->name))
> -     return 1;
> -
> -      fs_module_list = p->next;
> -      grub_free (p->name);
> -      grub_free (p);
> -    }
> -
> -  return 0;
> -}
> -
> -/* Read the file fs.lst for auto-loading.  */
> -static void
> -read_fs_list (void)
> -{
> -  const char *prefix;
> -  static int first_time = 1;
> -
> -  /* Make sure that this function does not get executed twice.  */
> -  if (! first_time)
> -    return;
> -  first_time = 0;
> -  
> -  prefix = grub_env_get ("prefix");
> -  if (prefix)
> -    {
> -      char *filename;
> -
> -      filename = grub_malloc (grub_strlen (prefix) + sizeof ("/fs.lst"));
> -      if (filename)
> -     {
> -       grub_file_t file;
> -       
> -       grub_sprintf (filename, "%s/fs.lst", prefix);
> -       file = grub_file_open (filename);
> -       if (file)
> -         {
> -           while (1)
> -             {
> -               char *buf;
> -               char *p;
> -               char *q;
> -               grub_fs_module_list_t fs_mod;
> -               
> -               buf = grub_file_getline (file);
> -               if (! buf)
> -                 break;
> -
> -               p = buf;
> -               q = buf + grub_strlen (buf) - 1;
> -
> -               /* Ignore space.  */
> -               while (grub_isspace (*p))
> -                 p++;
> -
> -               while (p < q && grub_isspace (*q))
> -                 *q-- = '\0';
> -
> -               /* If the line is empty, skip it.  */
> -               if (p >= q)
> -                 continue;
> -
> -               fs_mod = grub_malloc (sizeof (*fs_mod));
> -               if (! fs_mod)
> -                 continue;
> -
> -               fs_mod->name = grub_strdup (p);
> -               if (! fs_mod->name)
> -                 {
> -                   grub_free (fs_mod);
> -                   continue;
> -                 }
> -
> -               fs_mod->next = fs_module_list;
> -               fs_module_list = fs_mod;
> -             }
> -
> -           grub_file_close (file);
> -         }
> -
> -       grub_free (filename);
> -     }
> -    }
> -
> -  /* Ignore errors.  */
> -  grub_errno = GRUB_ERR_NONE;
> -
> -  /* Set the hook.  */
> -  grub_fs_autoload_hook = autoload_fs_module;
> -}
> -
>  /* Read the config file COFIG, and execute the menu interface or
>     the command-line interface if BATCH is false.  */
>  void
> @@ -651,10 +400,13 @@
>    read_command_list ();
>    read_fs_list ();
>    read_handler_list ();
> +  grub_command_execute ("parser.sh", 0, 0);
> +
> +  reader_nested = nested;
>    
>    if (config)
>      {
> -      menu = read_config_file (config, nested);
> +      menu = read_config_file (config);
>  
>        /* Ignore any error.  */
>        grub_errno = GRUB_ERR_NONE;
> @@ -663,40 +415,28 @@
>    if (! batch)
>      {
>        if (menu && menu->size)
> -        {
> -          grub_menu_viewer_show_menu (menu, nested);
> -          if (nested)
> -            free_menu (menu);
> -        }
> -      else
> -        grub_cmdline_run (nested);
> +     {
> +       grub_menu_viewer_show_menu (menu, nested);
> +       if (nested)
> +         free_menu (menu);
> +     }
>      }
>  }
>  
> -static grub_err_t
> -grub_cmd_rescue (struct grub_command *cmd __attribute__ ((unused)),
> -              int argc __attribute__ ((unused)),
> -              char **args __attribute__ ((unused)))
> +/* This starts the normal mode.  */
> +void
> +grub_enter_normal_mode (const char *config)
>  {
> -  grub_longjmp (grub_exit_env, 0);
> -
> -  /* Never reach here.  */
> -  return 0;
> +  grub_normal_execute (config, 0, 0);
>  }
>  
> -static grub_command_t cmd_normal;
> -
>  /* Enter normal mode from rescue mode.  */
>  static grub_err_t
> -grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
> +grub_cmd_normal (struct grub_command *cmd,
>                int argc, char *argv[])
>  {
> -  grub_command_t cmd_rescue;
> +  grub_unregister_command (cmd);
>  
> -  grub_unregister_command (cmd_normal);
> -  cmd_rescue = grub_register_command ("rescue", grub_cmd_rescue,
> -                                   0, "enter rescue mode");
> -
>    if (argc == 0)
>      {
>        /* Guess the config filename. It is necessary to make CONFIG static,
> @@ -722,12 +462,77 @@
>      grub_enter_normal_mode (argv[0]);
>  
>  quit:
> -  grub_unregister_command (cmd_rescue);
> -  cmd_normal = grub_register_command_prio ("normal", grub_cmd_normal,
> -                                        0, "enter normal mode", 0);
>    return 0;
>  }
>  
> +void
> +grub_cmdline_run (int nested)
> +{
> +  grub_reader_t reader = grub_reader_get_current ();
> +
> +  reader_nested = nested;
> +  if (reader->init)
> +    reader->init ();
> +  grub_reader_loop (0);
> +}
> +
> +static grub_err_t
> +grub_normal_reader_init (void)
> +{
> +  grub_normal_init_page ();
> +  grub_setcursor (1);
> +
> +  grub_printf ("\
> + [ Minimal BASH-like line editing is supported. For the first word, TAB\n\
> +   lists possible command completions. Anywhere else TAB lists possible\n\
> +   device/file completions.%s ]\n\n",
> +            reader_nested ? " ESC at any time exits." : "");
> +
> +  return 0;
> +}
> +
> +static char cmdline[GRUB_MAX_CMDLINE];
> +
> +static grub_err_t
> +grub_normal_read_line (char **line, int cont)
> +{
> +  grub_parser_t parser = grub_parser_get_current ();
> +  char prompt[8 + grub_strlen (parser->name)];
> +
> +  grub_sprintf (prompt, "%s:%s> ", parser->name, (cont) ? "" : "grub");
> +
> +  while (1)
> +    {
> +      cmdline[0] = 0;
> +      if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1))
> +     break;
> +
> +      if ((reader_nested) || (cont))
> +     {
> +       *line = 0;
> +       return grub_errno;
> +     }
> +    }
> +
> +  *line = grub_strdup (cmdline);
> +  return 0;
> +}
> +
> +static struct grub_reader grub_normal_reader =
> +  {
> +    .name = "normal",
> +    .init = grub_normal_reader_init,
> +    .read_line = grub_normal_read_line
> +  };
> +
> +static char *
> +grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
> +                   const char *val)
> +{
> +  grub_set_more ((*val == '1'));
> +  return grub_strdup (val);
> +}
> +
>  GRUB_MOD_INIT(normal)
>  {
>    /* Normal mode shouldn't be unloaded.  */
> @@ -738,9 +543,13 @@
>  
>    grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
>  
> +  grub_reader_register ("normal", &grub_normal_reader);
> +  grub_reader_set_current (&grub_normal_reader);
> +  grub_register_variable_hook ("pager", 0, grub_env_write_pager);
> +
>    /* Register a command "normal" for the rescue mode.  */
> -  cmd_normal = grub_register_command ("normal", grub_cmd_normal,
> -                                   0, "enter normal mode");
> +  grub_register_command_prio ("normal", grub_cmd_normal,
> +                           0, "Enter normal mode", 0);
>  
>    /* Reload terminal colors when these variables are written to.  */
>    grub_register_variable_hook ("color_normal", NULL, 
> grub_env_write_color_normal);
> @@ -754,6 +563,8 @@
>  GRUB_MOD_FINI(normal)
>  {
>    grub_set_history (0);
> -  grub_unregister_command (cmd_normal);
> +  grub_reader_unregister (&grub_normal_reader);
> +  grub_register_variable_hook ("pager", 0, 0);
> +  grub_fs_autoload_hook = 0;
>    free_handler_list ();
>  }
> 
> Modified: trunk/grub2/normal/menu.c
> ===================================================================
> --- trunk/grub2/normal/menu.c 2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/menu.c 2009-05-02 19:49:34 UTC (rev 2158)
> @@ -23,8 +23,8 @@
>  #include <grub/mm.h>
>  #include <grub/time.h>
>  #include <grub/env.h>
> -#include <grub/script.h>
>  #include <grub/menu_viewer.h>
> +#include <grub/command.h>
>  
>  /* Get a menu entry by its index in the entry list.  */
>  grub_menu_entry_t
> @@ -123,11 +123,11 @@
>  void
>  grub_menu_execute_entry(grub_menu_entry_t entry)
>  {
> -  grub_script_execute (entry->commands);
> +  grub_parser_execute ((char *) entry->sourcecode);
>  
>    if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
>      /* Implicit execution of boot, only if something is loaded.  */
> -    grub_command_execute ("boot", 0);
> +    grub_command_execute ("boot", 0, 0);
>  }
>  
>  /* Execute ENTRY from the menu MENU, falling back to entries specified
> 
> Modified: trunk/grub2/normal/menu_entry.c
> ===================================================================
> --- trunk/grub2/normal/menu_entry.c   2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/menu_entry.c   2009-05-02 19:49:34 UTC (rev 2158)
> @@ -21,7 +21,8 @@
>  #include <grub/misc.h>
>  #include <grub/mm.h>
>  #include <grub/loader.h>
> -#include <grub/script.h>
> +#include <grub/command.h>
> +#include <grub/parser.h>
>  
>  enum update_mode
>    {
> @@ -970,12 +971,11 @@
>  static int
>  run (struct screen *screen)
>  {
> -  struct grub_script *parsed_script = 0;
>    int currline = 0;
>    char *nextline;
>  
> -  auto grub_err_t editor_getline (char **line);
> -  grub_err_t editor_getline (char **line)
> +  auto grub_err_t editor_getline (char **line, int cont);
> +  grub_err_t editor_getline (char **line, int cont __attribute__ ((unused)))
>      {
>        struct line *linep = screen->lines + currline;
>        char *p;
> @@ -1008,23 +1008,14 @@
>    /* Execute the script, line for line.  */
>    while (currline < screen->num_lines)
>      {
> -      editor_getline (&nextline);
> -      parsed_script = grub_script_parse (nextline, editor_getline);
> -      if (parsed_script)
> -     {
> -       /* Execute the command(s).  */
> -       grub_script_execute (parsed_script);
> -       
> -       /* The parsed script was executed, throw it away.  */
> -       grub_script_free (parsed_script);
> -     }
> -      else
> +      editor_getline (&nextline, 0);
> +      if (grub_parser_get_current ()->parse_line (nextline, editor_getline))
>       break;
>      }
>  
>    if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
>      /* Implicit execution of boot, only if something is loaded.  */
> -    grub_command_execute ("boot", 0);
> +    grub_command_execute ("boot", 0, 0);
>  
>    if (grub_errno != GRUB_ERR_NONE)
>      {
> 
> Modified: trunk/grub2/normal/menu_text.c
> ===================================================================
> --- trunk/grub2/normal/menu_text.c    2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/menu_text.c    2009-05-02 19:49:34 UTC (rev 2158)
> @@ -24,7 +24,6 @@
>  #include <grub/mm.h>
>  #include <grub/time.h>
>  #include <grub/env.h>
> -#include <grub/script.h>
>  #include <grub/menu_viewer.h>
>  
>  /* Time to delay after displaying an error message about a default/fallback
> 
> Deleted: trunk/grub2/normal/parser.y
> ===================================================================
> --- trunk/grub2/normal/parser.y       2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/parser.y       2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,238 +0,0 @@
> -/* parser.y - The scripting parser.  */
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2005,2006,2007,2008,2009  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -%{
> -#include <grub/script.h>
> -#include <grub/mm.h>
> -
> -#define YYFREE               grub_free
> -#define YYMALLOC     grub_malloc
> -#define YYLTYPE_IS_TRIVIAL      0
> -#define YYENABLE_NLS 0
> -
> -%}
> -
> -%union {
> -  struct grub_script_cmd *cmd;
> -  struct grub_script_arglist *arglist;
> -  struct grub_script_arg *arg;
> -  char *string;
> -}
> -
> -%token GRUB_PARSER_TOKEN_IF          "if"
> -%token GRUB_PARSER_TOKEN_WHILE               "while"
> -%token GRUB_PARSER_TOKEN_FUNCTION    "function"
> -%token GRUB_PARSER_TOKEN_MENUENTRY   "menuentry"
> -%token GRUB_PARSER_TOKEN_ELSE                "else"
> -%token GRUB_PARSER_TOKEN_THEN                "then"
> -%token GRUB_PARSER_TOKEN_FI          "fi"
> -%token GRUB_PARSER_TOKEN_NAME
> -%token GRUB_PARSER_TOKEN_VAR
> -%type <cmd> script_init script grubcmd command commands commandblock 
> menuentry if
> -%type <arglist> arguments;
> -%type <arg> argument;
> -%type <string> "if" "while" "function" "else" "then" "fi"
> -%type <string> text GRUB_PARSER_TOKEN_NAME GRUB_PARSER_TOKEN_VAR
> -
> -%pure-parser
> -%lex-param { struct grub_parser_param *state };
> -%parse-param { struct grub_parser_param *state };
> -
> -%%
> -/* It should be possible to do this in a clean way...  */
> -script_init: { state->err = 0; } script
> -               {
> -                 state->parsed = $2;
> -               }
> -;
> -
> -script:              commands { $$ = $1; }
> -             | function '\n' { $$ = 0; }
> -             | menuentry '\n' { $$ = $1; }
> -;
> -
> -delimiter:   '\n'
> -             | ';'
> -             | delimiter '\n'
> -;
> -
> -newlines:    /* Empty */
> -             | newlines '\n'
> -;
> -
> -/* Some tokens are both used as token or as plain text.  XXX: Add all
> -   tokens without causing conflicts.  */
> -text:                GRUB_PARSER_TOKEN_NAME
> -               {
> -                 $$ = $1;
> -               }
> -             | "if"
> -               {
> -                 $$ = $1;
> -               }
> -             | "while"
> -               {
> -                 $$ = $1;
> -               }
> -;
> -
> -/* An argument can consist of some static text mixed with variables,
> -   for example: `foo${bar}baz'.  */
> -argument:    GRUB_PARSER_TOKEN_VAR
> -               {
> -                 $$ = grub_script_arg_add (state, 0, 
> GRUB_SCRIPT_ARG_TYPE_VAR, $1);
> -               }
> -             | text
> -               {
> -                 $$ = grub_script_arg_add (state, 0, 
> GRUB_SCRIPT_ARG_TYPE_STR, $1);
> -               }
> -/* XXX: Currently disabled to simplify the parser.  This should be
> -   parsed by yet another parser for readability.  */
> -/*           | argument GRUB_PARSER_TOKEN_VAR */
> -/*             { */
> -/*               $$ = grub_script_arg_add ($1, GRUB_SCRIPT_ARG_TYPE_VAR, 
> $2); */
> -/*             } */
> -/*           | argument text */
> -/*             { */
> -/*               $$ = grub_script_arg_add ($1, GRUB_SCRIPT_ARG_TYPE_STR, 
> $2); */
> -/*             } */
> -;
> -
> -arguments:   argument
> -               {
> -                 $$ = grub_script_add_arglist (state, 0, $1);
> -               }
> -             | arguments argument
> -               {
> -                 $$ = grub_script_add_arglist (state, $1, $2);
> -               }
> -;
> -
> -grubcmd:     GRUB_PARSER_TOKEN_NAME arguments
> -               {
> -                 $$ = grub_script_create_cmdline (state, $1, $2);
> -               }
> -             | GRUB_PARSER_TOKEN_NAME
> -               {
> -                 $$ = grub_script_create_cmdline (state, $1, 0);
> -               }
> -;
> -
> -/* A single command.  */
> -command:     grubcmd delimiter { $$ = $1; }
> -             | if delimiter  { $$ = $1; }
> -             | commandblock delimiter { $$ = $1; }
> -             | error delimiter
> -               {
> -                 $$ = 0;
> -                 yyerror (state, "Incorrect command");
> -                 state->err = 1;
> -                 yyerrok;
> -               }
> -;
> -
> -/* A block of commands.  */
> -commands:    command
> -               {
> -                 $$ = grub_script_add_cmd (state, 0, $1);
> -               }
> -             | command commands
> -               {
> -                 struct grub_script_cmdblock *cmd;
> -                 cmd = (struct grub_script_cmdblock *) $2;
> -                 $$ = grub_script_add_cmd (state, cmd, $1);
> -               }
> -;
> -
> -/* A function.  Carefully save the memory that is allocated.  Don't
> -   change any stuff because it might seem like a fun thing to do!
> -   Special care was take to make sure the mid-rule actions are
> -   executed on the right moment.  So the `commands' rule should be
> -   recognized after executing the `grub_script_mem_record; and before
> -   `grub_script_mem_record_stop'.  */
> -function:    "function" GRUB_PARSER_TOKEN_NAME
> -               { 
> -                 grub_script_lexer_ref (state->lexerstate);
> -               } newlines '{'
> -               { 
> -                 /* The first part of the function was recognized.
> -                    Now start recording the memory usage to store
> -                    this function.  */
> -                 state->func_mem = grub_script_mem_record (state);
> -               } newlines commands '}'
> -               {
> -                 struct grub_script *script;
> -
> -                 /* All the memory usage for parsing this function
> -                    was recorded.  */
> -                 state->func_mem = grub_script_mem_record_stop (state,
> -                                                                
> state->func_mem);
> -                 script = grub_script_create ($8, state->func_mem);
> -                 if (script)
> -                   grub_script_function_create ($2, script);
> -                 grub_script_lexer_deref (state->lexerstate);
> -               }
> -;
> -
> -/* Carefully designed, together with `menuentry' so everything happens
> -   just in the expected order.  */
> -commandblock:        '{'
> -               {
> -                 grub_script_lexer_ref (state->lexerstate);
> -               }
> -                newlines commands '}'
> -                  {
> -                 grub_script_lexer_deref (state->lexerstate);
> -                 $$ = $4;
> -               }
> -;
> -
> -/* A menu entry.  Carefully save the memory that is allocated.  */
> -menuentry:   "menuentry" arguments
> -               {
> -                 grub_script_lexer_ref (state->lexerstate);
> -               } newlines '{'
> -               {
> -                 grub_script_lexer_record_start (state->lexerstate);
> -               } newlines commands '}'
> -               {
> -                 char *menu_entry;
> -                 menu_entry = grub_script_lexer_record_stop 
> (state->lexerstate);
> -                 grub_script_lexer_deref (state->lexerstate);
> -                 $$ = grub_script_create_cmdmenu (state, $2, menu_entry, 0);
> -               }
> -;
> -
> -/* The first part of the if statement.  It's used to switch the lexer
> -   to a state in which it demands more tokens.  */
> -if_statement:        "if" { grub_script_lexer_ref (state->lexerstate); }
> -;
> -
> -/* The if statement.  */
> -if:           if_statement commands "then" newlines commands "fi"
> -               {
> -                 $$ = grub_script_create_cmdif (state, $2, $5, 0);
> -                 grub_script_lexer_deref (state->lexerstate);
> -               }
> -              | if_statement commands "then" newlines commands "else" 
> newlines commands  "fi"
> -               {
> -                 $$ = grub_script_create_cmdif (state, $2, $5, $8);
> -                 grub_script_lexer_deref (state->lexerstate);
> -               }
> -;
> 
> Deleted: trunk/grub2/normal/script.c
> ===================================================================
> --- trunk/grub2/normal/script.c       2009-05-02 16:55:35 UTC (rev 2157)
> +++ trunk/grub2/normal/script.c       2009-05-02 19:49:34 UTC (rev 2158)
> @@ -1,348 +0,0 @@
> -/* script.c -- Functions to create an in memory description of the script. */
> -/*
> - *  GRUB  --  GRand Unified Bootloader
> - *  Copyright (C) 2005,2006,2007,2009  Free Software Foundation, Inc.
> - *
> - *  GRUB is free software: you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation, either version 3 of the License, or
> - *  (at your option) any later version.
> - *
> - *  GRUB is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <grub/misc.h>
> -#include <grub/script.h>
> -#include <grub/parser.h>
> -#include <grub/mm.h>
> -
> -/* It is not possible to deallocate the memory when a syntax error was
> -   found.  Because of that it is required to keep track of all memory
> -   allocations.  The memory is freed in case of an error, or
> -   assigned to the parsed script when parsing was successful.  */
> -
> -/* XXX */
> -
> -/* In case of the normal malloc, some additional bytes are allocated
> -   for this datastructure.  All reserved memory is stored in a linked
> -   list so it can be easily freed.  The original memory can be found
> -   from &mem.  */
> -struct grub_script_mem
> -{
> -  struct grub_script_mem *next;
> -  char mem;
> -};
> -
> -/* Return malloc'ed memory and keep track of the allocation.  */
> -void *
> -grub_script_malloc (struct grub_parser_param *state, grub_size_t size)
> -{
> -  struct grub_script_mem *mem;
> -  mem = (struct grub_script_mem *) grub_malloc (size + sizeof (*mem)
> -                                             - sizeof (char));
> -
> -  grub_dprintf ("scripting", "malloc %p\n", mem);
> -  mem->next = state->memused;
> -  state->memused = mem;
> -  return (void *) &mem->mem;
> -}
> -
> -/* Free all memory described by MEM.  */
> -static void
> -grub_script_mem_free (struct grub_script_mem *mem)
> -{
> -  struct grub_script_mem *memfree;
> -
> -  while (mem)
> -    {
> -      memfree = mem->next;
> -      grub_dprintf ("scripting", "free %p\n", mem);
> -      grub_free (mem);
> -      mem = memfree;
> -    }
> -}
> -
> -/* Start recording memory usage.  Returns the memory that should be
> -   restored when calling stop.  */
> -struct grub_script_mem *
> -grub_script_mem_record (struct grub_parser_param *state)
> -{
> -  struct grub_script_mem *mem = state->memused;
> -  state->memused = 0;
> -
> -  return mem;
> -}
> -
> -/* Stop recording memory usage.  Restore previous recordings using
> -   RESTORE.  Return the recorded memory.  */
> -struct grub_script_mem *
> -grub_script_mem_record_stop (struct grub_parser_param *state,
> -                          struct grub_script_mem *restore)
> -{
> -  struct grub_script_mem *mem = state->memused;
> -  state->memused = restore;
> -  return mem;
> -}
> -
> -/* Free the memory reserved for CMD and all of it's children.  */
> -void
> -grub_script_free (struct grub_script *script)
> -{
> -  if (! script)
> -    return;
> -  grub_script_mem_free (script->mem);
> -  grub_free (script);
> -}
> -
> -
> -
> -/* Extend the argument arg with a variable or string of text.  If ARG
> -   is zero a new list is created.  */
> -struct grub_script_arg *
> -grub_script_arg_add (struct grub_parser_param *state, struct grub_script_arg 
> *arg,
> -                  grub_script_arg_type_t type, char *str)
> -{
> -  struct grub_script_arg *argpart;
> -  struct grub_script_arg *ll;
> -  
> -  argpart = (struct grub_script_arg *) grub_script_malloc (state, sizeof 
> (*arg));
> -  argpart->type = type;
> -  argpart->str = str;
> -  argpart->next = 0;
> -
> -  if (! arg)
> -    return argpart;
> -
> -  for (ll = arg; ll->next; ll = ll->next);
> -  ll->next = argpart;
> -      
> -  return arg;
> -}
> -
> -/* Add the argument ARG to the end of the argument list LIST.  If LIST
> -   is zero, a new list will be created.  */
> -struct grub_script_arglist *
> -grub_script_add_arglist (struct grub_parser_param *state,
> -                      struct grub_script_arglist *list, struct 
> grub_script_arg *arg)
> -{
> -  struct grub_script_arglist *link;
> -  struct grub_script_arglist *ll;
> -
> -  grub_dprintf ("scripting", "arglist\n");
> -
> -  link = (struct grub_script_arglist *) grub_script_malloc (state, sizeof 
> (*link));
> -  link->next = 0;
> -  link->arg = arg;
> -  link->argcount = 0;
> -
> -  if (! list)
> -    {
> -      link->argcount++;
> -      return link;
> -    }
> -
> -  list->argcount++;
> -
> -  /* Look up the last link in the chain.  */
> -  for (ll = list; ll->next; ll = ll->next);
> -  ll->next = link;
> -
> -  return list;
> -}
> -
> -/* Create a command that describes a single command line.  CMDLINE
> -   contains the name of the command that should be executed.  ARGLIST
> -   holds all arguments for this command.  */
> -struct grub_script_cmd *
> -grub_script_create_cmdline (struct grub_parser_param *state,
> -                         char *cmdname, struct grub_script_arglist *arglist)
> -{
> -  struct grub_script_cmdline *cmd;
> -
> -  grub_dprintf ("scripting", "cmdline\n");
> -
> -  cmd = grub_script_malloc (state, sizeof (*cmd));
> -  cmd->cmd.exec = grub_script_execute_cmdline;
> -  cmd->cmd.next = 0;
> -  cmd->arglist = arglist;
> -  cmd->cmdname = cmdname;
> -
> -  return (struct grub_script_cmd *) cmd;
> -}
> -
> -/* Create a command that functions as an if statement.  If BOOL is
> -   evaluated to true (the value is returned in envvar '?'), the
> -   interpreter will run the command TRUE, otherwise the interpreter
> -   runs the command FALSE.  */
> -struct grub_script_cmd *
> -grub_script_create_cmdif (struct grub_parser_param *state,
> -                       struct grub_script_cmd *exec_to_evaluate,
> -                       struct grub_script_cmd *exec_on_true,
> -                       struct grub_script_cmd *exec_on_false)
> -{
> -  struct grub_script_cmdif *cmd;
> -
> -  grub_dprintf ("scripting", "cmdif\n");
> -
> -  cmd = grub_script_malloc (state, sizeof (*cmd));
> -  cmd->cmd.exec = grub_script_execute_cmdif;
> -  cmd->cmd.next = 0;
> -  cmd->exec_to_evaluate = exec_to_evaluate;
> -  cmd->exec_on_true = exec_on_true;
> -  cmd->exec_on_false = exec_on_false;
> -
> -  return (struct grub_script_cmd *) cmd;
> -}
> -
> -/* Create a command that adds a menu entry to the menu.  Title is an
> -   argument that is parsed to generate a string that can be used as
> -   the title.  The sourcecode for this entry is passed in SOURCECODE.
> -   The options for this entry are passed in OPTIONS.  */
> -struct grub_script_cmd *
> -grub_script_create_cmdmenu (struct grub_parser_param *state,
> -                         struct grub_script_arglist *arglist,
> -                         char *sourcecode,
> -                         int options)
> -{
> -  struct grub_script_cmd_menuentry *cmd;
> -  int i;
> -
> -  /* Skip leading newlines to make the sourcecode better readable when
> -     using the editor.  */
> -  while (*sourcecode == '\n')
> -    sourcecode++;
> -
> -  /* Having trailing returns can some some annoying conflicts, remove
> -     them.  XXX: Can the parser be improved to handle this?  */
> -  for (i = grub_strlen (sourcecode) - 1; i > 0; i--)
> -    {
> -      if (sourcecode[i] != '\n')
> -     break;
> -      sourcecode[i] = '\0';
> -    }
> -
> -  cmd = grub_script_malloc (state, sizeof (*cmd));
> -  cmd->cmd.exec = grub_script_execute_menuentry;
> -  cmd->cmd.next = 0;
> -  /* XXX: Check if this memory is properly freed.  */
> -  cmd->sourcecode = sourcecode;
> -  cmd->arglist = arglist;
> -  cmd->options = options;
> -
> -  return (struct grub_script_cmd *) cmd;
> -}
> -
> -/* Create a block of commands.  CMD contains the command that should
> -   be added at the end of CMDBLOCK's list.  If CMDBLOCK is zero, a new
> -   cmdblock will be created.  */
> -struct grub_script_cmd *
> -grub_script_add_cmd (struct grub_parser_param *state,
> -                  struct grub_script_cmdblock *cmdblock,
> -                  struct grub_script_cmd *cmd)
> -{
> -  grub_dprintf ("scripting", "cmdblock\n");
> -
> -  if (! cmd)
> -    return (struct grub_script_cmd *) cmdblock;
> -
> -  if (! cmdblock)
> -    {
> -      cmdblock = (struct grub_script_cmdblock *) grub_script_malloc (state,
> -                                                                  sizeof 
> (*cmdblock));
> -      cmdblock->cmd.exec = grub_script_execute_cmdblock;
> -      cmdblock->cmd.next = 0;
> -      cmdblock->cmdlist = cmd;
> -      cmd->next = 0;
> -    }
> -  else
> -    {
> -      cmd->next = cmdblock->cmdlist;
> -      cmdblock->cmdlist = cmd;
> -    }
> -
> -  return (struct grub_script_cmd *) cmdblock;
> -}
> -
> -
> -
> -struct grub_script *
> -grub_script_create (struct grub_script_cmd *cmd, struct grub_script_mem *mem)
> -{
> -  struct grub_script *parsed;
> -
> -  parsed = grub_malloc (sizeof (*parsed));
> -  if (! parsed)
> -    {
> -      grub_script_mem_free (mem);
> -      grub_free (cmd);
> -
> -      return 0;
> -    }
> -
> -  parsed->mem = mem;
> -  parsed->cmd = cmd;
> -
> -  return parsed;
> -}
> -
> -/* Parse the script passed in SCRIPT and return the parsed
> -   datastructure that is ready to be interpreted.  */
> -struct grub_script *
> -grub_script_parse (char *script, grub_err_t (*getline) (char **))
> -{
> -  struct grub_script *parsed;
> -  struct grub_script_mem *membackup;
> -  struct grub_lexer_param *lexstate;
> -  struct grub_parser_param *parsestate;
> -
> -  parsed = grub_malloc (sizeof (*parsed));
> -  if (! parsed)
> -    return 0;
> -
> -  parsestate = grub_malloc (sizeof (*parsestate));
> -  if (! parsestate)
> -    return 0;
> -
> -  parsestate->err = 0;
> -  parsestate->func_mem = 0;
> -  parsestate->memused = 0;
> -  parsestate->parsed = 0;
> -
> -  /* Initialize the lexer.  */
> -  lexstate = grub_script_lexer_init (script, getline);
> -  if (! lexstate)
> -    {
> -      grub_free (parsed);
> -      grub_free (parsestate);
> -      return 0;
> -    }
> -
> -  parsestate->lexerstate = lexstate;
> -
> -  membackup = grub_script_mem_record (parsestate);
> -
> -  /* Parse the script.  */
> -  if (grub_script_yyparse (parsestate) || parsestate->err)
> -    {
> -      struct grub_script_mem *memfree;
> -      memfree = grub_script_mem_record_stop (parsestate, membackup);
> -      grub_script_mem_free (memfree);
> -      grub_free (lexstate);
> -      grub_free (parsestate);
> -      return 0;
> -    }
> -
> -  parsed->mem = grub_script_mem_record_stop (parsestate, membackup);
> -  parsed->cmd = parsestate->parsed;
> -
> -  grub_free (lexstate);
> -  grub_free (parsestate);
> -
> -  return parsed;
> -}
> 
> Copied: trunk/grub2/script/sh/execute.c (from rev 2157, 
> trunk/grub2/normal/execute.c)
> ===================================================================
> --- trunk/grub2/script/sh/execute.c                           (rev 0)
> +++ trunk/grub2/script/sh/execute.c   2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,245 @@
> +/* execute.c -- Execute a GRUB script.  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2005,2007,2008,2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/misc.h>
> +#include <grub/mm.h>
> +#include <grub/env.h>
> +#include <grub/script_sh.h>
> +#include <grub/command.h>
> +#include <grub/menu.h>
> +#include <grub/lib/arg.h>
> +#include <grub/normal.h>
> +
> +static grub_err_t
> +grub_script_execute_cmd (struct grub_script_cmd *cmd)
> +{
> +  if (cmd == 0)
> +    return 0;
> +
> +  return cmd->exec (cmd);
> +}
> +
> +/* Parse ARG and return the textual representation.  Add strings are
> +   concatenated and all values of the variables are filled in.  */
> +static char *
> +grub_script_execute_argument_to_string (struct grub_script_arg *arg)
> +{
> +  int size = 0;
> +  char *val;
> +  char *chararg;
> +  struct grub_script_arg *argi;
> +
> +  /* First determine the size of the argument.  */
> +  for (argi = arg; argi; argi = argi->next)
> +    {
> +      if (argi->type == 1)
> +     {
> +       val = grub_env_get (argi->str);
> +       if (val)
> +         size += grub_strlen (val);
> +     }
> +      else
> +     size += grub_strlen (argi->str);
> +    }
> +
> +  /* Create the argument.  */
> +  chararg = grub_malloc (size + 1);
> +  if (! chararg)
> +    return 0;
> +
> +  *chararg = '\0';
> +  /* First determine the size of the argument.  */
> +  for (argi = arg; argi; argi = argi->next)
> +    {
> +      if (argi->type == 1)
> +     {
> +       val = grub_env_get (argi->str);
> +       if (val)
> +         grub_strcat (chararg, val);
> +     }
> +      else
> +     grub_strcat (chararg, argi->str);
> +    }
> +
> +  return chararg;
> +}
> +
> +/* Execute a single command line.  */
> +grub_err_t
> +grub_script_execute_cmdline (struct grub_script_cmd *cmd)
> +{
> +  struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd;
> +  struct grub_script_arglist *arglist;
> +  char **args = 0;
> +  int i = 0;
> +  grub_command_t grubcmd;
> +  grub_err_t ret = 0;
> +  int argcount = 0;
> +  grub_script_function_t func = 0;
> +  char errnobuf[6];
> +
> +  /* Lookup the command.  */
> +  grubcmd = grub_command_find (cmdline->cmdname);
> +  if (! grubcmd)
> +    {
> +      /* Ignore errors.  */
> +      grub_errno = GRUB_ERR_NONE;
> +
> +      /* It's not a GRUB command, try all functions.  */
> +      func = grub_script_function_find (cmdline->cmdname);
> +      if (! func)
> +     {
> +       /* As a last resort, try if it is an assignment.  */
> +       char *assign = grub_strdup (cmdline->cmdname);
> +       char *eq = grub_strchr (assign, '=');
> +
> +       if (eq)
> +         {
> +           /* Create two strings and set the variable.  */
> +           *eq = '\0';
> +           eq++;
> +           grub_env_set (assign, eq);
> +
> +           /* This was set because the command was not found.  */
> +           grub_errno = GRUB_ERR_NONE;
> +         }
> +       grub_free (assign);
> +       return 0;
> +     }
> +    }
> +
> +  if (cmdline->arglist)
> +    {
> +      argcount = cmdline->arglist->argcount;
> +
> +      /* Create argv from the arguments.  */
> +      args = grub_malloc (sizeof (char *) * argcount);
> +      for (arglist = cmdline->arglist; arglist; arglist = arglist->next)
> +     {
> +       char *str;
> +       str = grub_script_execute_argument_to_string (arglist->arg);
> +       args[i++] = str;
> +     }
> +    }
> +
> +  /* Execute the GRUB command or function.  */
> +  if (grubcmd)
> +    ret = (grubcmd->func) (grubcmd, argcount, args);
> +  else
> +    ret = grub_script_function_call (func, argcount, args);
> +
> +  /* Free arguments.  */
> +  for (i = 0; i < argcount; i++)
> +    grub_free (args[i]);
> +  grub_free (args);
> +
> +  grub_sprintf (errnobuf, "%d", ret);
> +  grub_env_set ("?", errnobuf);
> +
> +  return ret;
> +}
> +
> +/* Execute a block of one or more commands.  */
> +grub_err_t
> +grub_script_execute_cmdblock (struct grub_script_cmd *cmd)
> +{
> +  struct grub_script_cmdblock *cmdblock = (struct grub_script_cmdblock *) 
> cmd;
> +
> +  /* Loop over every command and execute it.  */
> +  for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next)
> +    grub_script_execute_cmd (cmd);
> +
> +  return 0;
> +}
> +
> +/* Execute an if statement.  */
> +grub_err_t
> +grub_script_execute_cmdif (struct grub_script_cmd *cmd)
> +{
> +  struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd;
> +  char *result;
> +
> +  /* Check if the commands results in a true or a false.  The value is
> +     read from the env variable `?'.  */
> +  grub_script_execute_cmd (cmdif->exec_to_evaluate);
> +  result = grub_env_get ("?");
> +
> +  /* Execute the `if' or the `else' part depending on the value of
> +     `?'.  */
> +  if (result && ! grub_strcmp (result, "0"))
> +    return grub_script_execute_cmd (cmdif->exec_on_true);
> +  else
> +    return grub_script_execute_cmd (cmdif->exec_on_false);
> +}
> +
> +/* Execute the menu entry generate statement.  */
> +grub_err_t
> +grub_script_execute_menuentry (struct grub_script_cmd *cmd)
> +{
> +  struct grub_script_cmd_menuentry *cmd_menuentry;
> +  struct grub_script_arglist *arglist;
> +  char **args = 0;
> +  int argcount = 0;
> +  int i = 0;
> +
> +  cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;
> +
> +  if (cmd_menuentry->arglist)
> +    {
> +      argcount = cmd_menuentry->arglist->argcount;
> +
> +      /* Create argv from the arguments.  */
> +      args = grub_malloc (sizeof (char *) * argcount);
> +
> +      if (! args)
> +     {
> +       return grub_errno;
> +     }
> +
> +      for (arglist = cmd_menuentry->arglist; arglist; arglist = 
> arglist->next)
> +     {
> +       char *str;
> +       str = grub_script_execute_argument_to_string (arglist->arg);
> +       args[i++] = str;
> +     }
> +    }
> +
> +  grub_menu_addentry (argcount, (const char **) args,
> +                   cmd_menuentry->sourcecode);
> +
> +  /* Free arguments.  */
> +  for (i = 0; i < argcount; i++)
> +    grub_free (args[i]);
> +  grub_free (args);
> +
> +  return grub_errno;
> +}
> +
> +
> +
> +/* Execute any GRUB pre-parsed command or script.  */
> +grub_err_t
> +grub_script_execute (struct grub_script *script)
> +{
> +  if (script == 0)
> +    return 0;
> +
> +  return grub_script_execute_cmd (script->cmd);
> +}
> +
> 
> Copied: trunk/grub2/script/sh/function.c (from rev 2157, 
> trunk/grub2/normal/function.c)
> ===================================================================
> --- trunk/grub2/script/sh/function.c                          (rev 0)
> +++ trunk/grub2/script/sh/function.c  2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,125 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2005,2007,2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/misc.h>
> +#include <grub/script_sh.h>
> +#include <grub/parser.h>
> +#include <grub/mm.h>
> +
> +static grub_script_function_t grub_script_function_list;
> +
> +grub_script_function_t
> +grub_script_function_create (char *functionname, struct grub_script *cmd)
> +{
> +  grub_script_function_t func;
> +  grub_script_function_t *p;
> +
> +  func = (grub_script_function_t) grub_malloc (sizeof (*func));
> +  if (! func)
> +    return 0;
> +
> +  func->name = grub_strdup (functionname);
> +  if (! func->name)
> +    {
> +      grub_free (func);
> +      return 0;
> +    }
> +
> +  func->func = cmd;
> +
> +  /* Keep the list sorted for simplicity.  */
> +  p = &grub_script_function_list;
> +  while (*p)
> +    {
> +      if (grub_strcmp ((*p)->name, functionname) >= 0)
> +     break;
> +
> +      p = &((*p)->next);
> +    }
> +
> +  /* If the function already exists, overwrite the old function.  */
> +  if (*p && grub_strcmp ((*p)->name, functionname) == 0)
> +    {
> +      grub_script_function_t q;
> +
> +      q = *p;
> +      grub_script_free (q->func);
> +      q->func = cmd;
> +      grub_free (func);
> +      func = q;
> +    }
> +  else
> +    {
> +      func->next = *p;
> +      *p = func;
> +    }
> +
> +  return func;
> +}
> +
> +void
> +grub_script_function_remove (const char *name)
> +{
> +  grub_script_function_t *p, q;
> +
> +  for (p = &grub_script_function_list, q = *p; q; p = &(q->next), q = 
> q->next)
> +    if (grub_strcmp (name, q->name) == 0)
> +      {
> +        *p = q->next;
> +     grub_free (q->name);
> +     grub_script_free (q->func);
> +        grub_free (q);
> +        break;
> +      }
> +}
> +
> +grub_script_function_t
> +grub_script_function_find (char *functionname)
> +{
> +  grub_script_function_t func;
> +
> +  for (func = grub_script_function_list; func; func = func->next)
> +    if (grub_strcmp (functionname, func->name) == 0)
> +      break;
> +
> +  if (! func)
> +    grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", 
> functionname);
> +
> +  return func;
> +}
> +
> +int
> +grub_script_function_iterate (int (*iterate) (grub_script_function_t))
> +{
> +  grub_script_function_t func;
> +
> +  for (func = grub_script_function_list; func; func = func->next)
> +    if (iterate (func))
> +      return 1;
> +
> +  return 0;
> +}
> +
> +int
> +grub_script_function_call (grub_script_function_t func,
> +                        int argc __attribute__((unused)),
> +                        char **args __attribute__((unused)))
> +{
> +  /* XXX: Arguments are not supported yet.  */
> +  return grub_script_execute (func->func);
> +}
> 
> Copied: trunk/grub2/script/sh/lexer.c (from rev 2157, 
> trunk/grub2/normal/lexer.c)
> ===================================================================
> --- trunk/grub2/script/sh/lexer.c                             (rev 0)
> +++ trunk/grub2/script/sh/lexer.c     2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,364 @@
> +/* lexer.c - The scripting lexer.  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2005,2006,2007,2008,2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/parser.h>
> +#include <grub/misc.h>
> +#include <grub/mm.h>
> +#include <grub/script_sh.h>
> +
> +#include "grub_script.tab.h"
> +
> +static int
> +check_varstate (grub_parser_state_t state)
> +{
> +  return (state == GRUB_PARSER_STATE_VARNAME
> +       || state == GRUB_PARSER_STATE_VAR
> +       || state == GRUB_PARSER_STATE_QVAR
> +       || state == GRUB_PARSER_STATE_VARNAME2
> +       || state == GRUB_PARSER_STATE_QVARNAME
> +       || state == GRUB_PARSER_STATE_QVARNAME2);
> +}
> +
> +static int
> +check_textstate (grub_parser_state_t state)
> +{
> +  return (state == GRUB_PARSER_STATE_TEXT
> +       || state == GRUB_PARSER_STATE_QUOTE
> +       || state == GRUB_PARSER_STATE_DQUOTE);
> +}
> +
> +struct grub_lexer_param *
> +grub_script_lexer_init (char *script, grub_reader_getline_t getline)
> +{
> +  struct grub_lexer_param *param;
> +
> +  param = grub_malloc (sizeof (*param));
> +  if (! param)
> +    return 0;
> +
> +  param->state = GRUB_PARSER_STATE_TEXT;
> +  param->getline = getline;
> +  param->refs = 0;
> +  param->done = 0;
> +  param->newscript = 0;
> +  param->script = script;
> +  param->record = 0;
> +  param->recording = 0;
> +  param->recordpos = 0;
> +  param->recordlen = 0;
> +
> +  return param;
> +}
> +
> +void
> +grub_script_lexer_ref (struct grub_lexer_param *state)
> +{
> +  state->refs++;
> +}
> +
> +void
> +grub_script_lexer_deref (struct grub_lexer_param *state)
> +{
> +  state->refs--;
> +}
> +
> +/* Start recording all characters passing through the lexer.  */
> +void
> +grub_script_lexer_record_start (struct grub_lexer_param *state)
> +{
> +  state->record = 1;
> +  state->recordlen = 100;
> +  state->recording = grub_malloc (state->recordlen);
> +  state->recordpos = 0;
> +}
> +
> +char *
> +grub_script_lexer_record_stop (struct grub_lexer_param *state)
> +{
> +  state->record = 0;
> +
> +  /* Delete the last character, it is a `}'.  */
> +  if (state->recordpos > 0)
> +    {
> +      if (state->recording[--state->recordpos] != '}')
> +     {
> +       grub_printf ("Internal error while parsing menu entry");
> +       for (;;); /* XXX */
> +     }
> +      state->recording[state->recordpos] = '\0';
> +    }
> +
> +  return state->recording;
> +}
> +
> +/* When recording is enabled, record the character C as the next item
> +   in the character stream.  */
> +static void
> +recordchar (struct grub_lexer_param *state, char c)
> +{
> +  if (state->recordpos == state->recordlen)
> +    {
> +      char *old = state->recording;
> +      state->recordlen += 100;
> +      state->recording = grub_realloc (state->recording, state->recordlen);
> +      if (! state->recording)
> +     {
> +       grub_free (old);
> +       state->record = 0;
> +     }
> +    }
> +  state->recording[state->recordpos++] = c;
> +}
> +
> +/* Fetch the next character for the lexer.  */
> +static void
> +nextchar (struct grub_lexer_param *state)
> +{
> +  if (state->record)
> +    recordchar (state, *state->script);
> +  state->script++;
> +}
> +
> +int
> +grub_script_yylex2 (union YYSTYPE *yylval,
> +                 struct grub_parser_param *parsestate);
> +
> +int
> +grub_script_yylex (union YYSTYPE *yylval, struct grub_parser_param 
> *parsestate)
> +{
> +  int r = -1;
> +
> +  while (r == -1)
> +    {
> +      r = grub_script_yylex2 (yylval, parsestate);
> +      if (r == ' ')
> +     r = -1;
> +    }
> +  return r;
> +}
> +
> +int
> +grub_script_yylex2 (union YYSTYPE *yylval, struct grub_parser_param 
> *parsestate)
> +{
> +  grub_parser_state_t newstate;
> +  char use;
> +  char *buffer;
> +  char *bp;
> +  struct grub_lexer_param *state = parsestate->lexerstate;
> +
> +  if (state->done)
> +    return 0;
> +
> +  if (! *state->script)
> +    {
> +      /* Check if more tokens are requested by the parser.  */
> +      if ((state->refs
> +        || state->state == GRUB_PARSER_STATE_ESC)
> +       && state->getline)
> +     {
> +       while (!state->script || ! grub_strlen (state->script))
> +         {
> +           grub_free (state->newscript);
> +           state->newscript = 0;
> +           state->getline (&state->newscript, 1);
> +           state->script = state->newscript;
> +           if (! state->script)
> +             return 0;
> +         }
> +       grub_dprintf ("scripting", "token=`\\n'\n");
> +       recordchar (state, '\n');
> +       if (state->state != GRUB_PARSER_STATE_ESC)
> +         return '\n';
> +     }
> +      else
> +     {
> +       grub_free (state->newscript);
> +       state->newscript = 0;
> +       state->done = 1;
> +       grub_dprintf ("scripting", "token=`\\n'\n");
> +       return '\n';
> +     }
> +    }
> +
> +  newstate = grub_parser_cmdline_state (state->state, *state->script, &use);
> +
> +  /* Check if it is a text.  */
> +  if (check_textstate (newstate))
> +    {
> +      /* In case the string is not quoted, this can be a one char
> +      length symbol.  */
> +      if (newstate == GRUB_PARSER_STATE_TEXT)
> +     {
> +       switch (*state->script)
> +         {
> +         case ' ':
> +           while (*state->script)
> +             {
> +               newstate = grub_parser_cmdline_state (state->state,
> +                                                     *state->script, &use);
> +               if (! (state->state == GRUB_PARSER_STATE_TEXT
> +                      && *state->script == ' '))
> +                 {
> +                   grub_dprintf ("scripting", "token=` '\n");
> +                   return ' ';
> +                 }
> +               state->state = newstate;
> +               nextchar (state);
> +             }
> +           grub_dprintf ("scripting", "token=` '\n");
> +           return ' ';
> +         case '{':
> +         case '}':
> +         case ';':
> +         case '\n':
> +           {
> +             char c;
> +             grub_dprintf ("scripting", "token=`%c'\n", *state->script);
> +             c = *state->script;;
> +             nextchar (state);
> +             return c;
> +           }
> +         }
> +     }
> +
> +      /* XXX: Use a better size.  */
> +      buffer = grub_script_malloc (parsestate, 2048);
> +      if (! buffer)
> +     return 0;
> +
> +      bp = buffer;
> +
> +      /* Read one token, possible quoted.  */
> +      while (*state->script)
> +     {
> +       newstate = grub_parser_cmdline_state (state->state,
> +                                             *state->script, &use);
> +
> +       /* Check if a variable name starts.  */
> +       if (check_varstate (newstate))
> +         break;
> +
> +       /* If the string is not quoted or escaped, stop processing
> +          when a special token was found.  It will be recognized
> +          next time when this function is called.  */
> +       if (newstate == GRUB_PARSER_STATE_TEXT
> +           && state->state != GRUB_PARSER_STATE_ESC)
> +         {
> +           int breakout = 0;
> +
> +           switch (use)
> +             {
> +             case ' ':
> +             case '{':
> +             case '}':
> +             case ';':
> +             case '\n':
> +               breakout = 1;
> +             }
> +           if (breakout)
> +             break;
> +           *(bp++) = use;
> +         }
> +       else if (use)
> +         *(bp++) = use;
> +
> +       state->state = newstate;
> +       nextchar (state);
> +     }
> +
> +      /* A string of text was read in.  */
> +      *bp = '\0';
> +      grub_dprintf ("scripting", "token=`%s'\n", buffer);
> +      yylval->string = buffer;
> +
> +      /* Detect some special tokens.  */
> +      if (! grub_strcmp (buffer, "while"))
> +     return GRUB_PARSER_TOKEN_WHILE;
> +      else if (! grub_strcmp (buffer, "if"))
> +     return GRUB_PARSER_TOKEN_IF;
> +      else if (! grub_strcmp (buffer, "function"))
> +     return GRUB_PARSER_TOKEN_FUNCTION;
> +      else if (! grub_strcmp (buffer, "menuentry"))
> +     return GRUB_PARSER_TOKEN_MENUENTRY;
> +      else if (! grub_strcmp (buffer, "@"))
> +     return GRUB_PARSER_TOKEN_MENUENTRY;
> +      else if (! grub_strcmp (buffer, "else"))
> +     return GRUB_PARSER_TOKEN_ELSE;
> +      else if (! grub_strcmp (buffer, "then"))
> +     return GRUB_PARSER_TOKEN_THEN;
> +      else if (! grub_strcmp (buffer, "fi"))
> +     return GRUB_PARSER_TOKEN_FI;
> +      else
> +     return GRUB_PARSER_TOKEN_NAME;
> +    }
> +  else if (newstate == GRUB_PARSER_STATE_VAR
> +        || newstate == GRUB_PARSER_STATE_QVAR)
> +    {
> +      /* XXX: Use a better size.  */
> +      buffer = grub_script_malloc (parsestate, 2096);
> +      if (! buffer)
> +     return 0;
> +
> +      bp = buffer;
> +
> +      /* This is a variable, read the variable name.  */
> +      while (*state->script)
> +     {
> +       newstate = grub_parser_cmdline_state (state->state,
> +                                             *state->script, &use);
> +
> +       /* Check if this character is not part of the variable name
> +          anymore.  */
> +       if (! (check_varstate (newstate)))
> +         {
> +           if (state->state == GRUB_PARSER_STATE_VARNAME2
> +               || state->state == GRUB_PARSER_STATE_QVARNAME2)
> +             nextchar (state);
> +           state->state = newstate;
> +           break;
> +         }
> +
> +       if (use)
> +         *(bp++) = use;
> +       nextchar (state);
> +       state->state = newstate;
> +     }
> +
> +      *bp = '\0';
> +      state->state = newstate;
> +      yylval->string = buffer;
> +      grub_dprintf ("scripting", "vartoken=`%s'\n", buffer);
> +
> +      return GRUB_PARSER_TOKEN_VAR;
> +    }
> +  else
> +    {
> +      /* There is either text or a variable name.  In the case you
> +      arrive here there is a serious problem with the lexer.  */
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, "Internal error\n");
> +      return 0;
> +    }
> +}
> +
> +void
> +grub_script_yyerror (struct grub_parser_param *lex __attribute__ ((unused)),
> +                  char const *err)
> +{
> +  grub_printf ("%s\n", err);
> +}
> 
> Copied: trunk/grub2/script/sh/main.c (from rev 2157, 
> trunk/grub2/normal/command.c)
> ===================================================================
> --- trunk/grub2/script/sh/main.c                              (rev 0)
> +++ trunk/grub2/script/sh/main.c      2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,58 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/dl.h>
> +#include <grub/parser.h>
> +#include <grub/script_sh.h>
> +
> +static grub_err_t
> +grub_normal_parse_line (char *line, grub_reader_getline_t getline)
> +{
> +  struct grub_script *parsed_script;
> +
> +  /* Parse the script.  */
> +  parsed_script = grub_script_parse (line, getline);
> +
> +  if (parsed_script)
> +    {
> +      /* Execute the command(s).  */
> +      grub_script_execute (parsed_script);
> +
> +      /* The parsed script was executed, throw it away.  */
> +      grub_script_free (parsed_script);
> +    }
> +
> +  return grub_errno;
> +}
> +
> +static struct grub_parser grub_sh_parser =
> +  {
> +    .name = "sh",
> +    .parse_line = grub_normal_parse_line
> +  };
> +
> +GRUB_MOD_INIT(sh)
> +{
> +  (void) mod;
> +  grub_parser_register ("sh", &grub_sh_parser);
> +}
> +
> +GRUB_MOD_FINI(sh)
> +{
> +  grub_parser_unregister (&grub_sh_parser);
> +}
> 
> Copied: trunk/grub2/script/sh/parser.y (from rev 2157, 
> trunk/grub2/normal/parser.y)
> ===================================================================
> --- trunk/grub2/script/sh/parser.y                            (rev 0)
> +++ trunk/grub2/script/sh/parser.y    2009-05-02 19:49:34 UTC (rev 2158)
> @@ -0,0 +1,238 @@
> +/* parser.y - The scripting parser.  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2005,2006,2007,2008,2009  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +%{
> +#include <grub/script_sh.h>
> +#include <grub/mm.h>
> +
> +#define YYFREE               grub_free
> +#define YYMALLOC     grub_malloc
> +#define YYLTYPE_IS_TRIVIAL      0
> +#define YYENABLE_NLS 0
> +
> +%}
> +
> +%union {
> +  struct grub_script_cmd *cmd;
> +  struct grub_script_arglist *arglist;
> +  struct grub_script_arg *arg;
> +  char *string;
> +}
> +
> 
> @@ Diff output truncated at 153600 characters. @@
> 
> 
> 

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."




reply via email to

[Prev in Thread] Current Thread [Next in Thread]