On Sat, Feb 14, 2009 at 11:11 PM, Felix Zielcke <fziel...@z-51.de> wrote:
>     A. Am Samstag, den 14.02.2009, 22:46 +0800 schrieb Bean:
>
>> If there is no objection, I'd commit this patch in a few days.
>
> Hello Bean,
>
> if you want to drop termin_input and terminal_output command then please
> don't forget to update util/grub.d/00_header.in
>
> +GRUB_MOD_INIT(handler)
> +{
> +  (void)mod;                   /* To stop warning. */
> +  grub_register_command ("handler", grub_cmd_handler,
> GRUB_COMMAND_FLAG_BOTH,
> +                        "handler [class [handler]]",
> +                        "List or select a handler", 0);
> +}
> +
> +GRUB_MOD_FINI(handler)
> +{
> +  grub_unregister_command ("hello");
> +}
>
> This should probable be grub_unregister_command ("handler").

Hi,

Thanks for pointing out, this new patch should fix the problem.

-- 
Bean
diff --git a/commands/handler.c b/commands/handler.c
new file mode 100644
index 0000000..9f4e632
--- /dev/null
+++ b/commands/handler.c
@@ -0,0 +1,105 @@
+/* handler.c - test module for dynamic loading */
+/*
+ *  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/normal.h>
+#include <grub/dl.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/handler.h>
+
+static grub_err_t
+grub_cmd_handler (struct grub_arg_list *state __attribute__ ((unused)),
+		  int argc, char **args)
+{
+  char *find_name;
+  void *find_result;
+  void *curr_item = 0;
+
+  auto int list_item (grub_handler_class_t item);
+  int list_item (grub_handler_class_t item)
+    {
+      if (item == curr_item)
+	grub_putchar ('*');
+
+      grub_printf ("%s\n", item->name);
+
+      return 0;
+    }
+
+  auto int find_item (grub_handler_class_t item);
+  int find_item (grub_handler_class_t item)
+    {
+      if (! grub_strcmp (item->name, find_name))
+	{
+	  find_result = item;
+	  return 1;
+	}
+
+      return 0;
+    }
+
+  if (argc == 0)
+    {
+      grub_handler_class_iterate (list_item);
+    }
+  else
+    {
+      grub_handler_class_t class;
+
+      find_name = args[0];
+      find_result = 0;
+      grub_handler_class_iterate (find_item);
+      if (! find_result)
+	return grub_error (GRUB_ERR_FILE_NOT_FOUND, "class not found");
+
+      class = find_result;
+
+      if (argc == 1)
+	{
+	  curr_item = class->cur_handler;
+	  grub_handler_iterate (find_result, (grub_list_hook_t) list_item);
+	}
+      else
+	{
+	  find_name = args[1];
+	  find_result = 0;
+	  grub_handler_iterate (class, (grub_list_hook_t) find_item);
+
+	  if (! find_result)
+	    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "handler not found");
+
+	  grub_handler_set_current (class, find_result);
+	}
+    }
+
+  return 0;
+}
+
+GRUB_MOD_INIT(handler)
+{
+  (void)mod;			/* To stop warning. */
+  grub_register_command ("handler", grub_cmd_handler, GRUB_COMMAND_FLAG_BOTH,
+			 "handler [class [handler]]",
+			 "List or select a handler", 0);
+}
+
+GRUB_MOD_FINI(handler)
+{
+  grub_unregister_command ("handler");
+}
diff --git a/conf/common.rmk b/conf/common.rmk
index dfd481a..9a62ac3 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -330,7 +330,7 @@ scsi_mod_CFLAGS = $(COMMON_CFLAGS)
 scsi_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # Commands.
-pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod	\
+pkglib_MODULES += hello.mod boot.mod handler.mod ls.mod	\
 	cmp.mod cat.mod help.mod search.mod					\
 	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
@@ -346,10 +346,10 @@ boot_mod_SOURCES = commands/boot.c
 boot_mod_CFLAGS = $(COMMON_CFLAGS)
 boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For terminal.mod.
