]> git.proxmox.com Git - grub2.git/commitdiff
2005-11-06 Marco Gerards <mgerards@xs4all.nl>
authormarco_g <marco_g@localhost>
Sun, 6 Nov 2005 22:19:59 +0000 (22:19 +0000)
committermarco_g <marco_g@localhost>
Sun, 6 Nov 2005 22:19:59 +0000 (22:19 +0000)
Add initial scripting support.

* commands/test.c: New file.
* include/grub/script.h: Likewise.
* normal/execute.c: Likewise.
* normal/function.c: Likewise.
* normal/lexer.c: Likewise.
* normal/parser.y: Likewise.
* normal/script.c: Likewise.

* configure.ac: Add `AC_PROG_YACC' test.

* conf/i386-pc.rmk (grub_emu_SOURCES): Add `commands/test.c',
`normal/execute.c', `normal/lexer.c', `grub_script.tab.c',
`normal/function.c' and `normal/script.c'.
(normal_mod_SOURCES): `normal/execute.c', `normal/lexer.c',
`grub_script.tab.c', `normal/function.c' and `normal/script.c'.
(test_mod_SOURCES, test_mod_CFLAGS, test_mod_LDFLAGS): New variables.
(pkgdata_MODULES): Add `test.mod'.
(grub_script.tab.c): New rule.
(grub_script.tab.h): Likewise.

* include/grub/err.h (grub_err_t): Add `GRUB_ERR_TEST_FAILURE'.

* include/grub/normal.h (grub_test_init): New prototype.
(grub_test_fini): Likewise.

* normal/command.c: Include <grub/script.h>.
(grub_command_execute): Rewritten.

* util/grub-emu.c (main): Call `grub_test_init' and
`grub_test_fini'.

16 files changed:
ChangeLog
commands/test.c [new file with mode: 0644]
conf/i386-pc.mk
conf/i386-pc.rmk
configure
configure.ac
include/grub/err.h
include/grub/normal.h
include/grub/script.h [new file with mode: 0644]
normal/command.c
normal/execute.c [new file with mode: 0644]
normal/function.c [new file with mode: 0644]
normal/lexer.c [new file with mode: 0644]
normal/parser.y [new file with mode: 0644]
normal/script.c [new file with mode: 0644]
util/grub-emu.c

index 52eadd6d6c7cdc29bdc02e1f2d1d87f8da72417b..728ef1a473fb22c80f4277453b095d7556b8721d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2005-11-06  Marco Gerards  <mgerards@xs4all.nl>
+
+       Add initial scripting support.
+
+       * commands/test.c: New file.
+       * include/grub/script.h: Likewise.
+       * normal/execute.c: Likewise.
+       * normal/function.c: Likewise.
+       * normal/lexer.c: Likewise.
+       * normal/parser.y: Likewise.
+       * normal/script.c: Likewise.
+
+       * configure.ac: Add `AC_PROG_YACC' test.
+       
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `commands/test.c',
+       `normal/execute.c', `normal/lexer.c', `grub_script.tab.c',
+       `normal/function.c' and `normal/script.c'.
+       (normal_mod_SOURCES): `normal/execute.c', `normal/lexer.c',
+       `grub_script.tab.c', `normal/function.c' and `normal/script.c'.
+       (test_mod_SOURCES, test_mod_CFLAGS, test_mod_LDFLAGS): New variables.
+       (pkgdata_MODULES): Add `test.mod'.
+       (grub_script.tab.c): New rule.
+       (grub_script.tab.h): Likewise.
+
+       * include/grub/err.h (grub_err_t): Add `GRUB_ERR_TEST_FAILURE'.
+
+       * include/grub/normal.h (grub_test_init): New prototype.
+       (grub_test_fini): Likewise.
+       
+       * normal/command.c: Include <grub/script.h>.
+       (grub_command_execute): Rewritten.
+       
+       * util/grub-emu.c (main): Call `grub_test_init' and
+       `grub_test_fini'.
+
 2005-11-03  Hollis Blanchard  <hollis@penguinppc.org>
 
        * kern/powerpc/ieee1275/init.c (grub_get_rtc): Initialize `msecs'
diff --git a/commands/test.c b/commands/test.c
new file mode 100644 (file)
index 0000000..9ee7abe
--- /dev/null
@@ -0,0 +1,89 @@
+/* test.c -- The test command..  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+
+static grub_err_t
+grub_cmd_test (struct grub_arg_list *state __attribute__ ((unused)), int argc,
+              char **args)
+
+{
+  char *eq;
+  char *eqis;
+
+  /* XXX: No fancy expression evaluation yet.  */
+  
+  if (argc == 0)
+    return 0;
+  
+  eq = grub_strdup (args[0]);
+  eqis = grub_strchr (eq, '=');
+  if (! eqis)
+    return 0;
+
+  *eqis = '\0';
+  eqis++;
+  /* Check an expression in the form `A=B'.  */
+  if (grub_strcmp (eq, eqis))
+    grub_error (GRUB_ERR_TEST_FAILURE, "false");
+  grub_free (eq);
+
+  return grub_errno;
+}
+
+
+\f
+#ifdef GRUB_UTIL
+void
+grub_test_init (void)
+{
+  grub_register_command ("[", grub_cmd_test, GRUB_COMMAND_FLAG_CMDLINE,
+                        "[ EXPRESSION ]", "Evaluate an expression", 0);
+  grub_register_command ("test", grub_cmd_test, GRUB_COMMAND_FLAG_CMDLINE,
+                        "test EXPRESSION", "Evaluate an expression", 0);
+}
+
+void
+grub_test_fini (void)
+{
+  grub_unregister_command ("[");
+  grub_unregister_command ("test");
+}
+#else /* ! GRUB_UTIL */
+GRUB_MOD_INIT
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("[", grub_cmd_test, GRUB_COMMAND_FLAG_CMDLINE,
+                        "[ EXPRESSION ]", "Evaluate an expression", 0);
+  grub_register_command ("test", grub_cmd_test, GRUB_COMMAND_FLAG_CMDLINE,
+                        "test EXPRESSION", "Evaluate an expression", 0);
+}
+
+GRUB_MOD_FINI
+{
+  grub_unregister_command ("[");
+  grub_unregister_command ("test");
+}
+#endif /* ! GRUB_UTIL */
index 2af0a7c8cf9a7b91ae483a18825e7897f9027c37..20afa077788f7306f7994e5cf1ecf5d531fe5bc6 100644 (file)
@@ -274,6 +274,13 @@ DEFSYMFILES += kernel_syms.lst
 symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) gensymlist.sh
        sh $(srcdir)/gensymlist.sh $(filter %.h,$^) > $@
 
