grub-devel
[Top][All Lists]
Advanced

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

[PATCH] Handler support


From: Bean
Subject: [PATCH] Handler support
Date: Thu, 12 Feb 2009 20:01:53 +0800

Hi,

This patch add handler support, the lowest level structure is list,
which represent a linked list:

struct grub_list
{
  struct grub_list *next;
};

functions to manipulate the list object:
grub_list_push, grub_list_pop, grub_list_remove and grub_list_iterate.

Another new structure is handler class, which represent a class of handlers:

struct grub_handler_class
{
  struct grub_handler_class *next;
  const char *name;
  grub_list_t handler_list;
  struct grub_handler *cur_handler;
};

functions:
grub_handler_class_register, grub_handler_class_unregister,
grub_handler_class_iterate

Finally, it's the handler structure:

struct grub_handler
{
  struct grub_handler *next;
  const char *name;
  grub_err_t (*init) (void);
  grub_err_t (*fini) (void);
};

functions:
grub_handler_register, grub_handler_unregister, grub_handler_iterate,
grub_handler_set_current, grub_handler_get_current

handler class and handler are lists, the register and unregister
function calls the list function to do the job.

I convert the terminal_input and terminal_output to use the new
handler modal, but this can also apply to other parts of grub2.
Structure lile fs, partmap, modules, commands are lists, and script
engine, menu viewer and so on can be converted to handlers.

Using handler method, terminal_input and terminal_output command are
not necessary anymore. Instead, we can have a generic handler command:

handler [class [handler]]

called with no argument, it lists all handler class.
called with 1 argument, it lists all handlers in a selected class.
called with 2 argument, it set the current handler for a selected class.

handler might be better implemented using the object orient features,
however, this would be a overkill for grub2. Instead, I use a simpler
compiler type checking method. For example, here is a code segment:

void
grub_handler_register (grub_handler_class_t class, void *handler)
{
  int first_handler = (class->cur_handler == 0);

  GRUB_ASSERT_IS_LIST (grub_handler);
  grub_list_push (&class->handler_list, handler);

  if (first_handler)
    grub_handler_set_current (class, handler);
}

the handler type is void*, which allows it to pass pointers around
without casting. Inside the function, when we want to use handler as a
list object, we call macro GRUB_ASSERT_IS_LIST. This macro confirms
that the fields required by grub_list is at the same location as in
grub_handler, so we don't run into problem when accessing the
structure in lower layout. Likewise, GRUB_ASSERT_IS_HANDLER checks
whether a structure, such as grub_term_input_t, can be safely cast as
grub_handler_t. The macro runs at compiled time, if no problem is
found, it wouldn't generate any extra code.

-- 
Bean

Attachment: handler.diff
Description: Text document


reply via email to

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