-terminal_mod_SOURCES = commands/terminal.c
-terminal_mod_CFLAGS = $(COMMON_CFLAGS)
-terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For handler.mod.
+handler_mod_SOURCES = commands/handler.c
+handler_mod_CFLAGS = $(COMMON_CFLAGS)
+handler_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For ls.mod.
 ls_mod_SOURCES = commands/ls.c
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index b97483b..4938665 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -17,7 +17,7 @@ kernel_elf_SOURCES = kern/i386/coreboot/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/loader.c kern/rescue.c kern/term.c \
-	kern/time.c \
+	kern/time.c kern/list.c kern/handler.c \
 	kern/i386/dl.c kern/parser.c kern/partition.c \
 	kern/i386/tsc.c kern/i386/pit.c \
 	kern/generic/rtc_get_time_ms.c \
@@ -30,7 +30,7 @@ kernel_elf_HEADERS = arg.h 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 \
 	machine/boot.h machine/console.h machine/init.h \
-	machine/memory.h machine/loader.h
+	machine/memory.h machine/loader.h list.h handler.h
 kernel_elf_CFLAGS = $(COMMON_CFLAGS)
 kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x8200,-Bstatic
@@ -57,7 +57,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
 grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c	\
 	commands/configfile.c commands/echo.c commands/help.c		\
-	commands/terminal.c commands/ls.c commands/test.c 		\
+	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	lib/hexdump.c commands/i386/cpuid.c				\
 	disk/host.c disk/loopback.c					\
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 3814abb..7ae9c5e 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -34,7 +34,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
 grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c 	\
 	commands/configfile.c commands/help.c				\
-	commands/terminal.c commands/ls.c commands/test.c 		\
+	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/hexdump.c lib/hexdump.c		\
 	commands/halt.c commands/reboot.c				\
 	commands/i386/cpuid.c						\
@@ -88,14 +88,14 @@ kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.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 \
-	kern/time.c \
+	kern/time.c kern/list.c kern/handler.c \
 	kern/i386/tsc.c kern/i386/pit.c \
 	kern/generic/rtc_get_time_ms.c \
 	kern/generic/millisleep.c
 kernel_mod_HEADERS = arg.h 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 \
-	efi/efi.h efi/time.h efi/disk.h
+	efi/efi.h efi/time.h efi/disk.h list.h handler.h
 kernel_mod_CFLAGS = $(COMMON_CFLAGS)
 kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 903113e..16a3fba 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -20,7 +20,7 @@ kernel_elf_SOURCES = kern/i386/ieee1275/startup.S kern/i386/ieee1275/init.c \
 	kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
 	kern/i386/dl.c kern/parser.c kern/partition.c \
 	kern/env.c \
-	kern/time.c \
+	kern/time.c kern/list.c kern/handler.c \
 	kern/generic/millisleep.c \
 	kern/ieee1275/ieee1275.c \
 	term/ieee1275/ofconsole.c \
@@ -29,7 +29,8 @@ kernel_elf_SOURCES = kern/i386/ieee1275/startup.S kern/i386/ieee1275/init.c \
 kernel_elf_HEADERS = arg.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 \
-	ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h
+	ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h \
+	list.h handler.h
 kernel_elf_CFLAGS = $(COMMON_CFLAGS)
 kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic
 
@@ -55,7 +56,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
 grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c	\
 	commands/configfile.c commands/echo.c commands/help.c		\
-	commands/terminal.c commands/ls.c commands/test.c 		\
+	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	lib/hexdump.c commands/halt.c commands/reboot.c			\
 	commands/i386/cpuid.c						\
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 3ef351e..9e83bda 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -42,7 +42,7 @@ cdboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,7C00
 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/loader.c kern/rescue.c kern/term.c \
-	kern/time.c \
+	kern/time.c kern/list.c kern/handler.c \
 	kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
 	kern/parser.c kern/partition.c \
 	kern/i386/tsc.c kern/i386/pit.c \
@@ -56,7 +56,7 @@ kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
 	partition.h pc_partition.h rescue.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