+# For the parser.
+grub_script.tab.c: normal/parser.y
+       $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
+grub_script.tab.h: normal/parser.y
+       $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
+
+
 kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_HEADERS)) genkernsyms.sh
        sh $(srcdir)/genkernsyms.sh $(filter %h,$^) > $@
 
@@ -748,27 +755,28 @@ grub_probefs-fs_sfs.d: fs/sfs.c
 # For grub-emu.
 grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
        commands/configfile.c commands/default.c commands/help.c        \
-       commands/terminal.c commands/ls.c commands/search.c             \
-       commands/timeout.c                                              \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/timeout.c                            \
        commands/i386/pc/halt.c commands/i386/pc/reboot.c               \
        disk/loopback.c                                                 \
        fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c  \
        fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c                  \
        io/gzio.c                                                       \
        kern/device.c kern/disk.c kern/dl.c kern/env.c kern/err.c       \
-       kern/file.c kern/fs.c kern/loader.c kern/main.c kern/misc.c     \
-       kern/parser.c kern/partition.c kern/rescue.c kern/term.c        \
-       normal/arg.c normal/cmdline.c normal/command.c                  \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
        normal/completion.c normal/context.c normal/main.c              \
-       normal/menu.c normal/menu_entry.c normal/misc.c                 \
+       normal/menu.c normal/menu_entry.c normal/misc.c normal/script.c \
        partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
        util/console.c util/grub-emu.c util/misc.c                      \
        util/i386/pc/biosdisk.c util/i386/pc/getroot.c                  \
        util/i386/pc/misc.c
-CLEANFILES += grub-emu grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_default.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_search.o grub_emu-commands_timeout.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_fshelp.o grub_emu-fs_hfs.o grub_emu-fs_iso9660.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_completion.o grub_emu-normal_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_misc.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-util_console.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_i386_pc_biosdisk.o grub_emu-util_i386_pc_getroot.o grub_emu-util_i386_pc_misc.o
-MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_configfile.d grub_emu-commands_default.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_search.d grub_emu-commands_timeout.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_i386_pc_reboot.d grub_emu-disk_loopback.d grub_emu-fs_affs.d grub_emu-fs_ext2.d grub_emu-fs_fat.d grub_emu-fs_fshelp.d grub_emu-fs_hfs.d grub_emu-fs_iso9660.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_sfs.d grub_emu-fs_ufs.d grub_emu-fs_xfs.d grub_emu-io_gzio.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_parser.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_completion.d grub_emu-normal_context.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.d grub_emu-normal_misc.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-partmap_sun.d grub_emu-util_console.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_i386_pc_biosdisk.d grub_emu-util_i386_pc_getroot.d grub_emu-util_i386_pc_misc.d
+CLEANFILES += grub-emu grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_default.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_timeout.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_fshelp.o grub_emu-fs_hfs.o grub_emu-fs_iso9660.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-util_console.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_i386_pc_biosdisk.o grub_emu-util_i386_pc_getroot.o grub_emu-util_i386_pc_misc.o
+MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_configfile.d grub_emu-commands_default.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_test.d grub_emu-commands_search.d grub_emu-commands_timeout.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_i386_pc_reboot.d grub_emu-disk_loopback.d grub_emu-fs_affs.d grub_emu-fs_ext2.d grub_emu-fs_fat.d grub_emu-fs_fshelp.d grub_emu-fs_hfs.d grub_emu-fs_iso9660.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_sfs.d grub_emu-fs_ufs.d grub_emu-fs_xfs.d grub_emu-io_gzio.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-normal_execute.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-normal_lexer.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_parser.d grub_emu-grub_script_tab.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_function.d grub_emu-normal_completion.d grub_emu-normal_context.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.d grub_emu-normal_misc.d grub_emu-normal_script.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-partmap_sun.d grub_emu-util_console.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_i386_pc_biosdisk.d grub_emu-util_i386_pc_getroot.d grub_emu-util_i386_pc_misc.d
 
