grub-devel
[Top][All Lists]
Advanced

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

Re: Idea: elimination of the normal mode (revised version)


From: Bean
Subject: Re: Idea: elimination of the normal mode (revised version)
Date: Fri, 18 Jul 2008 23:14:38 +0800

On Fri, Jul 18, 2008 at 10:46 PM, Colin D Bennett <address@hidden> wrote:
> On Thu, 17 Jul 2008 11:24:23 +0800
> Bean <address@hidden> wrote:
>
>> On Mon, Jul 7, 2008 at 8:29 AM, Bean <address@hidden> wrote:
>> > Hi,
>> >
>> > First of all, we can still keep rescue and normal command. But
>> > instead of depending on normal.mod, normal command depends on
>> > module arg, which is an option parser. Also, these two type of
>> > commands are of the same command set. In fact, module arg is
>> > implemented as a pre parser, which goes through the list of
>> > arguments and extract the options. In the case of rescue command,
>> > the pre parser field is null, which means it wants to parse options
>> > itself.
>> >
>> > Then, I think of a new structure to represent all configurable
>> > handlers of grub. Different types of handler have different fields,
>> > but they all share a command header:
>> >
>> > struct grub_handler
>> > {
>> >  .next,
>> >  .name,
>> >  .init,
>> >  .fini
>> > };
>> >
>> > Same type of handlers are linked together. We first define an enum
>> > to list all types. For example:
>> >
>> > enum {
>> >  GRUB_HANDLER_INPUT,
>> >  GRUB_HANDLER_OUTPUT,
>> >  GRUB_HANDLER_CONSOLE,
>> >  GRUB_HANDLER_MENU,
>> >  GRUB_HANDLER_SCRIPT,
>> >  GRUB_HANDLER_NUM
>> > };
>> >
>> > Then, we define an array to point to the head of handler linked
>> > list: grub_handler[GRUB_HANDLER_NUM];
>> >
>> > Head is the default selection. When we insert a new handler module,
>> > it would automatically become the new default, although we can
>> > switch back to old handler using a command.
>> >
>> > Here are more details about different handlers:
>> >
>> > input:
>> > This is the input component of terminal:
>> >
>> > struct grub_handler_input
>> > {
>> >  .next,
>> >  .name,
>> >  .init,
>> >  .fini,
>> >  .checkkey,
>> >  .getkey
>> >  .flags,
>> > };
>> >
>> > output:
>> > This is the output component of terminal:
>> >
>> > struct grub_handler_output
>> > {
>> >  .next,
>> >  .name,
>> >  .init,
>> >  .fini,
>> >  .putchar,
>> >  .getcharwidth,
>> >  .getxy,
>> >  .gotoxy,
>> >  .cls,
>> >  .setcolorstate,
>> >  .setcursor,
>> >  .flags,
>> > };
>> >
>> > console interface:
>> > It represent the grub console, users type commands and execute them
>> > line by line.
>> >
>> > struct grub_handler_console
>> > {
>> >  .next,
>> >  .name,
>> >  .init,
>> >  .fini,
>> >  .run
>> > };
>> >
>> > menu interface:
>> > It represent the menu, users select a menu item and execute it.
>> >
>> > struct grub_handler_menu
>> > {
>> >  .next,
>> >  .name,
>> >  .init,
>> >  .fini,
>> >  .run
>> > };
>> >
>> > script engine:
>> > It's responsible for parsing config file to get the menu list, and
>> > execution of commands.
>> >
>> > struct grub_handler_script
>> > {
>> >  .next,
>> >  .name,
>> >  .init,
>> >  .fini,
>> >  .readconfig
>> >  .getmenu
>> >  .execute
>> > };
>> >
>> > The handlers are independent of each other. When they need
>> > something, they called specific function of the default handler.
>> > For example, to read a key from the console, we can use
>> > grub_handler[GRUB_HANDLER_INPUT]->getkey. Also, to get the list of
>> > items to be displayed on screen, the menu handler can call
>> > grub_handler[GRUB_HANDLER_SCRIPT]->getmenu.
>>
>> Any comment for this idea ?
>
> I like the idea, especially the idea of separating the script engine
> and menu loading code from the character-terminal-based menu system.
>
> I wonder whether it would be better just to have separate variables for
> the different handler types like
>
> struct grub_handler_input grub_handler_input;
> struct grub_handler_output grub_handler_output;
> struct grub_handler_console grub_handler_console;
>
> instead of an array indexed by a constant representing the type, for
> the following reasons:
>
> 1. You would have to use casting to be able to call the functions in
> the handler other than the common 4 (next, name, init, fini).  For
> instance, you couldn't do
>  grub_handler[GRUB_HANDLER_INPUT]->getkey()
> since the type of grub_handler is struct grub_handler[].
>
> 2. If we did use casting for each call to a handler, it is more error
> prone since we would not get compiler type checking and could
> accidentally write GRUB_HANDLER_INPUT when we meant GRUB_HANDLER_OUTPUT
> with obvious consequences.
>
> 3. It is more code to write to do
>  grub_handler[GRUB_HANDLER_INPUT]->getkey()
> instead of
>  grub_handler_input->getkey()
>
>
> Now, suppose we did define grub_handler_input, grub_handler_output,
> etc.  Then if there were a reason to iterate over all types of
> handlers, or treat handlers generically for some other reason, we could
> certainly also create and array of pointers to the handlers for that
> purpose:
>
> extern struct grub_handler *grub_handlers[GRUB_HANDLER_NUM];
> extern const char *grub_handler_types[GRUB_HANDLER_NUM];
>
> void print_current_handlers (void)
> {
>  int i;
>  for (i = 0; i < GRUB_HANDLER_NUM; i++)
>    grub_printf ("handler for %s: %s\n",
>                  grub_handler_types[i],
>                  grub_handlers[i]);
> }
>
> We would then have to make sure the list of all handlers was kept in
> sync with the separate variables.  This would mean a little more code
> for each handler type (a global "set current handler" function for
> each) but we would probably rarely add a new handler type so it would
> not be a great burden.  I don't see a need for this iteration over all
> handlers, anyway.

Hi,

I like the idea. In fact, I hate using cast, it makes the code ugly.

Also, we can use generic code to handle them, define a structure like this:

{
 { "input", &grub_handler_input_head},
 { "output", &grub_handler_output_head},
 {0, 0}
};

As the first few fields of handler is the same, we can use casting to
access them.

-- 
Bean




reply via email to

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