+	machine/kernel.h machine/pxe.h list.h handler.h
 kernel_img_CFLAGS = $(COMMON_CFLAGS)
 kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,$(GRUB_MEMORY_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)
@@ -114,7 +114,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
 grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c	\
 	commands/configfile.c commands/echo.c commands/help.c		\
-	commands/terminal.c commands/ls.c commands/test.c 		\
+	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c		\
 	commands/i386/cpuid.c						\
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index 51e7c07..bedd4e0 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -40,7 +40,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
 grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c 	\
 	commands/configfile.c commands/help.c				\
-	commands/search.c commands/terminal.c commands/test.c 		\
+	commands/search.c commands/handler.c commands/test.c 		\
 	commands/ls.c commands/blocklist.c commands/hexdump.c		\
 	lib/hexdump.c commands/halt.c commands/reboot.c			\
 	disk/loopback.c							\
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index 640ceda..18c108e 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -44,7 +44,7 @@ grub_mkimage_SOURCES = util/sparc64/ieee1275/grub-mkimage.c util/misc.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/search.c commands/terminal.c commands/ls.c		\
+#	commands/search.c commands/handler.c commands/ls.c		\
 #	commands/timeout.c commands/test.c				\
 #	commands/halt.c commands/reboot.c		\
 #	disk/loopback.c							\
@@ -76,8 +76,8 @@ kernel_elf_SOURCES = kern/sparc64/ieee1275/init.c kern/ieee1275/ieee1275.c \
 	kern/sparc64/ieee1275/openfw.c disk/ieee1275/ofdisk.c \
 	kern/partition.c kern/env.c kern/sparc64/dl.c symlist.c \
 	kern/generic/millisleep.c kern/generic/get_time_ms.c \
-	kern/sparc64/cache.S kern/parser.c
-kernel_elf_HEADERS = grub/sparc64/ieee1275/ieee1275.h
+	kern/sparc64/cache.S kern/parser.c kern/list.c kern/handler.c
+kernel_elf_HEADERS = grub/sparc64/ieee1275/ieee1275.h list.h handler.h
 kernel_elf_CFLAGS = $(COMMON_CFLAGS)
 kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_elf_LDFLAGS = -mno-app-regs -nostdlib -Wl,-N,-Ttext,0x200000,-Bstatic,-melf64_sparc
@@ -86,7 +86,7 @@ kernel_elf_LDFLAGS = -mno-app-regs -nostdlib -Wl,-N,-Ttext,0x200000,-Bstatic,-me
 #_linux.mod linux.mod
 pkglib_MODULES = fat.mod ufs.mod ext2.mod minix.mod \
 	hfs.mod jfs.mod normal.mod hello.mod font.mod ls.mod \
-	boot.mod cmp.mod cat.mod terminal.mod fshelp.mod amiga.mod apple.mod \
+	boot.mod cmp.mod cat.mod handler.mod fshelp.mod amiga.mod apple.mod \
 	pc.mod suspend.mod loopback.mod help.mod reboot.mod halt.mod sun.mod \
 	configfile.mod search.mod gzio.mod xfs.mod \
 	affs.mod sfs.mod acorn.mod
@@ -187,10 +187,10 @@ boot_mod_SOURCES = commands/boot.c
 boot_mod_CFLAGS = $(COMMON_CFLAGS)
 boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For terminal.mod.
-terminal_mod_SOURCES = commands/terminal.c
-terminal_mod_CFLAGS = $(COMMON_CFLAGS)
-terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For handler.mod.
+handler_mod_SOURCES = commands/handler.c
+handler_mod_CFLAGS = $(COMMON_CFLAGS)
+handler_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For ls.mod.
 ls_mod_SOURCES = commands/ls.c
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 5b108d2..07bf1a6 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -36,7 +36,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
 grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c 	\
 	commands/configfile.c commands/help.c				\
-	commands/terminal.c commands/ls.c commands/test.c 		\
+	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/hexdump.c lib/hexdump.c		\
 	commands/halt.c commands/reboot.c				\
 	commands/i386/cpuid.c						\