-grub-emu: grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_default.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_search.o grub_emu-commands_timeout.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_fshelp.o grub_emu-fs_hfs.o grub_emu-fs_iso9660.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_completion.o grub_emu-normal_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_misc.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-util_console.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_i386_pc_biosdisk.o grub_emu-util_i386_pc_getroot.o grub_emu-util_i386_pc_misc.o
+grub-emu: grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_default.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_timeout.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_fshelp.o grub_emu-fs_hfs.o grub_emu-fs_iso9660.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-util_console.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_i386_pc_biosdisk.o grub_emu-util_i386_pc_getroot.o grub_emu-util_i386_pc_misc.o
        $(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(grub_emu_LDFLAGS)
 
 grub_emu-commands_boot.o: commands/boot.c
@@ -835,6 +843,14 @@ grub_emu-commands_ls.d: commands/ls.c
 
 -include grub_emu-commands_ls.d
 
+grub_emu-commands_test.o: commands/test.c
+       $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-commands_test.d: commands/test.c
+       set -e;           $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $<    | sed 's,test\.o[ :]*,grub_emu-commands_test.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include grub_emu-commands_test.d
+
 grub_emu-commands_search.o: commands/search.c
        $(BUILD_CC) -Icommands -I$(srcdir)/commands $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
 
@@ -1011,6 +1027,14 @@ grub_emu-kern_err.d: kern/err.c
 
 -include grub_emu-kern_err.d
 
+grub_emu-normal_execute.o: normal/execute.c
+       $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-normal_execute.d: normal/execute.c
+       set -e;           $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $<        | sed 's,execute\.o[ :]*,grub_emu-normal_execute.o $@ : ,g' > $@;       [ -s $@ ] || rm -f $@
+
+-include grub_emu-normal_execute.d
+
 grub_emu-kern_file.o: kern/file.c
        $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
 
@@ -1027,6 +1051,14 @@ grub_emu-kern_fs.d: kern/fs.c
 
 -include grub_emu-kern_fs.d
 
+grub_emu-normal_lexer.o: normal/lexer.c
+       $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-normal_lexer.d: normal/lexer.c
+       set -e;           $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $<        | sed 's,lexer\.o[ :]*,grub_emu-normal_lexer.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include grub_emu-normal_lexer.d
+
 grub_emu-kern_loader.o: kern/loader.c
        $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
 
@@ -1059,6 +1091,14 @@ grub_emu-kern_parser.d: kern/parser.c
 
 -include grub_emu-kern_parser.d
 
+grub_emu-grub_script_tab.o: grub_script.tab.c
+       $(BUILD_CC) -I. -I$(srcdir)/. $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-grub_script_tab.d: grub_script.tab.c
+       set -e;           $(BUILD_CC) -I. -I$(srcdir)/. $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $<          | sed 's,grub_script\.tab\.o[ :]*,grub_emu-grub_script_tab.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include grub_emu-grub_script_tab.d
+
 grub_emu-kern_partition.o: kern/partition.c
        $(BUILD_CC) -Ikern -I$(srcdir)/kern $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
 
@@ -1107,6 +1147,14 @@ grub_emu-normal_command.d: normal/command.c
 
 -include grub_emu-normal_command.d
 
+grub_emu-normal_function.o: normal/function.c
+       $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-normal_function.d: normal/function.c
+       set -e;           $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $<        | sed 's,function\.o[ :]*,grub_emu-normal_function.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include grub_emu-normal_function.d
+
 grub_emu-normal_completion.o: normal/completion.c
        $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
 
@@ -1155,6 +1203,14 @@ grub_emu-normal_misc.d: normal/misc.c
 
 -include grub_emu-normal_misc.d
 
+grub_emu-normal_script.o: normal/script.c
+       $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-normal_script.d: normal/script.c
+       set -e;           $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $<        | sed 's,script\.o[ :]*,grub_emu-normal_script.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include grub_emu-normal_script.d
+
 grub_emu-partmap_amiga.o: partmap/amiga.c
        $(BUILD_CC) -Ipartmap -I$(srcdir)/partmap $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
 
@@ -1275,7 +1331,7 @@ pkgdata_MODULES = _chain.mod _linux.mod linux.mod fat.mod ufs.mod \
        apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod       \
        help.mod default.mod timeout.mod configfile.mod vbe.mod         \
        vesafb.mod vbetest.mod vbeinfo.mod search.mod gzio.mod          \
-       terminfo.mod serial.mod xfs.mod affs.mod sfs.mod
+       terminfo.mod serial.mod xfs.mod affs.mod sfs.mod test.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -1998,11 +2054,12 @@ linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For normal.mod.
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/context.c normal/main.c              \
-       normal/menu.c normal/menu_entry.c normal/misc.c                 \
-       normal/i386/setjmp.S
-CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-normal_i386_setjmp.o def-normal.lst und-normal.lst
-MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_context.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-normal_i386_setjmp.d
+       normal/completion.c normal/context.c normal/execute.c           \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_entry.c normal/misc.c grub_script.tab.c             \
+       normal/script.c normal/i386/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_context.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o def-normal.lst und-normal.lst
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_context.d normal_mod-normal_execute.d normal_mod-normal_function.d normal_mod-normal_lexer.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-grub_script_tab.d normal_mod-normal_script.d normal_mod-normal_i386_setjmp.d
 DEFSYMFILES += def-normal.lst
 UNDSYMFILES += und-normal.lst
 
@@ -2011,7 +2068,7 @@ normal.mod: pre-normal.o mod-normal.o
        $(LD) $(normal_mod_LDFLAGS) $(LDFLAGS) -r -d -o $@ $^
        $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
 
-pre-normal.o: normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-normal_i386_setjmp.o
+pre-normal.o: normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_context.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
        -rm -f $@
        $(LD) $(normal_mod_LDFLAGS) -r -d -o $@ $^
 
@@ -2123,6 +2180,63 @@ fs-context.lst: normal/context.c genfslist.sh
        set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
 
 
+normal_mod-normal_execute.o: normal/execute.c
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+normal_mod-normal_execute.d: normal/execute.c
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $<      | sed 's,execute\.o[ :]*,normal_mod-normal_execute.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include normal_mod-normal_execute.d
+
+CLEANFILES += cmd-execute.lst fs-execute.lst
+COMMANDFILES += cmd-execute.lst
+FSFILES += fs-execute.lst
+
+cmd-execute.lst: normal/execute.c gencmdlist.sh
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-execute.lst: normal/execute.c genfslist.sh
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_function.o: normal/function.c
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+normal_mod-normal_function.d: normal/function.c
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $<      | sed 's,function\.o[ :]*,normal_mod-normal_function.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include normal_mod-normal_function.d
+
+CLEANFILES += cmd-function.lst fs-function.lst
+COMMANDFILES += cmd-function.lst
+FSFILES += fs-function.lst
+
+cmd-function.lst: normal/function.c gencmdlist.sh
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-function.lst: normal/function.c genfslist.sh
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_lexer.o: normal/lexer.c
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+normal_mod-normal_lexer.d: normal/lexer.c
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $<      | sed 's,lexer\.o[ :]*,normal_mod-normal_lexer.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include normal_mod-normal_lexer.d
+
+CLEANFILES += cmd-lexer.lst fs-lexer.lst
+COMMANDFILES += cmd-lexer.lst
+FSFILES += fs-lexer.lst
+
+cmd-lexer.lst: normal/lexer.c gencmdlist.sh
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-lexer.lst: normal/lexer.c genfslist.sh
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+
 normal_mod-normal_main.o: normal/main.c
        $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
 
@@ -2199,6 +2313,44 @@ fs-misc.lst: normal/misc.c genfslist.sh
        set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
 
 
+normal_mod-grub_script_tab.o: grub_script.tab.c
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+normal_mod-grub_script_tab.d: grub_script.tab.c
+       set -e;           $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $<        | sed 's,grub_script\.tab\.o[ :]*,normal_mod-grub_script_tab.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include normal_mod-grub_script_tab.d
+
+CLEANFILES += cmd-grub_script.tab.lst fs-grub_script.tab.lst
+COMMANDFILES += cmd-grub_script.tab.lst
+FSFILES += fs-grub_script.tab.lst
+
+cmd-grub_script.tab.lst: grub_script.tab.c gencmdlist.sh
+       set -e;           $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-grub_script.tab.lst: grub_script.tab.c genfslist.sh
+       set -e;           $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_script.o: normal/script.c
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+normal_mod-normal_script.d: normal/script.c
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $<      | sed 's,script\.o[ :]*,normal_mod-normal_script.o $@ : ,g' > $@;       [ -s $@ ] || rm -f $@
+
+-include normal_mod-normal_script.d
+
+CLEANFILES += cmd-script.lst fs-script.lst
+COMMANDFILES += cmd-script.lst
+FSFILES += fs-script.lst
+
+cmd-script.lst: normal/script.c gencmdlist.sh
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-script.lst: normal/script.c genfslist.sh
+       set -e;           $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+
 normal_mod-normal_i386_setjmp.o: normal/i386/setjmp.S
        $(CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(CPPFLAGS) $(ASFLAGS) $(normal_mod_ASFLAGS) -c -o $@ $<
 
@@ -3719,6 +3871,57 @@ fs-gzio.lst: io/gzio.c genfslist.sh
 
 gzio_mod_CFLAGS = $(COMMON_CFLAGS)
 gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For test.mod.
+test_mod_SOURCES = commands/test.c
+CLEANFILES += test.mod mod-test.o mod-test.c pre-test.o test_mod-commands_test.o def-test.lst und-test.lst
+MOSTLYCLEANFILES += test_mod-commands_test.d
+DEFSYMFILES += def-test.lst
+UNDSYMFILES += und-test.lst
+
+test.mod: pre-test.o mod-test.o
+       -rm -f $@
+       $(LD) $(test_mod_LDFLAGS) $(LDFLAGS) -r -d -o $@ $^
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-test.o: test_mod-commands_test.o
+       -rm -f $@
+       $(LD) $(test_mod_LDFLAGS) -r -d -o $@ $^
+
+mod-test.o: mod-test.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(test_mod_CFLAGS) -c -o $@ $<
+
+mod-test.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'test' $< > $@ || (rm -f $@; exit 1)
+
+def-test.lst: pre-test.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 test/' > $@
+
+und-test.lst: pre-test.o
+       echo 'test' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+test_mod-commands_test.o: commands/test.c
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(test_mod_CFLAGS) -c -o $@ $<
+
+test_mod-commands_test.d: commands/test.c
+       set -e;           $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(test_mod_CFLAGS) -M $<    | sed 's,test\.o[ :]*,test_mod-commands_test.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include test_mod-commands_test.d
+
+CLEANFILES += cmd-test.lst fs-test.lst
+COMMANDFILES += cmd-test.lst
+FSFILES += fs-test.lst
+
+cmd-test.lst: commands/test.c gencmdlist.sh
+       set -e;           $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(test_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh test > $@ || (rm -f $@; exit 1)
+
+fs-test.lst: commands/test.c genfslist.sh
+       set -e;           $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) $(test_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh test > $@ || (rm -f $@; exit 1)
+
+
+test_mod_CFLAGS = $(COMMON_CFLAGS)
+test_mod_LDFLAGS = $(COMMON_LDFLAGS)
 CLEANFILES += moddep.lst command.lst fs.lst
 pkgdata_DATA += moddep.lst command.lst fs.lst
 moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep
index 027c909e732b53b1c7eb075b05d50374c886b01d..f2452668042746e04b16a535f091f2b874b2229e 100644 (file)
@@ -46,6 +46,13 @@ DEFSYMFILES += kernel_syms.lst
 symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) gensymlist.sh
        sh $(srcdir)/gensymlist.sh $(filter %.h,$^) > $@
 
+# For the parser.
+grub_script.tab.c: normal/parser.y
+       $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
+grub_script.tab.h: normal/parser.y
+       $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
+
+
 kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_HEADERS)) genkernsyms.sh
        sh $(srcdir)/genkernsyms.sh $(filter %h,$^) > $@
 