@@ -90,14 +90,14 @@ kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \
 	kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.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/time.c kern/list.c kern/handler.c \
 	kern/i386/tsc.c kern/i386/pit.c \
 	kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c \
 	term/efi/console.c disk/efi/efidisk.c
 kernel_mod_HEADERS = arg.h 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 \
-	efi/efi.h efi/time.h efi/disk.h machine/loader.h
+	efi/efi.h efi/time.h efi/disk.h machine/loader.h list.h handler.h
 kernel_mod_CFLAGS = $(COMMON_CFLAGS)
 kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
 kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/include/grub/handler.h b/include/grub/handler.h
new file mode 100644
index 0000000..826fd2b
--- /dev/null
+++ b/include/grub/handler.h
@@ -0,0 +1,63 @@
+/* handler.h - header for grub handler */
+/*
+ *  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_HANDLER_HEADER
+#define GRUB_HANDLER_HEADER 1
+
+#include <grub/list.h>
+#include <grub/err.h>
+
+struct grub_handler
+{
+  struct grub_handler *next;
+  const char *name;
+  grub_err_t (*init) (void);
+  grub_err_t (*fini) (void);
+};
+typedef struct grub_handler *grub_handler_t;
+
+struct grub_handler_class
+{
+  struct grub_handler_class *next;
+  const char *name;
+  grub_list_t handler_list;
+  struct grub_handler *cur_handler;
+};
+typedef struct grub_handler_class *grub_handler_class_t;
+
+void EXPORT_FUNC(grub_handler_class_iterate) (int (*hook)
+					      (grub_handler_class_t item));
+
+void EXPORT_FUNC(grub_handler_register) (grub_handler_class_t class,
+					 grub_handler_t handler);
+void EXPORT_FUNC(grub_handler_unregister) (grub_handler_class_t class,
+					   grub_handler_t handler);
+void EXPORT_FUNC(grub_handler_iterate) (grub_handler_class_t class,
+					grub_list_hook_t hook);
+grub_err_t EXPORT_FUNC(grub_handler_set_current) (grub_handler_class_t class,
+						  grub_handler_t handler);
+
+#define GRUB_AS_HANDLER(ptr) \
+  ((GRUB_FIELD_MATCH (ptr, grub_handler_t, next) && \
+    GRUB_FIELD_MATCH (ptr, grub_handler_t, name) && \
+    GRUB_FIELD_MATCH (ptr, grub_handler_t, init) && \
+    GRUB_FIELD_MATCH (ptr, grub_handler_t, fini)) ? \
+   (grub_handler_t) ptr : grub_assert_fail ())
+
+#endif /* ! GRUB_HANDLER_HEADER */
diff --git a/include/grub/list.h b/include/grub/list.h
new file mode 100644
index 0000000..59b352a
--- /dev/null
+++ b/include/grub/list.h
@@ -0,0 +1,50 @@
+/* list.h - header for grub list */
+/*
+ *  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_LIST_HEADER
+#define GRUB_LIST_HEADER 1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+struct grub_list
+{
+  struct grub_list *next;
+};
+typedef struct grub_list *grub_list_t;
+
+typedef int (*grub_list_hook_t) (grub_list_t item);
+
+void EXPORT_FUNC(grub_list_push) (grub_list_t *head, grub_list_t item);
+void * EXPORT_FUNC(grub_list_pop) (grub_list_t *head);
+void EXPORT_FUNC(grub_list_remove) (grub_list_t *head, grub_list_t item);
+void EXPORT_FUNC(grub_list_iterate) (grub_list_t head, grub_list_hook_t hook);
+
+/* This function doesn't exist, so if assertion is false for some reason, the
+   linker would fail.  */
+extern void* grub_assert_fail (void);
+
+#define GRUB_FIELD_MATCH(ptr, type, field) \
+  ((char *) &(ptr)->field == (char *) &((type) (ptr))->field)
+
+#define GRUB_AS_LIST(ptr) \
+  (GRUB_FIELD_MATCH (ptr, grub_list_t, next) ? \
+   (grub_list_t) ptr : grub_assert_fail ())
+
+#endif /* ! GRUB_LIST_HEADER */
diff --git a/include/grub/term.h b/include/grub/term.h
index 13835bb..8ac8bc5 100644
--- a/include/grub/term.h
+++ b/include/grub/term.h
@@ -38,6 +38,7 @@
 #include <grub/err.h>
 #include <grub/symbol.h>
 #include <grub/types.h>
+#include <grub/handler.h>
 
 /* These are used to represent the various color states we use.  */
 typedef enum
@@ -139,6 +140,9 @@ grub_term_color_state;
 
 struct grub_term_input
 {
+  /* The next terminal.  */
+  struct grub_term_input *next;
+
   /* The terminal name.  */
   const char *name;
 
@@ -153,14 +157,14 @@ struct grub_term_input
   
   /* Get a character.  */
   int (*getkey) (void);
-
-  /* The next terminal.  */
-  struct grub_term_input *next;
 };
 typedef struct grub_term_input *grub_term_input_t;
 
 struct grub_term_output
 {
+  /* The next terminal.  */
+  struct grub_term_output *next;
+
   /* The terminal name.  */
   const char *name;
 
@@ -208,9 +212,6 @@ struct grub_term_output
 
   /* The feature flags defined above.  */
   grub_uint32_t flags;
-  
-  /* The next terminal.  */
-  struct grub_term_output *next;
 };
 typedef struct grub_term_output *grub_term_output_t;
 
@@ -218,8 +219,6 @@ void EXPORT_FUNC(grub_term_register_input) (grub_term_input_t term);
 void EXPORT_FUNC(grub_term_register_output) (grub_term_output_t term);
 void EXPORT_FUNC(grub_term_unregister_input) (grub_term_input_t term);
 void EXPORT_FUNC(grub_term_unregister_output) (grub_term_output_t term);
-void EXPORT_FUNC(grub_term_iterate_input) (int (*hook) (grub_term_input_t term));
-void EXPORT_FUNC(grub_term_iterate_output) (int (*hook) (grub_term_output_t term));
 
 grub_err_t EXPORT_FUNC(grub_term_set_current_input) (grub_term_input_t term);
 grub_err_t EXPORT_FUNC(grub_term_set_current_output) (grub_term_output_t term);