@@ -80,19 +87,20 @@ grub_probefs_SOURCES = util/i386/pc/grub-probefs.c  \
 # For grub-emu.
 grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
        commands/configfile.c commands/default.c commands/help.c        \
-       commands/terminal.c commands/ls.c commands/search.c             \
-       commands/timeout.c                                              \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/timeout.c                            \
        commands/i386/pc/halt.c commands/i386/pc/reboot.c               \
        disk/loopback.c                                                 \
        fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c  \
        fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c                  \
        io/gzio.c                                                       \
        kern/device.c kern/disk.c kern/dl.c kern/env.c kern/err.c       \
-       kern/file.c kern/fs.c kern/loader.c kern/main.c kern/misc.c     \
-       kern/parser.c kern/partition.c kern/rescue.c kern/term.c        \
-       normal/arg.c normal/cmdline.c normal/command.c                  \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
        normal/completion.c normal/context.c normal/main.c              \
-       normal/menu.c normal/menu_entry.c normal/misc.c                 \
+       normal/menu.c normal/menu_entry.c normal/misc.c normal/script.c \
        partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
        util/console.c util/grub-emu.c util/misc.c                      \
        util/i386/pc/biosdisk.c util/i386/pc/getroot.c                  \
@@ -117,7 +125,7 @@ pkgdata_MODULES = _chain.mod _linux.mod linux.mod fat.mod ufs.mod   \
        apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod       \
        help.mod default.mod timeout.mod configfile.mod vbe.mod         \
        vesafb.mod vbetest.mod vbeinfo.mod search.mod gzio.mod          \
-       terminfo.mod serial.mod xfs.mod affs.mod sfs.mod
+       terminfo.mod serial.mod xfs.mod affs.mod sfs.mod test.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -196,9 +204,10 @@ linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For normal.mod.
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
-       normal/completion.c normal/context.c normal/main.c              \
-       normal/menu.c normal/menu_entry.c normal/misc.c                 \
-       normal/i386/setjmp.S
+       normal/completion.c normal/context.c normal/execute.c           \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.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) -m32
 normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
@@ -347,3 +356,8 @@ search_mod_LDFLAGS = $(COMMON_LDFLAGS)
 gzio_mod_SOURCES = io/gzio.c
 gzio_mod_CFLAGS = $(COMMON_CFLAGS)
 gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For test.mod.
+test_mod_SOURCES = commands/test.c
+test_mod_CFLAGS = $(COMMON_CFLAGS)
+test_mod_LDFLAGS = $(COMMON_LDFLAGS)
index bf208456a430f80482aed143b532df0634706d28..a7d1f49820ceed984dabe3b923344de2652ae102 100644 (file)
--- a/configure
+++ b/configure
@@ -311,7 +311,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA SET_MAKE OBJCOPY ac_ct_OBJCOPY STRIP ac_ct_STRIP NM ac_ct_NM LD ac_ct_LD RUBY BUILD_CC CPP EGREP LIBLZO LIBCURSES LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT YACC INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA SET_MAKE OBJCOPY ac_ct_OBJCOPY STRIP ac_ct_STRIP NM ac_ct_NM LD ac_ct_LD RUBY BUILD_CC CPP EGREP LIBLZO LIBCURSES LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -2345,6 +2345,47 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_YACC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  echo "$as_me:$LINENO: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
 
 # Check whether --enable-largefile or --disable-largefile was given.
 if test "${enable_largefile+set}" = set; then
@@ -7100,6 +7141,7 @@ s,@CPPFLAGS@,$CPPFLAGS,;t t
 s,@ac_ct_CC@,$ac_ct_CC,;t t
 s,@EXEEXT@,$EXEEXT,;t t
 s,@OBJEXT@,$OBJEXT,;t t
+s,@YACC@,$YACC,;t t
 s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
 s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
 s,@INSTALL_DATA@,$INSTALL_DATA,;t t
index 279726aad5b5623cb9ed4edb543d2e56d59020ba..f2f4f541c0ce13ec8d6dc7c3793043661703e4ba 100644 (file)
@@ -44,6 +44,7 @@ if test "x$CFLAGS" = x; then
 fi
 
 AC_PROG_CC
+AC_PROG_YACC
 AC_SYS_LARGEFILE
 
 # Must be GCC.
index 636009033d5774e1790aacd613f7fc48cee381e2..3ef858225c43a8d3765b757fffd8c7b3643de892 100644 (file)
@@ -26,6 +26,7 @@
 typedef enum
   {
     GRUB_ERR_NONE = 0,
+    GRUB_ERR_TEST_FAILURE,
     GRUB_ERR_BAD_MODULE,
     GRUB_ERR_OUT_OF_MEMORY,
     GRUB_ERR_BAD_FILE_TYPE,
index 89d0d74ac4deed6fe9d8080d550c0e3e5fbc2079..9dd7debb2a7bbe6b907a7fa53c7bde66e0fddc28 100644 (file)
@@ -224,6 +224,8 @@ void grub_configfile_init (void);
 void grub_configfile_fini (void);
 void grub_search_init (void);
 void grub_search_fini (void);
+void grub_test_init (void);
+void grub_test_fini (void);
 #endif
 
 #endif /* ! GRUB_NORMAL_HEADER */
diff --git a/include/grub/script.h b/include/grub/script.h
new file mode 100644 (file)
index 0000000..6ba0a4c
--- /dev/null
@@ -0,0 +1,189 @@
+/* script.h  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *
+ *  This program 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <grub/types.h>
+#include <grub/err.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;
+};
+\f
+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 *bool;
+
+  /* The code executed in case the result if bool was true.  */
+  struct grub_script_cmd *true;
+
+  /* The code executed in case the result if bool was false.  */
+  struct grub_script_cmd *false;
+};
+
+struct grub_script_arglist *
+grub_script_create_arglist (void);
+
+struct grub_script_arglist *
+grub_script_add_arglist (struct grub_script_arglist *list,
+                        struct grub_script_arg *arg);
+struct grub_script_cmd *
+grub_script_create_cmdline (char *cmdname,
+                           struct grub_script_arglist *arglist);
+struct grub_script_cmd *
+grub_script_create_cmdblock (void);
+
+struct grub_script_cmd *
+grub_script_create_cmdif (struct grub_script_cmd *bool,
+                         struct grub_script_cmd *true,
+                         struct grub_script_cmd *false);
+struct grub_script_cmd *
+grub_script_add_cmd (struct grub_script_cmdblock *cmdblock,
+                    struct grub_script_cmd *cmd);
+struct grub_script_arg *
+grub_script_arg_add (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);
+
+void grub_script_lexer_init (char *s, grub_err_t (*getline) (char **));
+void grub_script_lexer_ref (void);
+void grub_script_lexer_deref (void);
+
+/* Functions to track allocated memory.  */
+void *grub_script_malloc (grub_size_t size);
+struct grub_script_mem *grub_script_mem_record (void);
+struct grub_script_mem *grub_script_mem_record_stop (struct grub_script_mem *restore);
+
+/* Functions used by bison.  */
+int grub_script_yylex (void);
+int grub_script_yyparse (void);
+void grub_script_yyerror (char const *err);
+
+/* 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);
+
+/* 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;
+
+\f
+
+/* 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);
index 431c07650c06050dc5ca997979de8c8cfe67a45f..5df26e7c0126234ab37e39e85b59d89765e1976d 100644 (file)
@@ -25,6 +25,7 @@
 #include <grub/env.h>
 #include <grub/dl.h>
 #include <grub/parser.h>
+#include <grub/script.h>
 
 static grub_command_t grub_command_list;
 
@@ -193,42 +194,9 @@ grub_command_execute (char *cmdline, int interactive)
       return grub_cmdline_get (">", *s, GRUB_MAX_CMDLINE, 0, 1);
     }
 
-  grub_command_t cmd;
   grub_err_t ret = 0;
   char *pager;
-  int num;
-  char **args;
-  struct grub_arg_list *state;
-  struct grub_arg_option *parser;
-  int maxargs = 0;
-  char **arglist;
-  int numargs;
-
-  if (grub_parser_split_cmdline (cmdline, cmdline_get, &num, &args))
-    return 0;
-  
-  /* In case of an assignment set the environment accordingly instead
-     of calling a function.  */
-  if (num == 0 && grub_strchr (args[0], '='))
-    {
-      char *val;
-
-      if (! interactive)
-       grub_printf ("%s\n", cmdline);
-      
-      val = grub_strchr (args[0], '=');
-      val[0] = 0;
-      grub_env_set (args[0], val + 1);
-      val[0] = '=';
-      return 0;
-    }
-  
-  cmd = grub_command_find (args[0]);
-  if (! cmd)
-    return -1;
-
-  if (! (cmd->flags & GRUB_COMMAND_FLAG_NO_ECHO) && ! interactive)
-    grub_printf ("%s\n", cmdline);
+  struct grub_script *parsed_script;
   
   /* Enable the pager if the environment pager is set to 1.  */
   if (interactive)