diff --git a/kern/handler.c b/kern/handler.c
new file mode 100644
index 0000000..b22d9af
--- /dev/null
+++ b/kern/handler.c
@@ -0,0 +1,72 @@
+/* handler.c - grub handler function*/
+/*
+ *  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/handler.h>
+
+static grub_list_t grub_handler_class_list;
+
+void
+grub_handler_class_iterate (int (*hook) (grub_handler_class_t item))
+{
+  grub_list_iterate (grub_handler_class_list, (grub_list_hook_t) hook);
+}
+
+void
+grub_handler_register (grub_handler_class_t class, grub_handler_t handler)
+{
+  int first_handler = (class->handler_list == 0);
+
+  grub_list_push (&class->handler_list, GRUB_AS_LIST (handler));
+
+  if (first_handler)
+    {
+      grub_list_push (&grub_handler_class_list, GRUB_AS_LIST (class));
+      grub_handler_set_current (class, handler);
+    }
+}
+
+void
+grub_handler_unregister (grub_handler_class_t class, grub_handler_t handler)
+{
+  grub_list_remove (&class->handler_list, GRUB_AS_LIST (handler));
+
+  if (class->handler_list == 0)
+    grub_list_remove (&grub_handler_class_list, GRUB_AS_LIST (class));
+}
+
+void
+grub_handler_iterate (grub_handler_class_t class, grub_list_hook_t hook)
+{
+  grub_list_iterate (class->handler_list, hook);
+}
+
+grub_err_t
+grub_handler_set_current (grub_handler_class_t class, grub_handler_t handler)
+{
+  if (class->cur_handler && class->cur_handler->fini)
+    if ((class->cur_handler->fini) () != GRUB_ERR_NONE)
+      return grub_errno;
+
+  if (handler->init)
+    if ((handler->init) () != GRUB_ERR_NONE)
+      return grub_errno;
+
+  class->cur_handler = handler;
+  return GRUB_ERR_NONE;
+}
diff --git a/kern/list.c b/kern/list.c
new file mode 100644
index 0000000..e553443
--- /dev/null
+++ b/kern/list.c
@@ -0,0 +1,62 @@
+/* list.c - grub list function*/
+/*
+ *  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/list.h>
+
+void
+grub_list_push (grub_list_t *head, grub_list_t item)
+{
+  item->next = *head;
+  *head = item;
+}
+
+void *
+grub_list_pop (grub_list_t *head)
+{
+  grub_list_t item;
+
+  item = *head;
+  if (item)
+    *head = item->next;
+
+  return item;
+}
+
+void
+grub_list_remove (grub_list_t *head, grub_list_t item)
+{
+  grub_list_t *p, q;
+
+  for (p = head, q = *p; q; p = &(q->next), q = q->next)
+    if (q == item)
+      {
+	*p = q->next;
+	break;
+      }
+}
+
+void
+grub_list_iterate (grub_list_t head, grub_list_hook_t hook)
+{
+  grub_list_t p;
+
+  for (p = head; p; p = p->next)
+    if (hook (p))
+      break;
+}
diff --git a/kern/term.c b/kern/term.c
index 8d5a23b..3de1db4 100644
--- a/kern/term.c
+++ b/kern/term.c
@@ -22,14 +22,6 @@
 #include <grub/misc.h>
 #include <grub/env.h>
 
-/* The list of terminals.  */
-static grub_term_input_t grub_term_list_input;
-static grub_term_output_t grub_term_list_output;
-
-/* The current terminal.  */
-static grub_term_input_t grub_cur_term_input;
-static grub_term_output_t grub_cur_term_output;
-
 /* The amount of lines counted by the pager.  */
 static int grub_more_lines;
 
@@ -39,98 +31,58 @@ static int grub_more;
 /* The current cursor state.  */
 static int cursor_state = 1;
 
+static struct grub_handler_class grub_term_input_class =
+  {
+    .name = "input"
+  };
+
+static struct grub_handler_class grub_term_output_class =
+  {
+    .name = "output"
+  };
+
+#define grub_cur_term_input \
+  ((grub_term_input_t) grub_term_input_class.cur_handler)
+
+#define grub_cur_term_output \
+  ((grub_term_output_t) grub_term_output_class.cur_handler)
+
 void
 grub_term_register_input (grub_term_input_t term)
 {
-  term->next = grub_term_list_input;
-  grub_term_list_input = term;
-  if (! grub_cur_term_input)
-    grub_term_set_current_input (term);
+  grub_handler_register (&grub_term_input_class, GRUB_AS_HANDLER (term));
 }
 
 void
 grub_term_register_output (grub_term_output_t term)
 {
-  term->next = grub_term_list_output;
-  grub_term_list_output = term;
-  if (! grub_cur_term_output)
-    grub_term_set_current_output (term);
+  grub_handler_register (&grub_term_output_class, GRUB_AS_HANDLER (term));
 }
 
 void
 grub_term_unregister_input (grub_term_input_t term)
 {
-  grub_term_input_t *p, q;
-  
-  for (p = &grub_term_list_input, q = *p; q; p = &(q->next), q = q->next)
-    if (q == term)
-      {
-        *p = q->next;
-	break;
-      }
+  grub_handler_unregister (&grub_term_input_class, GRUB_AS_HANDLER (term));
 }
 
 void
 grub_term_unregister_output (grub_term_output_t term)
 {
-  grub_term_output_t *p, q;
-  
-  for (p = &grub_term_list_output, q = *p; q; p = &(q->next), q = q->next)
-    if (q == term)
-      {
-        *p = q->next;
-	break;
-      }
-}
-
-void
-grub_term_iterate_input (int (*hook) (grub_term_input_t term))
-{
-  grub_term_input_t p;
-  
-  for (p = grub_term_list_input; p; p = p->next)
-    if (hook (p))
-      break;
-}
-
-void
-grub_term_iterate_output (int (*hook) (grub_term_output_t term))
-{
-  grub_term_output_t p;
-  
-  for (p = grub_term_list_output; p; p = p->next)
-    if (hook (p))
-      break;
+  grub_handler_unregister (&grub_term_output_class, GRUB_AS_HANDLER (term));
 }
 
 grub_err_t
 grub_term_set_current_input (grub_term_input_t term)
 {
-  if (grub_cur_term_input && grub_cur_term_input->fini)
-    if ((grub_cur_term_input->fini) () != GRUB_ERR_NONE)
-      return grub_errno;
-
-  if (term->init)
-    if ((term->init) () != GRUB_ERR_NONE)
-      return grub_errno;
-  
-  grub_cur_term_input = term;
-  return GRUB_ERR_NONE;
+  return grub_handler_set_current (&grub_term_input_class,
+				   GRUB_AS_HANDLER (term));
 }
 
 grub_err_t
 grub_term_set_current_output (grub_term_output_t term)
 {
-  if (grub_cur_term_output && grub_cur_term_output->fini)
-    if ((grub_cur_term_output->fini) () != GRUB_ERR_NONE)
-      return grub_errno;
-
-  if (term->init)
-    if ((term->init) () != GRUB_ERR_NONE)
-      return grub_errno;
-  
-  grub_cur_term_output = term;
-  return GRUB_ERR_NONE;
+  return grub_handler_set_current (&grub_term_output_class,
+				   GRUB_AS_HANDLER (term));
 }
 
 grub_term_input_t
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
index d8fa416..236ba51 100644
--- a/util/grub.d/00_header.in
+++ b/util/grub.d/00_header.in
@@ -60,10 +60,14 @@ case x${GRUB_TERMINAL_INPUT} in
   ;;
   x*)
     cat << EOF