@@ -237,27 +205,22 @@ grub_command_execute (char *cmdline, int interactive)
     pager = 0;
   if (pager && (! grub_strcmp (pager, "1")))
     grub_set_more (1);
-  
-  parser = (struct grub_arg_option *) cmd->options;
-  while (parser && (parser++)->doc)
-    maxargs++;
 
-  state = grub_malloc (sizeof (struct grub_arg_list) * maxargs);
-  grub_memset (state, 0, sizeof (struct grub_arg_list) * maxargs);
-  if (! (cmd->flags & GRUB_COMMAND_FLAG_NO_ARG_PARSE))
+  /* Parse the script.  */
+  parsed_script = grub_script_parse (cmdline, cmdline_get);
+
+  if (parsed_script)
     {
-      if (grub_arg_parse (cmd, num, &args[1], state, &arglist, &numargs))
-       ret = (cmd->func) (state, numargs, arglist);
+      /* Execute the command(s).  */
+      grub_script_execute (parsed_script);
+
+      /* The parsed script was executed, throw it away.  */
+      grub_script_free (parsed_script);
     }
-  else
-    ret = (cmd->func) (state, num, &args[1]);
-  
-  grub_free (state);
 
   if (pager && (! grub_strcmp (pager, "1")))
     grub_set_more (0);
-  
-  grub_free (args);
+
   return ret;
 }
 