-if terminal_input ${GRUB_TERMINAL_INPUT} ; then true ; else
-  # For backward compatibility with versions of terminal.mod that don't
-  # understand terminal_input
-  terminal ${GRUB_TERMINAL_INPUT}
+if handler input ${GRUB_TERMINAL_INPUT} ; then true ; else
+  # For backward compatibility with versions that uses terminal.mod instead
+  # of handler.mod
+  if terminal_input ${GRUB_TERMINAL_INPUT} ; then true ; else
+    # For backward compatibility with versions of terminal.mod that don't
+    # understand terminal_input
+    terminal ${GRUB_TERMINAL_INPUT}
+  fi
 fi
 EOF
   ;;
@@ -91,10 +95,14 @@ if loadfont `make_system_path_relative_to_its_root ${GRUB_FONT_PATH}` ; then
   set gfxmode=${GRUB_GFXMODE}
   insmod gfxterm
   insmod ${video_backend}
-  if terminal_output gfxterm ; then true ; else
-    # For backward compatibility with versions of terminal.mod that don't
-    # understand terminal_output
-    terminal gfxterm
+  if handler output gfxterm ; then true ; else
+    # For backward compatibility with versions that uses terminal.mod instead
+    # of handler.mod
+    if terminal_output gfxterm ; then true ; else
+      # For backward compatibility with versions of terminal.mod that don't
+      # understand terminal_output
+      terminal gfxterm
+    fi
   fi
 fi
 EOF
@@ -104,10 +112,14 @@ EOF
   ;;
   x*)
     cat << EOF
-if terminal_output ${GRUB_TERMINAL_OUTPUT} ; then true ; else
-  # For backward compatibility with versions of terminal.mod that don't
-  # understand terminal_output
-  terminal ${GRUB_TERMINAL_OUTPUT}
+if handler output ${GRUB_TERMINAL_OUTPUT} ; then true ; else
+  # For backward compatibility with versions that uses terminal.mod instead
+  # of handler.mod
+  if terminal_output ${GRUB_TERMINAL_OUTPUT} ; then true ; else
+    # For backward compatibility with versions of terminal.mod that don't
+    # understand terminal_output
+    terminal ${GRUB_TERMINAL_OUTPUT}
+  fi
 fi
 EOF
   ;;
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to