diff --git a/normal/execute.c b/normal/execute.c
new file mode 100644 (file)
index 0000000..98d828e
--- /dev/null
@@ -0,0 +1,204 @@
+/* execute.c -- Execute a GRUB script.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *
+ *  This program 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/env.h>
+#include <grub/script.h>
+
+static int
+grub_script_execute_cmd (struct grub_script_cmd *cmd)
+{
+  if (cmd == 0)
+    return 0;
+  cmd->exec (cmd);
+
+  return 0;
+}
+
+/* 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);
+         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);
+         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;
+  struct grub_arg_list *state;
+  struct grub_arg_option *parser;
+  int maxargs = 0;
+  char **parsed_arglist;
+  int numargs;
+  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)
+    {
+      /* It's not a GRUB command, try all functions.  */
+      func = grub_script_function_find (cmdline->cmdname);
+      if (! func)
+       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)
+    {
+      /* Count the amount of options the command has.  */
+      parser = (struct grub_arg_option *) grubcmd->options;
+      while (parser && (parser++)->doc)
+       maxargs++;
+      
+      /* Set up the option state.  */
+      state = grub_malloc (sizeof (struct grub_arg_list) * maxargs);
+      grub_memset (state, 0, sizeof (struct grub_arg_list) * maxargs);
+  
+      /* Start the command.  */
+      if (! (grubcmd->flags & GRUB_COMMAND_FLAG_NO_ARG_PARSE))
+       {
+         if (grub_arg_parse (grubcmd, argcount, args, state, &parsed_arglist, &numargs))
+           ret = (grubcmd->func) (state, numargs, parsed_arglist);
+       }
+      else
+       ret = (grubcmd->func) (state, argcount, args);
+  
+      grub_free (state);
+    }
+  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 *bool;
+
+  /* Check if the commands results in a true or a false.  The value is
+     read from the env variable `RESULT'.  */
+  grub_script_execute_cmd (cmdif->bool);
+  bool = grub_env_get ("?");
+
+  /* Execute the `if' or the `else' part depending on the value of
+     `RESULT'.  */
+  if (bool && ! grub_strcmp (bool, "0"))
+    return grub_script_execute_cmd (cmdif->true);
+  else
+    return grub_script_execute_cmd (cmdif->false);
+}
+
+\f
+
+/* 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);
+}
diff --git a/normal/function.c b/normal/function.c
new file mode 100644 (file)
index 0000000..7ae5c5b
--- /dev/null
@@ -0,0 +1,127 @@
+/* script.c */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *
+ *  This program 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#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);
+}
diff --git a/normal/lexer.c b/normal/lexer.c
new file mode 100644 (file)
index 0000000..968fffa
--- /dev/null
@@ -0,0 +1,274 @@
+/* lexer.c - The scripting lexer.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *
+ *  This program 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/parser.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/script.h>
+
+#include "grub_script.tab.h"
+
+static grub_parser_state_t grub_script_lexer_state;
+static int grub_script_lexer_done = 0;
+static grub_err_t (*grub_script_lexer_getline) (char **);
+
+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);
+}
+
+/* The amount of references to the lexer by the parser.  If the parser
+   expects tokens the lexer is referenced.  */
+static int grub_script_lexer_refs = 0;
+static char *script;
+static char *newscript;
+
+/* XXX: The lexer is not reentrant.  */
+void
+grub_script_lexer_init (char *s, grub_err_t (*getline) (char **))
+{
+  grub_script_lexer_state = GRUB_PARSER_STATE_TEXT;
+  grub_script_lexer_getline = getline;
+  grub_script_lexer_refs = 0;
+  grub_script_lexer_done = 0;
+  newscript = 0;
+  script = s;
+}
+
+void
+grub_script_lexer_ref (void)
+{
+  grub_script_lexer_refs++;
+}
+
+void
+grub_script_lexer_deref (void)
+{
+  grub_script_lexer_refs--;
+}
+
+int
+grub_script_yylex (void)
+{
+  grub_parser_state_t newstate;
+  char use;
+  char *buffer;
+  char *bp;
+
+  if (grub_script_lexer_done)
+    return 0;
+
+  if (! *script)
+    {
+      /* Check if more tokens are requested by the parser.  */
+      if ((grub_script_lexer_refs
+          || grub_script_lexer_state == GRUB_PARSER_STATE_ESC)
+         && grub_script_lexer_getline)
+       {
+         while (! grub_strlen (script))
+           {
+             grub_free (newscript);
+             grub_script_lexer_getline (&newscript);
+             script = newscript;
+           }
+         grub_dprintf ("scripting", "token=`\\n'\n");
+         if (grub_script_lexer_state != GRUB_PARSER_STATE_ESC)
+           return '\n';
+       }
+      else
+       {
+         grub_free (newscript);
+         newscript = 0;
+         grub_script_lexer_done = 1;
+         grub_dprintf ("scripting", "token=`\\n'\n");
+         return '\n';
+       }
+    }
+
+  newstate = grub_parser_cmdline_state (grub_script_lexer_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 (*script)
+           {
+           case ' ':
+             while (*script)
+               {
+                 newstate = grub_parser_cmdline_state (grub_script_lexer_state,
+                                                       *script, &use);
+                 if (! (grub_script_lexer_state == GRUB_PARSER_STATE_TEXT
+                        && *script == ' '))
+                   {
+                     grub_dprintf ("scripting", "token=` '\n");
+                     return ' ';
+                   }
+                 grub_script_lexer_state = newstate;
+                 script++;
+               }
+             grub_dprintf ("scripting", "token=` '\n");
+             return ' ';
+           case '{':
+           case '}':
+           case ';':
+           case '\n':
+             grub_dprintf ("scripting", "token=`%c'\n", *script);
+             return *(script++);
+           }
+       }
+
+      /* XXX: Use a better size.  */
+      buffer = grub_script_malloc (2096);
+      if (! buffer)
+       return 0;
+
+      bp = buffer;
+
+      /* Read one token, possible quoted.  */
+      while (*script)
+       {
+         newstate = grub_parser_cmdline_state (grub_script_lexer_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 recognised
+            next time when this function is called.  */
+         if (newstate == GRUB_PARSER_STATE_TEXT
+             && grub_script_lexer_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;
+
+         grub_script_lexer_state = newstate;
+         script++;
+       }
+
+      /* A string of text was read in.  */
+      *bp = '\0';
+      grub_dprintf ("scripting", "token=`%s'\n", buffer);
+      grub_script_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, "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 (2096);
+      if (! buffer)
+       return 0;
+
+      bp = buffer;
+
+      /* This is a variable, read the variable name.  */
+      while (*script)
+       {
+         newstate = grub_parser_cmdline_state (grub_script_lexer_state,
+                                               *script, &use);
+
+         /* Check if this character is not part of the variable name
+            anymore.  */
+         if (! (check_varstate (newstate)))
+           {
+             if (grub_script_lexer_state == GRUB_PARSER_STATE_VARNAME2
+                 || grub_script_lexer_state == GRUB_PARSER_STATE_QVARNAME2)
+               script++;
+             grub_script_lexer_state = newstate;
+             break;
+           }
+
+         if (use)
+           *(bp++) = use;
+         script++;
+         grub_script_lexer_state = newstate;
+       }
+
+      *bp = '\0';
+      grub_script_lexer_state = newstate;
+      grub_script_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 (char const *err)
+{
+  grub_printf (err);
+}
diff --git a/normal/parser.y b/normal/parser.y
new file mode 100644 (file)
index 0000000..50fc7c2
--- /dev/null
@@ -0,0 +1,191 @@
+/* parser.y - The scripting parser.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *
+ *  This program 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+%{
+#include <grub/script.h>
+#include <grub/mm.h>
+
+#define YYFREE         grub_free
+#define YYMALLOC       grub_malloc
+
+/* Keep track of the memory allocated for this specific function.  */
+static struct grub_script_mem *func_mem = 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_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 grubcmd command commands 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
+
+%%
+/* It should be possible to do this in a clean way...  */
+script:                commands '\n'
+                 {
+                   grub_script_parsed = $1;
+                 }
+;
+
+/* 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;
+                 }
+;
+
+ws:            /* Empty */
+               | ' '
+;
+
+returns:       /* Empty */
+               | '\n'
+;
+
+/* 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 (0, GRUB_SCRIPT_ARG_TYPE_VAR, $1);
+                 }
+               | text
+                 {
+                   $$ = grub_script_arg_add (0, GRUB_SCRIPT_ARG_TYPE_STR, $1);
+                 }
+               | 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 (0, $1);
+                 }
+               | arguments ' ' argument
+                 {
+                   $$ = grub_script_add_arglist ($1, $3);
+                 }
+;
+
+grubcmd:       ws GRUB_PARSER_TOKEN_NAME ' ' arguments ws
+                 {
+                   $$ = grub_script_create_cmdline ($2, $4);
+                 }
+               | ws GRUB_PARSER_TOKEN_NAME ws
+                 {
+                   $$ = grub_script_create_cmdline ($2, 0);
+                 }
+;
+
+/* A single command.  */
+command:       grubcmd         { $$ = $1; }
+               | if            { $$ = $1; }
+               | function      { $$ = 0;  }
+;
+
+/* A block of commands.  */
+commands:      command
+                 { 
+                   $$ = grub_script_add_cmd (0, $1);
+                 }
+               | commands ';' command
+                 { 
+                   struct grub_script_cmdblock *cmd;
+                   cmd = (struct grub_script_cmdblock *) $1;
+                   $$ = grub_script_add_cmd (cmd, $3);
+                 }
+               | commands '\n' command
+                 { 
+                   struct grub_script_cmdblock *cmd;
+                   cmd = (struct grub_script_cmdblock *) $1;
+                   $$ = grub_script_add_cmd (cmd, $3);
+                 }
+;
+
+/* A function.  Carefully save the memory that is allocated.  */
+function:      "function" ' ' GRUB_PARSER_TOKEN_NAME
+                 { 
+                   grub_script_lexer_ref ();
+                 } ws '{' returns
+                 { 
+                   /* The first part of the function was recognised.
+                      Now start recording the memory usage to store
+                      this function.  */
+                   func_mem = grub_script_mem_record ();
+                 } commands returns '}'
+                 {
+                   struct grub_script *script;
+
+                   /* All the memory usage for parsing this function
+                      was recorded.  */
+                   func_mem = grub_script_mem_record_stop (func_mem);
+                   script = grub_script_create ($9, func_mem);
+                   if (script)
+                     grub_script_function_create ($3, script);
+                   grub_script_lexer_deref ();
+                 }
+;
+
+/* 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 (); }
+;
+
+/* The if statement.  */
+if:             if_statement grubcmd ';' ws "then" returns commands returns "fi"
+                 {
+                   $$ = grub_script_create_cmdif ($2, $7, 0);
+                   grub_script_lexer_deref ();
+                 }
+                | if_statement grubcmd ';' ws "then" returns commands returns "else" returns commands "fi"
+                 {
+                   $$ = grub_script_create_cmdif ($2, $7, $11);
+                   grub_script_lexer_deref ();
+                 }
+;
diff --git a/normal/script.c b/normal/script.c
new file mode 100644 (file)
index 0000000..f14254e
--- /dev/null
@@ -0,0 +1,289 @@
+/* script.c -- Functions to create an in memory description of the script. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005  Free Software Foundation, Inc.
+ *
+ *  This program 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#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 free'ed in case of an error, or
+   assigned to the parsed script when parsing was successful.  */
+
+/* The memory that was used while parsing and scanning.  */
+static struct grub_script_mem *grub_script_memused;
+
+/* The result of the parser.  */
+struct grub_script_cmd *grub_script_parsed = 0;
+
+/* 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 free'ed.  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 (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 = grub_script_memused;
+  grub_script_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 (void)
+{
+  struct grub_script_mem *mem = grub_script_memused;
+  grub_script_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_script_mem *restore)
+{
+  struct grub_script_mem *mem = grub_script_memused;
+  grub_script_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);
+}
+
+\f
+
+/* 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_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 (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_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 (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 (char *cmdname, struct grub_script_arglist *arglist)
+{
+  struct grub_script_cmdline *cmd;
+
+  grub_dprintf ("scripting", "cmdline\n");
+
+  cmd = grub_script_malloc (sizeof (*cmd));
+  cmd->cmd.exec = grub_script_execute_cmdline;
+/*   cmd->cmd.free = grub_script_free_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 RESULT), the
+   interpreter will run the command TRUE, otherwise the interpreter
+   runs the command FALSE.  */
+struct grub_script_cmd *
+grub_script_create_cmdif (struct grub_script_cmd *bool,
+                         struct grub_script_cmd *true,
+                         struct grub_script_cmd *false)
+{
+  struct grub_script_cmdif *cmd;
+
+  grub_dprintf ("scripting", "cmdif\n");
+
+  cmd = grub_script_malloc (sizeof (*cmd));
+  cmd->cmd.exec = grub_script_execute_cmdif;
+  cmd->cmd.next = 0;
+  cmd->bool = bool;
+  cmd->true = true;
+  cmd->false = false;
+
+  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_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 (sizeof (*cmdblock));
+      cmdblock->cmd.exec = grub_script_execute_cmdblock;
+      cmdblock->cmd.next = 0;
+      cmdblock->cmdlist = cmd;
+    }
+  else
+    {
+      struct grub_script_cmd **last;
+      for (last = &cmdblock->cmdlist; *last; last = &(*last)->next);
+      *last = cmd;
+    }
+
+  cmd->next = 0;
+
+  return (struct grub_script_cmd *) cmdblock;
+}
+
+\f
+
+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;
+
+  parsed = grub_malloc (sizeof (*parsed));
+  if (! parsed)
+    return 0;
+
+  /* Initialize the lexer.  */
+  grub_script_lexer_init (script, getline);
+
+  grub_script_parsed = 0;
+
+  membackup = grub_script_mem_record ();
+
+  /* Parse the script, the result is stored in
+     `grub_script_parsed'.  */
+  if (grub_script_yyparse ())
+    {
+      struct grub_script_mem *memfree;
+      memfree = grub_script_mem_record_stop (membackup);
+      grub_script_mem_free (memfree);
+      return 0;
+    }
+
+  parsed->mem = grub_script_mem_record_stop (membackup);
+  parsed->cmd = grub_script_parsed;
+
+  return parsed;
+}
index c74d77d860197d92e081af68f66c50e1f2d9b7da..193a28f2b1d20d5320bf9c78ac07f63274def776 100644 (file)
@@ -219,6 +219,7 @@ main (int argc, char *argv[])
   grub_timeout_init ();
   grub_configfile_init ();
   grub_search_init ();
+  grub_test_init ();
   
   /* XXX: Should normal mode be started by default?  */
   grub_normal_init ();
@@ -227,6 +228,7 @@ main (int argc, char *argv[])
   if (setjmp (main_env) == 0)
     grub_main ();
 
+  grub_test_fini ();
   grub_search_fini ();
   grub_configfile_fini ();
   grub_timeout_fini ();