All of lore.kernel.org
 help / color / mirror / Atom feed
* [DISCUSSION] Scripts and menus
@ 2005-08-14  9:18 Vladimir Serbinenko
  2005-08-14 13:29 ` Douglas Wade Needham
  2005-08-14 14:35 ` [DISCUSSION] Scripts and menus Yoshinori K. Okuji
  0 siblings, 2 replies; 19+ messages in thread
From: Vladimir Serbinenko @ 2005-08-14  9:18 UTC (permalink / raw)
  To: The development of GRUB 2

IMHO. Current system with title command is ugly because:
    -grub.cfg requires the separate parser. IMHO it should be
parsed the same way as user input.
    -Even when scripting support will be ready it's impossible
to create multiple menus of the same kind by just a loop
(like
    for x in /boot/vmlinuz-*;
       do
          menuitem name="linux-$x" title="Linux with kernel $x"
             linux $x [....]
          endmenuitem;
       done;
)
    - if in future menu entrys will have more parameters
    (e.g: name, keyboard shortcut) how could we specify them?

As arisen in discussion about serial console multiple menus could be
useful. I propose to split munu.c in general (e.g: run_entry) and
menu-specific (like run_menu) and then make multiple menu support like
done with terminals. Then we could add other menus: like lilo menu
(additional parameters could be stored in variable: then boot function
could also look at this variable for parameters (of course parameters from
unauthorized users will be ignored)), vesa menu
(and 3rd party programmers could write vesa menus then it would be like
skin support), x-menu over ssh/network, ...

IMHO grub2 needs scripting support to be more powerful I propose to
use bison translating commands in the structures like:
struct command
{
    enum type {SCRIPT_CMD_NORMAL, SCRIPT_CMD_IF, [...]}; /* type of
command*/
    enum link {SCRIPT_LINK_NORMAL, SCRIPT_LINK_AND, [...]}; /* Was there
a &&, ||, ... before command?*/
    union
    {
       char *command;
       struct command *if_jump; /* Bison could translate the condition
as preceding command*/
       [...]
    }  
};

then menu-entrys could be
menuentry name=<name> title=<title> [key-shortcut=<..>] [picture=<...>]
    <....>
endmenuentry

I'm ready to make the work of menu-splitting, lilo-menu and scripting

What do you think about it?

                                                                        
                  Vladimir



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14  9:18 [DISCUSSION] Scripts and menus Vladimir Serbinenko
@ 2005-08-14 13:29 ` Douglas Wade Needham
  2005-08-14 13:53   ` Vladimir Serbinenko
  2005-08-14 15:12   ` Yoshinori K. Okuji
  2005-08-14 14:35 ` [DISCUSSION] Scripts and menus Yoshinori K. Okuji
  1 sibling, 2 replies; 19+ messages in thread
From: Douglas Wade Needham @ 2005-08-14 13:29 UTC (permalink / raw)
  To: The development of GRUB 2

The problem with your idea is that it at least appears to be too
Linux-centric, and forgets entirely about other operating systems,
invalidating the "unified" part of the GRUB name.  And I get fed up
when on my machine which as FC3 has one of the OSes (along with NetBSD
and several others), up2date ignores the fact that FC3 **is not** the
default.

BTW...If 1.9 is supposed to be indicating that we are nearing a 2.0
release, I don't think that now would be the time for such a major
change.  After nearly 30 years of programming, one of the problems I
have seen in too many Open Source projects is that a release cycle is
supposedly started, but...

    1) No release branch is started in the source repository.

or

    2) Major, non-critical changes are committed to the release
       branch, which in turn delay the release or make it unstable.

In short...if you have the features in which you have decided upon for
a release, branch, start testing, and the only thing which goes on the
branch are fixes for problems or pullups related to security.  All
other work stays on the mainline branch for the next major release.

Just my opinion...

- Doug

Quoting Vladimir Serbinenko (phcoder@gmail.com):
> IMHO. Current system with title command is ugly because:
>     -grub.cfg requires the separate parser. IMHO it should be
> parsed the same way as user input.
>     -Even when scripting support will be ready it's impossible
> to create multiple menus of the same kind by just a loop
> (like
>     for x in /boot/vmlinuz-*;
>        do
>           menuitem name="linux-$x" title="Linux with kernel $x"
>              linux $x [....]
>           endmenuitem;
>        done;
> )
>     - if in future menu entrys will have more parameters
>     (e.g: name, keyboard shortcut) how could we specify them?
> 
> As arisen in discussion about serial console multiple menus could be
> useful. I propose to split munu.c in general (e.g: run_entry) and
> menu-specific (like run_menu) and then make multiple menu support like
> done with terminals. Then we could add other menus: like lilo menu
> (additional parameters could be stored in variable: then boot function
> could also look at this variable for parameters (of course parameters from
> unauthorized users will be ignored)), vesa menu
> (and 3rd party programmers could write vesa menus then it would be like
> skin support), x-menu over ssh/network, ...
> 
> IMHO grub2 needs scripting support to be more powerful I propose to
> use bison translating commands in the structures like:
> struct command
> {
>     enum type {SCRIPT_CMD_NORMAL, SCRIPT_CMD_IF, [...]}; /* type of
> command*/
>     enum link {SCRIPT_LINK_NORMAL, SCRIPT_LINK_AND, [...]}; /* Was there
> a &&, ||, ... before command?*/
>     union
>     {
>        char *command;
>        struct command *if_jump; /* Bison could translate the condition
> as preceding command*/
>        [...]
>     }  
> };
> 
> then menu-entrys could be
> menuentry name=<name> title=<title> [key-shortcut=<..>] [picture=<...>]
>     <....>
> endmenuentry
> 
> I'm ready to make the work of menu-splitting, lilo-menu and scripting
> 
> What do you think about it?
> 
>                                                                         
>                   Vladimir
> 
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel

-- 
Douglas Wade Needham - KA8ZRT        UN*X Consultant & UW/BSD kernel programmer
Email:  cinnion @ ka8zrt . com       http://cinnion.ka8zrt.com
Disclaimer: My opinions are my own.  Since I don't want them, why
            should my employer, or anybody else for that matter! 



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14 13:29 ` Douglas Wade Needham
@ 2005-08-14 13:53   ` Vladimir Serbinenko
  2005-08-14 15:12   ` Yoshinori K. Okuji
  1 sibling, 0 replies; 19+ messages in thread
From: Vladimir Serbinenko @ 2005-08-14 13:53 UTC (permalink / raw)
  To: The development of GRUB 2

Douglas Wade Needham wrote:

>The problem with your idea is that it at least appears to be too
>Linux-centric, and forgets entirely about other operating systems,
>invalidating the "unified" part of the GRUB name.  And I get fed up
>when on my machine which as FC3 has one of the OSes (along with NetBSD
>and several others), up2date ignores the fact that FC3 **is not** the
>default.
>  
>
Why linux centric? Scripting is an universal thing. If you speak
about

for x in /boot/vmlinuz-*; [...]
it was just an example.

"Menu modules" are also general thing. Lilo-like menu was also an example
but it could also be used with other OS that linux (other loaders can
also check for additional commands).
About menu-entry syntax - I see nothing linux-centric

Or don't I understand something?

                                                                        
      Vladimir



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14  9:18 [DISCUSSION] Scripts and menus Vladimir Serbinenko
  2005-08-14 13:29 ` Douglas Wade Needham
@ 2005-08-14 14:35 ` Yoshinori K. Okuji
  2005-08-14 16:03   ` Vladimir Serbinenko
  1 sibling, 1 reply; 19+ messages in thread
From: Yoshinori K. Okuji @ 2005-08-14 14:35 UTC (permalink / raw)
  To: The development of GRUB 2

On Sunday 14 August 2005 11:18, Vladimir Serbinenko wrote:
> IMHO. Current system with title command is ugly because:

I have already proposed my idea of making each entry a function before. First, 
please describe why you don't think this is not enough.

Okuji



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14 13:29 ` Douglas Wade Needham
  2005-08-14 13:53   ` Vladimir Serbinenko
@ 2005-08-14 15:12   ` Yoshinori K. Okuji
  2005-08-14 22:54     ` Douglas Wade Needham
  1 sibling, 1 reply; 19+ messages in thread
From: Yoshinori K. Okuji @ 2005-08-14 15:12 UTC (permalink / raw)
  To: The development of GRUB 2

On Sunday 14 August 2005 15:29, Douglas Wade Needham wrote:
> BTW...If 1.9 is supposed to be indicating that we are nearing a 2.0
> release, I don't think that now would be the time for such a major
> change.  After nearly 30 years of programming, one of the problems I
> have seen in too many Open Source projects is that a release cycle is
> supposedly started, but...

Do not care about the version number. For now, GRUB 2 is at an alpha stage. 
Rather, you must not stop thinking how to improve GRUB 2. So I appreciate 
that Vladimir is thinking various possibilities.

Possibly, we will have to begin stabilizing GRUB 2 in near future, maybe in 6 
months. Once we decide this, we should not make any (user-visible) 
incompatible change, because the requirement for a boot loader is more severe 
than other software. So, reversely, we should consider what we can change as 
much as possible at this moment. If we miss this occasion, the next chance is 
GRUB 3.

Okuji



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14 14:35 ` [DISCUSSION] Scripts and menus Yoshinori K. Okuji
@ 2005-08-14 16:03   ` Vladimir Serbinenko
  2005-08-14 18:01     ` Yoshinori K. Okuji
  0 siblings, 1 reply; 19+ messages in thread
From: Vladimir Serbinenko @ 2005-08-14 16:03 UTC (permalink / raw)
  To: The development of GRUB 2

Yoshinori K. Okuji wrote:

>I have already proposed my idea of making each entry a function before. First, 
>please describe why you don't think this is not enough.
>
>  
>
It's only a question of syntax so it's ok but IMHO 2 points are important:
    1) It must be possible to set additional attributes to a menu entry
    2) It must be possible to create functions that are *not* the menu
entries
                                                                        
            Vladimir





^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14 16:03   ` Vladimir Serbinenko
@ 2005-08-14 18:01     ` Yoshinori K. Okuji
  2005-08-14 18:30       ` Vladimir Serbinenko
  0 siblings, 1 reply; 19+ messages in thread
From: Yoshinori K. Okuji @ 2005-08-14 18:01 UTC (permalink / raw)
  To: The development of GRUB 2

On Sunday 14 August 2005 18:03, Vladimir Serbinenko wrote:
> It's only a question of syntax so it's ok but IMHO 2 points are important:
>     1) It must be possible to set additional attributes to a menu entry

I'd like to use options for these. Like this:

entry --label="gnu" --key="g" "GNU 0.3" {
  root=(hd0,0)
  multiboot /gnumach
  module /serverboot
}

>     2) It must be possible to create functions that are *not* the menu
> entries

They should be the same as Bash:

function load_modules {
  module /boot/module1
  module /boot/module2
}

entry "My OS version 1" {
  multiboot /boot/kernel-1
  load_modules
}

entry "My OS version 2" {
  multiboot /boot/kernel-2
  load_modules
}

Okuji



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14 18:01     ` Yoshinori K. Okuji
@ 2005-08-14 18:30       ` Vladimir Serbinenko
  2005-08-15 17:37         ` Marco Gerards
  0 siblings, 1 reply; 19+ messages in thread
From: Vladimir Serbinenko @ 2005-08-14 18:30 UTC (permalink / raw)
  To: The development of GRUB 2

Ok. At this moment I have one thing to do that will be approximately
finished
on Thursday and then I'll do it (on next Monday I suppose my assignment
will be finished)

Is it ok to create bison parser that will parse command by command and
create a pseudocode at output that can be easily executed?

Yoshinori K. Okuji wrote:

>On Sunday 14 August 2005 18:03, Vladimir Serbinenko wrote:
>  
>
>>It's only a question of syntax so it's ok but IMHO 2 points are important:
>>    1) It must be possible to set additional attributes to a menu entry
>>    
>>
>
>I'd like to use options for these. Like this:
>
>entry --label="gnu" --key="g" "GNU 0.3" {
>  root=(hd0,0)
>  multiboot /gnumach
>  module /serverboot
>}
>
>  
>
>>    2) It must be possible to create functions that are *not* the menu
>>entries
>>    
>>
>
>They should be the same as Bash:
>
>function load_modules {
>  module /boot/module1
>  module /boot/module2
>}
>
>entry "My OS version 1" {
>  multiboot /boot/kernel-1
>  load_modules
>}
>
>entry "My OS version 2" {
>  multiboot /boot/kernel-2
>  load_modules
>}
>
>Okuji
>
>
>_______________________________________________
>Grub-devel mailing list
>Grub-devel@gnu.org
>http://lists.gnu.org/mailman/listinfo/grub-devel
>
>  
>




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14 15:12   ` Yoshinori K. Okuji
@ 2005-08-14 22:54     ` Douglas Wade Needham
  2005-08-14 23:09       ` Yoshinori K. Okuji
  2005-08-15  7:27       ` [DISCUSSION] Grub2 Improvements marm.mm
  0 siblings, 2 replies; 19+ messages in thread
From: Douglas Wade Needham @ 2005-08-14 22:54 UTC (permalink / raw)
  To: The development of GRUB 2

Quoting Yoshinori K. Okuji (okuji@enbug.org):
> On Sunday 14 August 2005 15:29, Douglas Wade Needham wrote:
> > BTW...If 1.9 is supposed to be indicating that we are nearing a 2.0
> > release, I don't think that now would be the time for such a major
> > change.  After nearly 30 years of programming, one of the problems I
> > have seen in too many Open Source projects is that a release cycle is
> > supposedly started, but...
> 
> Do not care about the version number. For now, GRUB 2 is at an alpha stage. 
> Rather, you must not stop thinking how to improve GRUB 2. So I appreciate 
> that Vladimir is thinking various possibilities.
>
> Possibly, we will have to begin stabilizing GRUB 2 in near future, maybe in 6 
> months. Once we decide this, we should not make any (user-visible) 
> incompatible change, because the requirement for a boot loader is more severe 
> than other software. So, reversely, we should consider what we can change as 
> much as possible at this moment. If we miss this occasion, the next chance is 
> GRUB 3.

I agree that we should not continue to think about improvements, etc.  
However, if we are talking alpha/beta/rc stages, then we should be
talking about a release branch, into which we only put controlled
changes.  Otherwise, we will not get the stability during testing, and
the end result will likely be far from what we want, either in time or
in quality.

- Doug



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14 22:54     ` Douglas Wade Needham
@ 2005-08-14 23:09       ` Yoshinori K. Okuji
  2005-08-15  7:27       ` [DISCUSSION] Grub2 Improvements marm.mm
  1 sibling, 0 replies; 19+ messages in thread
From: Yoshinori K. Okuji @ 2005-08-14 23:09 UTC (permalink / raw)
  To: The development of GRUB 2

On Monday 15 August 2005 00:54, Douglas Wade Needham wrote:
> I agree that we should not continue to think about improvements, etc.
> However, if we are talking alpha/beta/rc stages, then we should be
> talking about a release branch, into which we only put controlled
> changes.  Otherwise, we will not get the stability during testing, and
> the end result will likely be far from what we want, either in time or
> in quality.

Don't worry. We do not need to make a stable version for a while. Now is too 
early to talk about branching in GRUB 2.

Okuji



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [DISCUSSION] Grub2 Improvements
  2005-08-14 22:54     ` Douglas Wade Needham
  2005-08-14 23:09       ` Yoshinori K. Okuji
@ 2005-08-15  7:27       ` marm.mm
  2005-08-15  8:37         ` Yoshinori K. Okuji
  1 sibling, 1 reply; 19+ messages in thread
From: marm.mm @ 2005-08-15  7:27 UTC (permalink / raw)
  To: The development of GRUB 2





-----Original Message-----
> Date: Mon, 15 Aug 2005 00:54:11 +0200
> Subject: Re: [DISCUSSION] Scripts and menus
> From: Douglas Wade Needham <site.grub@ka8zrt.com>
> To: The development of GRUB 2 <grub-devel@gnu.org>

> Quoting Yoshinori K. Okuji (okuji@enbug.org):
> > On Sunday 14 August 2005 15:29, Douglas Wade Needham wrote:
> > > BTW...If 1.9 is supposed to be indicating that we are nearing a
> > > 2.0 release, I don't think that now would be the time for such a
> > > major change.  After nearly 30 years of programming, one of the
> > > problems I have seen in too many Open Source projects is that a
> > > release cycle is supposedly started, but...
> > > 
> > 
> > Do not care about the version number. For now, GRUB 2 is at an alpha
> > stage.
> > Rather, you must not stop thinking how to improve GRUB 2. So I
> > appreciate that Vladimir is thinking various possibilities.
> > 
> > Possibly, we will have to begin stabilizing GRUB 2 in near future,
> > maybe in 6 months. Once we decide this, we should not make any
> > (user-visible) incompatible change, because the requirement for a
> > boot loader is more severe than other software. So, reversely, we
> > should consider what we can change as much as possible at this
> > moment. If we miss this occasion, the next chance is GRUB 3.
> > 
> 
> I agree that we should not continue to think about improvements, etc.
> However, if we are talking alpha/beta/rc stages, then we should be
> talking about a release branch, into which we only put controlled
> changes.  Otherwise, we will not get the stability during testing, and
> the end result will likely be far from what we want, either in time or
> in quality.

I would agree with this. We should have a stable basis on which we can
improve grub2. There are so many improvments, e.g. vesafb module and
many others, and later a graphical menu, but we dont have a structure
for a menu entry (or a stable). Other modules/improvement uses this
basis and when this basis changes, parts of grub2/modules must be
rewritten to fit to the basis. We should create a list of improvments
(all the improvments which occurs in the list) and set priorities. We
should cralify which improvements apear in the next release and which
not, ...
BTW I have successfully compiled grub2 on FreeBSD 5.3-RELEASE, but
havent tested it completely.
> 
> - Doug
> 
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel






^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Grub2 Improvements
  2005-08-15  7:27       ` [DISCUSSION] Grub2 Improvements marm.mm
@ 2005-08-15  8:37         ` Yoshinori K. Okuji
  0 siblings, 0 replies; 19+ messages in thread
From: Yoshinori K. Okuji @ 2005-08-15  8:37 UTC (permalink / raw)
  To: The development of GRUB 2

On Monday 15 August 2005 09:27, marm.mm@t-online.de wrote:
> I would agree with this. We should have a stable basis on which we can
> improve grub2. There are so many improvments, e.g. vesafb module and
> many others, and later a graphical menu, but we dont have a structure
> for a menu entry (or a stable). Other modules/improvement uses this
> basis and when this basis changes, parts of grub2/modules must be
> rewritten to fit to the basis. We should create a list of improvments
> (all the improvments which occurs in the list) and set priorities. We
> should cralify which improvements apear in the next release and which
> not, ...

Do not use "we should", when "we" do not include yourself.

I do not like your idea. I have already said that we do not need branching at 
the moment. If you need stability, use GRUB Legacy. That's it.

Okuji



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [DISCUSSION] Scripts and menus
  2005-08-14 18:30       ` Vladimir Serbinenko
@ 2005-08-15 17:37         ` Marco Gerards
  2005-08-24  9:36           ` [Patch] Scripting engine Vladimir Serbinenko
  0 siblings, 1 reply; 19+ messages in thread
From: Marco Gerards @ 2005-08-15 17:37 UTC (permalink / raw)
  To: The development of GRUB 2

Vladimir Serbinenko <phcoder@gmail.com> writes:

Hi Vladimir,

> Ok. At this moment I have one thing to do that will be approximately
> finished
> on Thursday and then I'll do it (on next Monday I suppose my assignment
> will be finished)
>
> Is it ok to create bison parser that will parse command by command and
> create a pseudocode at output that can be easily executed?

It would be nice if you could post your flex/bison code first.  In
that case we can discuss the syntax and how to fill in the
implementation before continuing.  I think being able to verify the
input before getting output is a big enough task to start with.

Thanks,
Marco




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [Patch] Scripting engine
  2005-08-15 17:37         ` Marco Gerards
@ 2005-08-24  9:36           ` Vladimir Serbinenko
  2005-08-28 12:55             ` Yoshinori K. Okuji
  2005-08-31 19:22             ` Marco Gerards
  0 siblings, 2 replies; 19+ messages in thread
From: Vladimir Serbinenko @ 2005-08-24  9:36 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 648 bytes --]

I wrote the preciew version of scripting engine. I'll add some comments
soonly.
Parser parses everytime one command because the commands could be
entered from
commandline. Bison converts in kind of pseudocode. Arithmethic support
will be done
by separate parser because arithmetic parse is very different form bash one.
Patch is attached. The next thing I'll do is adding entry handling and
changing menu
parser to the call of scripting engine. It would be good if then it
could be incorporated
to CVS because it would be easy to developpe and debug.

                                                                        
            Vladimir



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: script.diff --]
[-- Type: text/x-patch; name="script.diff", Size: 49389 bytes --]

diff -urN ./grub2_3/conf/i386-pc.mk ./grub2_4/conf/i386-pc.mk
--- ./grub2_3/conf/i386-pc.mk	2005-08-24 11:25:39.000000000 +0200
+++ ./grub2_4/conf/i386-pc.mk	2005-08-24 11:23:42.000000000 +0200
@@ -686,11 +686,11 @@
 	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_hexcat.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_timeout.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.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_ufs.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_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_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.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_hexcat.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_timeout.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_i386_pc_reboot.d grub_emu-disk_loopback.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_ufs.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_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_context.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.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
+	util/i386/pc/misc.c normal/parser.c
+CLEANFILES += grub-emu grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_hexcat.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_timeout.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.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_ufs.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_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_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.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-normal_parser.o
+MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_hexcat.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_timeout.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_i386_pc_reboot.d grub_emu-disk_loopback.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_ufs.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_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_context.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.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-normal_parser.d
 
-grub-emu: grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_hexcat.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_timeout.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.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_ufs.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_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_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.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_hexcat.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_timeout.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_i386_pc_reboot.o grub_emu-disk_loopback.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_ufs.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_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_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.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-normal_parser.o
 	$(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(grub_emu_LDFLAGS)
 
 grub_emu-commands_boot.o: commands/boot.c
@@ -1101,6 +1101,14 @@
 
 -include grub_emu-util_i386_pc_misc.d
 
+grub_emu-normal_parser.o: normal/parser.c
+	$(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-normal_parser.d: normal/parser.c
+	set -e; 	  $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $< 	  | sed 's,parser\.o[ :]*,grub_emu-normal_parser.o $@ : ,g' > $@; 	  [ -s $@ ] || rm -f $@
+
+-include grub_emu-normal_parser.d
+
 
 grub_emu_LDFLAGS = $(LIBCURSES)
 
@@ -1699,9 +1707,9 @@
 # For normal.mod.
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c	\
 	normal/context.c normal/main.c normal/menu.c 			\
-	normal/menu_entry.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_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.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_context.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_entry.d normal_mod-normal_i386_setjmp.d
+	normal/menu_entry.c normal/i386/setjmp.S normal/parser.c
+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_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_i386_setjmp.o normal_mod-normal_parser.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_context.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_entry.d normal_mod-normal_i386_setjmp.d normal_mod-normal_parser.d
 DEFSYMFILES += def-normal.lst
 UNDSYMFILES += und-normal.lst
 
@@ -1710,7 +1718,7 @@
 	$(LD) -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_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.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_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_i386_setjmp.o normal_mod-normal_parser.o
 	-rm -f $@
 	$(LD) -r -d -o $@ $^
 
@@ -1879,6 +1887,25 @@
 	set -e; 	  $(CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(CPPFLAGS) $(ASFLAGS) $(normal_mod_ASFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
 
 
+normal_mod-normal_parser.o: normal/parser.c
+	$(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+normal_mod-normal_parser.d: normal/parser.c
+	set -e; 	  $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $< 	  | sed 's,parser\.o[ :]*,normal_mod-normal_parser.o $@ : ,g' > $@; 	  [ -s $@ ] || rm -f $@
+
+-include normal_mod-normal_parser.d
+
+CLEANFILES += cmd-parser.lst fs-parser.lst
+COMMANDFILES += cmd-parser.lst
+FSFILES += fs-parser.lst
+
+cmd-parser.lst: normal/parser.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-parser.lst: normal/parser.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_CFLAGS = $(COMMON_CFLAGS)
 normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
 
diff -urN ./grub2_3/conf/i386-pc.rmk ./grub2_4/conf/i386-pc.rmk
--- ./grub2_3/conf/i386-pc.rmk	2005-08-08 15:08:59.000000000 +0200
+++ ./grub2_4/conf/i386-pc.rmk	2005-08-20 16:37:09.000000000 +0200
@@ -90,7 +90,7 @@
 	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
+	util/i386/pc/misc.c normal/parser.c
 
 grub_emu_LDFLAGS = $(LIBCURSES)
 
@@ -163,7 +163,7 @@
 # For normal.mod.
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c	\
 	normal/context.c normal/main.c normal/menu.c 			\
-	normal/menu_entry.c normal/i386/setjmp.S
+	normal/menu_entry.c normal/i386/setjmp.S normal/parser.c
 normal_mod_CFLAGS = $(COMMON_CFLAGS)
 normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
 
diff -urN ./grub2_3/conf/powerpc-ieee1275.mk ./grub2_4/conf/powerpc-ieee1275.mk
--- ./grub2_3/conf/powerpc-ieee1275.mk	2005-08-24 11:25:39.000000000 +0200
+++ ./grub2_4/conf/powerpc-ieee1275.mk	2005-08-24 11:23:42.000000000 +0200
@@ -78,11 +78,11 @@
 	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/powerpc/ieee1275/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_timeout.o grub_emu-commands_ieee1275_halt.o grub_emu-commands_ieee1275_reboot.o grub_emu-disk_loopback.o grub_emu-commands_hexcat.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_ufs.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_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_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.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_powerpc_ieee1275_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_timeout.d grub_emu-commands_ieee1275_halt.d grub_emu-commands_ieee1275_reboot.d grub_emu-disk_loopback.d grub_emu-commands_hexcat.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_ufs.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_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_context.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.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_powerpc_ieee1275_misc.d
+	util/powerpc/ieee1275/misc.c normal/parser.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_timeout.o grub_emu-commands_ieee1275_halt.o grub_emu-commands_ieee1275_reboot.o grub_emu-disk_loopback.o grub_emu-commands_hexcat.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_ufs.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_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_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.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_powerpc_ieee1275_misc.o grub_emu-normal_parser.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_timeout.d grub_emu-commands_ieee1275_halt.d grub_emu-commands_ieee1275_reboot.d grub_emu-disk_loopback.d grub_emu-commands_hexcat.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_ufs.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_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_context.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.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_powerpc_ieee1275_misc.d grub_emu-normal_parser.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_timeout.o grub_emu-commands_ieee1275_halt.o grub_emu-commands_ieee1275_reboot.o grub_emu-disk_loopback.o grub_emu-commands_hexcat.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_ufs.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_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_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.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_powerpc_ieee1275_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_timeout.o grub_emu-commands_ieee1275_halt.o grub_emu-commands_ieee1275_reboot.o grub_emu-disk_loopback.o grub_emu-commands_hexcat.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_ufs.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_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_context.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.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_powerpc_ieee1275_misc.o grub_emu-normal_parser.o
 	$(BUILD_CC) -o $@ $^ $(BUILD_LDFLAGS) $(grub_emu_LDFLAGS)
 
 grub_emu-commands_boot.o: commands/boot.c
@@ -493,6 +493,14 @@
 
 -include grub_emu-util_powerpc_ieee1275_misc.d
 
+grub_emu-normal_parser.o: normal/parser.c
+	$(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -c -o $@ $<
+
+grub_emu-normal_parser.d: normal/parser.c
+	set -e; 	  $(BUILD_CC) -Inormal -I$(srcdir)/normal $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -M $< 	  | sed 's,parser\.o[ :]*,grub_emu-normal_parser.o $@ : ,g' > $@; 	  [ -s $@ ] || rm -f $@
+
+-include grub_emu-normal_parser.d
+
 
 grub_emu_LDFLAGS = $(LIBCURSES)
 
@@ -1189,9 +1197,9 @@
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c	\
 	normal/context.c normal/main.c normal/menu.c			\
 	normal/menu_entry.c						\
-	normal/powerpc/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_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_powerpc_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_context.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_entry.d normal_mod-normal_powerpc_setjmp.d
+	normal/powerpc/setjmp.S normal/parser.c
+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_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_powerpc_setjmp.o normal_mod-normal_parser.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_context.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_entry.d normal_mod-normal_powerpc_setjmp.d normal_mod-normal_parser.d
 DEFSYMFILES += def-normal.lst
 UNDSYMFILES += und-normal.lst
 
@@ -1200,7 +1208,7 @@
 	$(LD) -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_context.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_entry.o normal_mod-normal_powerpc_setjmp.o
+pre-normal.o: normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.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_powerpc_setjmp.o normal_mod-normal_parser.o
 	-rm -f $@
 	$(LD) -r -d -o $@ $^
 
@@ -1369,6 +1377,25 @@
 	set -e; 	  $(CC) -Inormal/powerpc -I$(srcdir)/normal/powerpc $(CPPFLAGS) $(ASFLAGS) $(normal_mod_ASFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
 
 
+normal_mod-normal_parser.o: normal/parser.c
+	$(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+normal_mod-normal_parser.d: normal/parser.c
+	set -e; 	  $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) $(normal_mod_CFLAGS) -M $< 	  | sed 's,parser\.o[ :]*,normal_mod-normal_parser.o $@ : ,g' > $@; 	  [ -s $@ ] || rm -f $@
+
+-include normal_mod-normal_parser.d
+
+CLEANFILES += cmd-parser.lst fs-parser.lst
+COMMANDFILES += cmd-parser.lst
+FSFILES += fs-parser.lst
+
+cmd-parser.lst: normal/parser.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-parser.lst: normal/parser.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_CFLAGS = $(COMMON_CFLAGS)
 normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
 
diff -urN ./grub2_3/conf/powerpc-ieee1275.rmk ./grub2_4/conf/powerpc-ieee1275.rmk
--- ./grub2_3/conf/powerpc-ieee1275.rmk	2005-08-08 15:10:12.000000000 +0200
+++ ./grub2_4/conf/powerpc-ieee1275.rmk	2005-08-24 11:23:25.000000000 +0200
@@ -48,7 +48,7 @@
 	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/powerpc/ieee1275/misc.c
+	util/powerpc/ieee1275/misc.c normal/parser.c
 
 grub_emu_LDFLAGS = $(LIBCURSES)
 
@@ -119,7 +119,7 @@
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c	\
 	normal/context.c normal/main.c normal/menu.c			\
 	normal/menu_entry.c						\
-	normal/powerpc/setjmp.S
+	normal/powerpc/setjmp.S normal/parser.c
 normal_mod_CFLAGS = $(COMMON_CFLAGS)
 normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
 
diff -urN ./grub2_3/include/grub/err.h ./grub2_4/include/grub/err.h
--- ./grub2_3/include/grub/err.h	2005-08-08 12:05:38.000000000 +0200
+++ ./grub2_4/include/grub/err.h	2005-08-22 16:11:44.000000000 +0200
@@ -49,7 +49,9 @@
     GRUB_ERR_NO_KERNEL,
     GRUB_ERR_BAD_FONT,
     GRUB_ERR_NOT_IMPLEMENTED_YET,
-    GRUB_ERR_SYMLINK_LOOP
+    GRUB_ERR_SYMLINK_LOOP,
+    GRUB_ERR_PARSE,
+    GRUB_ERR_FALSE
   }
 grub_err_t;
 
diff -urN ./grub2_3/include/grub/script.h ./grub2_4/include/grub/script.h
--- ./grub2_3/include/grub/script.h	1970-01-01 01:00:00.000000000 +0100
+++ ./grub2_4/include/grub/script.h	2005-08-24 11:03:59.000000000 +0200
@@ -0,0 +1,92 @@
+#include <grub/err.h>
+
+#define GRUB_SCRIPT_SPECIALCHARS ";\n \t\r"
+#define WORDCUTS "|&;<> \t()"
+
+#define GRUB_SCRIPT_COMMAND_FLAG_NOT 0x1
+
+enum grub_script_superchar_type
+  {
+    GRUB_SCRIPT_SUPERCHAR_PLAIN, /* Just a normal string*/
+    GRUB_SCRIPT_SUPERCHAR_VARIABLE, /* $var */
+    GRUB_SCRIPT_SUPERCHAR_COMMAND,
+    GRUB_SCRIPT_SUPERCHAR_ARITHMETIC
+  };
+
+/* Character string is represented like connected list 
+   by parts of type grub_script_superchar */
+struct grub_script_superchar
+{
+  enum grub_script_superchar_type type;
+  union
+  {
+    char *plain;
+    char *var_name;
+    char *cmd;
+    char *expr;
+  };
+  struct grub_script_superchar *next;
+};
+
+/* Argument list*/
+struct grub_script_superchars
+{
+  struct grub_script_superchar str;
+  struct grub_script_superchars *next;
+};
+
+enum grub_script_command_type
+  {
+    GRUB_SCRIPT_COMMAND_NORMAL, /* Command without scripting*/
+    GRUB_SCRIPT_COMMAND_FORIN, /* for ... in ... */
+    GRUB_SCRIPT_COMMAND_STACK_LOOKUP /* done, fi, ...*/
+  };
+
+enum grub_script_command_chain
+  {
+    GRUB_SCRIPT_CHAIN_NORMAL, /* Normal*/
+    GRUB_SCRIPT_CHAIN_OR, /* after || */
+    GRUB_SCRIPT_CHAIN_AND /* after &&*/
+  };
+
+struct grub_script_command
+{
+  enum grub_script_command_type type;
+  enum grub_script_command_chain chain;
+  int flags;
+  union
+  {
+    struct grub_script_superchars *normal;
+    struct
+    {
+      struct grub_script_superchars *var;
+      struct grub_script_superchars *vals;
+      struct grub_script_commandlist *lookup;
+    };
+  };
+};
+
+struct grub_script_commandlist
+{
+  struct grub_script_command cmd;
+  struct grub_script_commandlist *next;
+};
+
+enum grub_script_stackitemtype {GRUB_SCRIPT_STACKITEM_FORIN};
+
+struct grub_script_stackitem
+{
+  enum grub_script_stackitemtype type;
+  struct grub_script_commandlist *cmd;
+  union 
+  {
+    struct
+    {
+      char **list, *var;
+      int num, cur;
+    };
+  };
+};
+
+grub_err_t
+grub_script_command_execute (char *cmd, char * (*nextline) (void));
diff -urN ./grub2_3/normal/command.c ./grub2_4/normal/command.c
--- ./grub2_3/normal/command.c	2005-08-08 12:05:42.000000000 +0200
+++ ./grub2_4/normal/command.c	2005-08-22 16:18:33.000000000 +0200
@@ -24,6 +24,7 @@
 #include <grub/term.h>
 #include <grub/env.h>
 #include <grub/dl.h>
+#include <grub/script.h>
 
 static grub_command_t grub_command_list;
 
@@ -181,68 +182,28 @@
 int
 grub_command_execute (char *cmdline)
 {
-  auto grub_err_t cmdline_get (char **s);
-  grub_err_t cmdline_get (char **s)
+  auto char *cmdline_get (void);
+  char *cmdline_get (void)
     {
-      *s = grub_malloc (GRUB_MAX_CMDLINE);
-      *s[0] = '\0';
-      return grub_cmdline_get (">", *s, GRUB_MAX_CMDLINE, 0, 1);
+      char *s;
+      s = grub_malloc (GRUB_MAX_CMDLINE);
+      s[0] = '\0';
+      grub_cmdline_get (">", s, GRUB_MAX_CMDLINE, 0, 1);
+      return s;
     }
 
-  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_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 = 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;
+  grub_err_t ret;
 
   /* Enable the pager if the environment pager is set to 1.  */
   pager = grub_env_get ("pager");
   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))
-    {
-      if (grub_arg_parse (cmd, num, &args[1], state, &arglist, &numargs))
-	ret = (cmd->func) (state, numargs, arglist);
-    }
-  else
-    ret = (cmd->func) (state, num, &args[1]);
-  
-  grub_free (state);
 
+  ret = grub_script_command_execute (grub_strdup (cmdline), cmdline_get);
   if (pager && (! grub_strcmp (pager, "1")))
-    grub_set_more (0);
-  
-  grub_free (args);
+    grub_set_more (0); 
+
   return ret;
 }
 
@@ -375,6 +336,40 @@
   return 0;
 }
 
+static grub_err_t
+echo_command (struct grub_arg_list *state __attribute__ ((unused)),
+	       int argc,
+	      char **args)
+{
+  int i;
+  
+  for (i = 0; i < argc; i++)
+    {
+      grub_printf (args[i]);
+      grub_printf (" ");
+    }
+
+  grub_printf ("\n");
+
+  return 0;
+}
+
+static grub_err_t
+true_command (struct grub_arg_list *state __attribute__ ((unused)),
+	      int argc __attribute__ ((unused)),
+	      char **args __attribute__ ((unused)))
+{
+  return 0;
+}
+
+static grub_err_t
+false_command (struct grub_arg_list *state __attribute__ ((unused)),
+	      int argc __attribute__ ((unused)),
+	      char **args __attribute__ ((unused)))
+{
+  return GRUB_ERR_FALSE;
+}
+
 void
 grub_command_init (void)
 {
@@ -401,4 +396,13 @@
 
   grub_register_command ("lsmod", lsmod_command, GRUB_COMMAND_FLAG_BOTH,
 			 "lsmod", "Show loaded modules.", 0);
+
+  grub_register_command ("echo", echo_command, GRUB_COMMAND_FLAG_BOTH,
+			 "echo TEXT", "Print TEXT.", 0);
+
+  grub_register_command ("true", true_command, GRUB_COMMAND_FLAG_BOTH,
+			 "true", "Return non-error.", 0);
+
+  grub_register_command ("false", false_command, GRUB_COMMAND_FLAG_BOTH,
+			 "false", "Return error.", 0);
 }
diff -urN ./grub2_3/normal/parser.y ./grub2_4/normal/parser.y
--- ./grub2_3/normal/parser.y	1970-01-01 01:00:00.000000000 +0100
+++ ./grub2_4/normal/parser.y	2005-08-24 11:18:21.000000000 +0200
@@ -0,0 +1,717 @@
+%{
+#include <grub/script.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/normal.h>
+
+#define PUTLNBUF 100
+#define malloc grub_malloc
+#define free grub_free
+
+static struct grub_script_commandlist *curexec;
+static int yylex (void);
+static void yyerror (const char *s);
+static int generate_end = 0;
+static int nopnum = 0;
+
+/* NOT DONE: brace expansion, vars like ${.../../..}, $*, ..., command expansion, arithmetic expansion,
+ arithmetic, logic, pipe, redirecting, heredoc, herestring, case esac , 
+ if then elif else fi,
+ for (()), function, entry, until, while, time, arrays, ~, special variables, pathname expansion,
+ aliases, builtin commands, prompting */
+
+
+%}
+
+%union 
+{
+  struct grub_script_commandlist *lst;
+  struct grub_script_superchars *str;
+};
+
+%token ENTER
+%token FOR
+%token SEMICOLON
+%token IN
+%token DO
+%token DONE
+%token NOP
+%token <str> WORD
+%token OR
+%token AND
+%token NOT
+
+%type <lst> commandlist
+%type <lst> command
+%type <lst> pre_command
+%type <lst> execlist
+%type <str> arglist
+
+%error-verbose
+
+%%
+
+out:/* command
+   { 
+     curexec = $1; 
+   }
+   |*/ command  
+   {
+     generate_end = 1;
+     nopnum=0;
+     curexec = $1; 
+   }
+
+commandlist  : command
+             | commandlist command
+             {
+	       if (!$1)
+		 $$ = $2;
+	       else
+		 {
+		   $$ = $1;
+		   if ($2)
+		     {
+		       struct grub_script_commandlist *cur;
+		       cur = $2;
+		       while (cur->next)
+			 cur = cur->next;
+		       cur->next = $2;
+		     }
+		 }
+	     };
+
+arglist : WORD
+        | arglist WORD
+        {
+	  struct grub_script_superchars *cur;
+	  $$ = $1;
+	  cur = $1;
+	  while (cur->next)
+	    cur = cur->next;
+	  cur->next = $2;
+	};
+
+command : cmdend
+        {
+	  $$ = 0;
+        }
+        | NOP NOP NOP NOP 
+        {
+	  $$ = 0;
+        }
+        | execlist cmdend
+        ;
+
+execlist : pre_command
+         | NOT pre_command
+         {
+	   $$ = $2;
+	   $$->cmd.flags |= GRUB_SCRIPT_COMMAND_FLAG_NOT;
+         }
+         | execlist AND pre_command
+         {
+	   struct grub_script_commandlist *cur;
+	   $$ = $1;
+	   cur = $1;
+	   while (cur->next)
+	     cur = cur->next;
+	   cur->next = $3;	   
+	   $3->cmd.chain = GRUB_SCRIPT_CHAIN_AND;
+	 }
+         | execlist OR pre_command
+         {
+	   struct grub_script_commandlist *cur;
+	   $$ = $1;
+	   cur = $1;
+	   while (cur->next)
+	     cur = cur->next;
+	   cur->next = $3;
+	   $3->cmd.chain = GRUB_SCRIPT_CHAIN_OR;
+	 }
+         ;
+
+
+pre_command :
+        arglist /* Normal command */
+        {
+	  $$ = grub_malloc (sizeof (struct grub_script_commandlist));
+	  $$->cmd.type = GRUB_SCRIPT_CHAIN_NORMAL;
+	  $$->cmd.chain = GRUB_SCRIPT_COMMAND_NORMAL;
+	  $$->cmd.normal = $1;
+	  $$->cmd.flags = 0;
+	  $$->next = 0;
+	}
+        | FOR WORD IN arglist cmdend DO commandlist DONE
+        {
+	  $$ = grub_malloc (sizeof (struct grub_script_commandlist));
+	  $$->cmd.type = GRUB_SCRIPT_COMMAND_FORIN;
+	  $$->cmd.var = $2;
+	  $$->cmd.vals = $4;
+	  $$->cmd.flags = 0;
+	  $$->cmd.chain = GRUB_SCRIPT_CHAIN_NORMAL;
+	  $$->next = $7;
+	  struct grub_script_commandlist *cur;
+	  cur = $7;
+	  while (cur->next)
+	    cur = cur->next;	  
+	  cur->next = (struct grub_script_commandlist *) 
+	    grub_malloc (sizeof (struct grub_script_commandlist));
+	  cur->next->next = 0;
+	  cur->next->cmd.type = GRUB_SCRIPT_COMMAND_STACK_LOOKUP;
+	  cur->next->cmd.chain = GRUB_SCRIPT_COMMAND_NORMAL;
+	  cur->next->cmd.flags = 0;
+	  $$->cmd.lookup = cur->next;
+	}
+        ;
+
+
+cmdend: ENTER
+      | SEMICOLON
+      ;
+
+%%
+
+static char *curcmd, *curptr;
+static char * (*nl) (void);
+
+static int
+yylex (void)
+{
+  char *putstr = 0, putln = 0, curch;
+  int putptr = 0;
+  /*Lexic analyzer mode: 0 - normal, 1 - between ", 2 - between ' */
+  int mode = 0;
+  
+  auto void cur_putchar (char ch);
+  void cur_putchar (char ch)
+    {
+      if (!(putptr % PUTLNBUF))
+	{
+	  putln += PUTLNBUF;
+	  putstr = grub_realloc (putstr, putln);
+	}
+      putstr[putptr++] = ch;
+    }
+
+  /* Check if next token is a KEYWORD. Set SEPARATOR to 1 if KEYWORD is a token separator like || */
+  auto int check_for_keyword (char *keyword, int separator);
+  int check_for_keyword (char *keyword, int separator)
+    {
+      unsigned keylen = grub_strlen (keyword);
+      if (!curcmd)
+	curptr = curcmd = nl ();      
+      if (mode == 0 && grub_strlen (curptr) >= keylen 
+	  && !grub_memcmp (curptr, keyword, keylen) 
+	  && (!curptr[keylen] || grub_strchr (WORDCUTS, curptr[keylen]) || separator))
+	{
+	  curptr += keylen;
+	  return 1;
+	}
+
+      return 0;
+    }
+
+  auto void add_wordpart (enum grub_script_superchar_type type);
+  void add_wordpart (enum grub_script_superchar_type type)
+    {
+      struct grub_script_superchar *cur;
+      if (!putstr)
+	return;
+      if (!yylval.str)
+	{
+	  yylval.str = (struct grub_script_superchars *) 
+	    grub_malloc (sizeof (struct grub_script_superchars));
+	  cur = &(yylval.str->str);
+	  yylval.str->next = 0;
+	}
+      else
+	{
+	  cur = &(yylval.str->str);
+	  while (cur->next)
+	    cur = cur->next;  
+	  cur->next = (struct grub_script_superchar *) 
+	    grub_malloc (sizeof (struct grub_script_superchar));
+	  cur = cur->next;	  
+	}
+      cur->type = type;
+      cur->next = 0;
+      switch (type)
+	{
+	case GRUB_SCRIPT_SUPERCHAR_PLAIN:
+	  cur->plain = putstr;
+	  break;
+
+	case GRUB_SCRIPT_SUPERCHAR_VARIABLE:
+	  cur->var_name = putstr;
+	  break;
+
+	case GRUB_SCRIPT_SUPERCHAR_COMMAND:
+	  cur->cmd = putstr;
+	  break;
+
+	case GRUB_SCRIPT_SUPERCHAR_ARITHMETIC:
+	  cur->expr = putstr;
+	  break;
+	}
+      putstr = 0;  
+      putln = 0;
+      putptr = 0;
+    }
+
+  auto void script_ungetchar (void);
+  void script_ungetchar (void)
+    {
+      if (curptr)
+	curptr--;
+      else
+	{
+	  curcmd = grub_malloc (sizeof (char));
+	  curptr = curcmd;
+	  curptr[0] = 0;
+	}
+    }
+
+  auto int script_getchar (void);
+  int script_getchar (void)
+    {
+      if (curptr && !*curptr)
+	{
+	  free (curcmd);
+	  curptr = curcmd = 0;
+	  return '\n';
+	}
+
+      if (!curcmd)
+	curptr = curcmd = nl ();
+      
+      return *(curptr++);
+    }
+
+  if (nopnum)
+    {
+      nopnum--;
+      return NOP;
+    }
+
+  if (generate_end)
+    {
+      generate_end = 0;
+      return 0;
+    }
+
+  while (*curptr && grub_isspace (*curptr))
+    curptr++;
+
+  if (*curptr && *curptr == '#')
+    {
+      free (curcmd);
+      curptr = curcmd = 0;
+      return ENTER;
+    }
+
+  if (check_for_keyword ("for", 0))
+    return FOR;
+
+  if (check_for_keyword ("in", 0))
+    return IN;
+
+  if (check_for_keyword ("do", 0))
+    return DO;
+
+  if (check_for_keyword ("done", 0))
+    return DONE;
+
+  if (check_for_keyword ("!", 0))
+    return NOT;
+
+  if (check_for_keyword ("||", 1))
+    return OR;
+
+  if (check_for_keyword ("&&", 1))
+    return AND;
+
+  if (check_for_keyword (";", 1))
+    return SEMICOLON;
+
+  curch = script_getchar ();
+    
+
+  /* Normal word */
+  /* FIXME: brace expansion*/
+  /* FIXME: filename expansion*/
+  if (!grub_strchr (GRUB_SCRIPT_SPECIALCHARS, curch) || mode)
+    {
+      yylval.str = 0;
+      while (!grub_strchr (GRUB_SCRIPT_SPECIALCHARS, curch) || mode)
+	{
+	  switch (curch)
+	    {
+	    case '\\':
+	      /* Inside ' */
+	      if (mode == 2)
+		{
+		  cur_putchar ('\\');
+		  break;
+		}
+	      curch = script_getchar ();
+	      /* Escaped newline */
+	      if (curch == '\n')
+		{
+		  break;
+		}
+	      cur_putchar (curch);
+	      curch = script_getchar ();
+	      break;
+
+	    case '"':
+	      if (mode == 0)
+		{
+		  mode = 1;
+		  curch = script_getchar ();
+		  break;
+		}
+	      if (mode == 1)
+		{
+		  mode = 0;
+		  curch = script_getchar ();
+		  break;
+		}
+	      cur_putchar (curch);
+	      curch = script_getchar ();
+	      break;
+
+	    case '\'':
+	      if (mode == 0)
+		{
+		  mode = 2;
+		  curch = script_getchar ();
+		  break;
+		}
+	      if (mode == 2)
+		{
+		  mode = 0;
+		  curch = script_getchar ();
+		  break;
+		}
+	      cur_putchar (curch);
+	      curch = script_getchar ();
+	      break;
+
+	    case '$':
+	      if (mode == 2)
+		{
+		  cur_putchar ('$');
+		  break;
+		}
+	      add_wordpart (GRUB_SCRIPT_SUPERCHAR_PLAIN);
+	      switch (curch = script_getchar ())
+		{
+		case '{':
+		  while ((curch = script_getchar ()) != '}')
+		    cur_putchar (curch);
+		  add_wordpart (GRUB_SCRIPT_SUPERCHAR_VARIABLE);
+		  curch = script_getchar ();
+		  break;
+
+		case '(':
+		  if ((curch = script_getchar ()) == '(')
+		    {
+		      int parcnt = 2;
+		      while (parcnt)
+			{
+			  curch = script_getchar ();
+			  if (curch == '\\')
+			    {
+			      cur_putchar (curch);
+			      cur_putchar (script_getchar ());
+			      continue;
+			    }
+			  if (curch == '(')
+			    parcnt++;
+			  if (curch == ')')
+			    parcnt--;
+			    
+			  cur_putchar (curch);
+			}
+		      add_wordpart (GRUB_SCRIPT_SUPERCHAR_ARITHMETIC);
+		      curch = script_getchar ();
+		      break;
+		    }
+		  {
+		    int parcnt = 1;
+		    while (parcnt)
+		      {
+			if (curch == '\\')
+			  {
+			    cur_putchar (curch);
+			    cur_putchar (script_getchar ());
+			    curch = script_getchar ();
+			    continue;
+			  }
+			if (curch == '(')
+			  parcnt++;
+			if (curch == ')')
+			  parcnt--;
+			
+			cur_putchar (curch);
+			curch = script_getchar ();
+		      }
+		    add_wordpart (GRUB_SCRIPT_SUPERCHAR_COMMAND);
+		    curch = script_getchar ();
+		    break;
+		  }
+		default:
+		  {
+		    int made = 0;
+		    while (grub_isalpha (curch) || grub_isdigit (curch))
+		      {
+			cur_putchar (curch);
+			made = 1;
+			curch = script_getchar ();
+		      }
+		    if (made)
+		      add_wordpart (GRUB_SCRIPT_SUPERCHAR_VARIABLE);
+		    else
+		      {
+			cur_putchar ('$');
+			add_wordpart (GRUB_SCRIPT_SUPERCHAR_PLAIN);
+		      }
+		  }
+		  break;
+		}
+	      break;
+	      
+	    case '`':
+	      if (mode == 2)
+		{
+		  cur_putchar ('`');
+		  break;
+		}
+	      add_wordpart (GRUB_SCRIPT_SUPERCHAR_PLAIN);
+	      curch = script_getchar ();
+	      while (curch != '`')
+		{
+		  if (curch == '\\')
+		    {
+		      cur_putchar (curch);
+		      curch = script_getchar ();
+		    }
+		  
+		  cur_putchar (curch);
+		  curch = script_getchar ();
+		}
+	      curch = script_getchar ();
+	      add_wordpart (GRUB_SCRIPT_SUPERCHAR_COMMAND);
+	      break;
+
+	    default:
+	      cur_putchar (curch);
+	      curch = script_getchar ();
+	      break;
+	    }
+	}
+      script_ungetchar ();
+      add_wordpart (GRUB_SCRIPT_SUPERCHAR_PLAIN);
+      return WORD;
+    }
+
+  if (curch == '\n')
+    return ENTER;
+  
+}
+
+static char *
+superchartostring (struct grub_script_superchar *in)
+{
+  char *retstr = 0;
+  int curret = 0, old;
+  struct grub_script_superchar *cur = in;
+  while (cur)
+    {
+      switch (cur->type)
+	{
+	case GRUB_SCRIPT_SUPERCHAR_PLAIN:
+	  old = curret;
+	  curret += grub_strlen (cur->plain);
+	  retstr = grub_realloc (retstr, curret + 1);
+	  grub_memcpy (retstr + old, cur->plain, sizeof (char) * grub_strlen (cur->plain));
+	  break;
+
+	  /* FIXME variables like ${...:...}*/
+	case GRUB_SCRIPT_SUPERCHAR_VARIABLE:
+	  {
+	    char *tmp;
+	    old = curret;
+	    tmp = grub_env_get (cur->var_name);
+	    if (!tmp)
+	      break;
+	    curret += grub_strlen (tmp);
+	    retstr = grub_realloc (retstr, curret + 1);
+	    grub_memcpy (retstr + old, tmp, sizeof (char) * grub_strlen (tmp));
+	    break;
+	  }
+	}
+      cur = cur->next;
+    }
+  retstr[curret] = 0;
+  return retstr;
+}
+
+static void
+supercharstostrings (struct grub_script_superchars *in, int *num, char ***out)
+{
+  struct grub_script_superchars *cur = in;
+  *num = 0;
+  *out = 0;
+  while (cur)
+    {
+      *out = (char **) grub_realloc (*out, (*num + 1) * sizeof (char **));
+      (*out)[*num] = superchartostring (&(cur->str));
+      if (!(*out)[*num])
+	continue;
+      (*num)++;
+      cur = cur->next;
+    }
+}
+
+static void
+yyerror (const char *s)
+{
+  grub_error (GRUB_ERR_PARSE, s);
+}
+
+static grub_err_t
+grub_script_command_execute_real (void)
+{
+  grub_err_t ret = 0;
+  grub_command_t cmd;
+  struct grub_script_stackitem *stack = 0;
+  int stackcnt = 0;
+  nopnum = 0;
+  generate_end = 0;
+
+  auto void exec_forin (void);
+  void exec_forin (void)
+    {
+      if (stack[stackcnt - 1].cur >= stack[stackcnt - 1].num)
+	{
+	  curexec = curexec->cmd.lookup;
+	  stack = (struct grub_script_stackitem *) 
+	    grub_realloc (stack, sizeof (struct grub_script_stackitem) * (--stackcnt));
+	  return;
+	}
+      grub_env_set (stack[stackcnt - 1].var, stack[stackcnt - 1].list[stack[stackcnt - 1].cur++]);
+    }
+
+  yyparse ();
+
+  while (curexec)
+    {
+      if (curexec->cmd.chain == GRUB_SCRIPT_CHAIN_AND && ret)
+	{
+	  curexec = curexec->next;
+	  continue;
+	}
+      if (curexec->cmd.chain == GRUB_SCRIPT_CHAIN_OR && !ret)
+	{
+	  curexec = curexec->next;
+	  continue;
+	}
+      switch (curexec->cmd.type)
+	{
+	case GRUB_SCRIPT_COMMAND_NORMAL:
+	  {
+	    int num;
+	    char **args = 0;
+	    struct grub_arg_list *state;
+	    struct grub_arg_option *parser;
+	    int maxargs = 0;
+	    char **arglist;
+	    int numargs;
+	    supercharstostrings (curexec->cmd.normal, &num, &args);
+	    /* In case of an assignment set the environment accordingly instead
+	       of calling a function.  */
+	    if (num == 1 && grub_strchr (args[0], '='))
+	      {
+		char *val = grub_strchr (args[0], '=');
+		val[0] = 0;
+		grub_env_set (args[0], val + 1);
+		val[0] = '=';
+		ret = 0;
+		break;
+	      }
+	      cmd = grub_command_find (args[0]);
+	      if (! cmd)
+		{
+		  ret = grub_error (GRUB_ERR_UNKNOWN_COMMAND, "Command not found");
+		  break;
+		}
+
+	      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))
+		{
+		  if (grub_arg_parse (cmd, num - 1, &args[1], state, &arglist, &numargs))
+		    ret = (cmd->func) (state, numargs, arglist);
+		}
+	      else
+		ret = (cmd->func) (state, num - 1, &args[1]);
+  
+	      grub_free (state);
+  
+	      grub_free (args);
+	      break;
+	  }
+	  
+	case GRUB_SCRIPT_COMMAND_FORIN:
+	  {
+	    stack = (struct grub_script_stackitem *) 
+	      grub_realloc (stack, sizeof (struct grub_script_stackitem) * (stackcnt + 1));
+	    stack[stackcnt].type = GRUB_SCRIPT_STACKITEM_FORIN;
+	    stack[stackcnt].var = superchartostring (&curexec->cmd.var->str);
+	    stack[stackcnt].list = 0;
+	    supercharstostrings (curexec->cmd.vals, &stack[stackcnt].num, &stack[stackcnt].list);
+	    stack[stackcnt].cmd = curexec;
+	    stack[stackcnt].cur = 0;
+	    stackcnt++;
+	    exec_forin ();
+	    break;
+	  }
+	case GRUB_SCRIPT_COMMAND_STACK_LOOKUP:
+	  {
+	    switch (stack[stackcnt - 1].type)
+	      {
+	      case GRUB_SCRIPT_STACKITEM_FORIN:
+		curexec = stack[stackcnt - 1].cmd;
+		exec_forin ();
+		break;
+	      }
+	    break;
+	  }
+	}
+      if (curexec->cmd.flags & GRUB_SCRIPT_COMMAND_FLAG_NOT)
+	ret = ret ? 0 : GRUB_ERR_FALSE;
+      curexec = curexec->next;
+    }
+
+  return ret; 
+}
+
+grub_err_t 
+grub_script_command_execute (char *in, char * (*nextline) (void))
+{
+  grub_err_t ret = 0;
+  curptr = curcmd = in;
+  nl = nextline;
+  while (curptr && grub_errno != GRUB_ERR_PARSE)
+    ret = grub_script_command_execute_real ();
+  return ret;
+}
+
+

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Patch] Scripting engine
  2005-08-24  9:36           ` [Patch] Scripting engine Vladimir Serbinenko
@ 2005-08-28 12:55             ` Yoshinori K. Okuji
  2005-08-28 14:11               ` Vladimir Serbinenko
  2005-09-25 11:40               ` Vladimir Serbinenko
  2005-08-31 19:22             ` Marco Gerards
  1 sibling, 2 replies; 19+ messages in thread
From: Yoshinori K. Okuji @ 2005-08-28 12:55 UTC (permalink / raw)
  To: The development of GRUB 2

On Wednesday 24 August 2005 11:36, Vladimir Serbinenko wrote:
> I wrote the preciew version of scripting engine. I'll add some comments
> soonly.

I'd like to see a kind of "design document", since it is a bit hard for others 
to understand.

> It would be good if then it
> could be incorporated
> to CVS because it would be easy to developpe and debug.

We must wait until your assignment is finished. How is it going?

Okuji



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Patch] Scripting engine
  2005-08-28 12:55             ` Yoshinori K. Okuji
@ 2005-08-28 14:11               ` Vladimir Serbinenko
  2005-09-25 11:40               ` Vladimir Serbinenko
  1 sibling, 0 replies; 19+ messages in thread
From: Vladimir Serbinenko @ 2005-08-28 14:11 UTC (permalink / raw)
  To: The development of GRUB 2


>I'd like to see a kind of "design document", since it is a bit hard for others 
>to understand.
>  
>
Ok. I hope to write it this week (my studies begin tomorrow)

>
>We must wait until your assignment is finished. How is it going?
>
>
>  
>
No problem. I meant after assignment. I sent it back to FSF about 2
weeks ago.

Vladimir




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Patch] Scripting engine
  2005-08-24  9:36           ` [Patch] Scripting engine Vladimir Serbinenko
  2005-08-28 12:55             ` Yoshinori K. Okuji
@ 2005-08-31 19:22             ` Marco Gerards
  2005-09-04 13:23               ` Vladimir Serbinenko
  1 sibling, 1 reply; 19+ messages in thread
From: Marco Gerards @ 2005-08-31 19:22 UTC (permalink / raw)
  To: The development of GRUB 2

Vladimir Serbinenko <phcoder@gmail.com> writes:

> I wrote the preciew version of scripting engine. I'll add some comments
> soonly.
> Parser parses everytime one command because the commands could be
> entered from
> commandline. Bison converts in kind of pseudocode. Arithmethic support
> will be done
> by separate parser because arithmetic parse is very different form
> bash one.

Can't this be done in the same bison parser?  Or what do you mean?

I noticed that you have hand written yylex, wouldn't it be a lot
easier to use flex for this?  In that case you can easily detect
tokens using regular expressions.  This makes maintaining the
tokenizer really easy.

Thanks,
Marco




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Patch] Scripting engine
  2005-08-31 19:22             ` Marco Gerards
@ 2005-09-04 13:23               ` Vladimir Serbinenko
  0 siblings, 0 replies; 19+ messages in thread
From: Vladimir Serbinenko @ 2005-09-04 13:23 UTC (permalink / raw)
  To: The development of GRUB 2

Marco Gerards wrote:

>
>Can't this be done in the same bison parser?  Or what do you mean?
>  
>
I don't think so. Even the tokenization is very differetn. Ex:
2+3*5 is one token for normal parsing, but five for arithmethic
and yylex knows nothing about what parsing is now. If it would always
issue 5 tokens it would be impossible to difference
2+3*5 and 2 + 3 * 5 And yylex normally must not issue the space -
it would make bison parser too complicated

>I noticed that you have hand written yylex, wouldn't it be a lot
>easier to use flex for this?  In that case you can easily detect
>tokens using regular expressions.  This makes maintaining the
>tokenizer really easy.
>  
>
For bash regular expression is not really needed. There are only 3 types
of tokens:
reserved words (if, ...), normal words (WORD) and command separators (;
and ENTER).
All token except WORD could be easily recognized by simple comparing
(check_for_keyword function). But WORD needs special treatment because
its value
is partially unknown that's why I use superchar structure (it keeps
known parts as well as
necessary information to determine the value of unknown parts)
                                 
                                                                        
                              Vladimir




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Patch] Scripting engine
  2005-08-28 12:55             ` Yoshinori K. Okuji
  2005-08-28 14:11               ` Vladimir Serbinenko
@ 2005-09-25 11:40               ` Vladimir Serbinenko
  1 sibling, 0 replies; 19+ messages in thread
From: Vladimir Serbinenko @ 2005-09-25 11:40 UTC (permalink / raw)
  To: The development of GRUB 2

Unfortunately I haven't had a lot of time to work with GRUB2. I'll have
some more when my holidays begin in mid October.


Yoshinori K. Okuji wrote:

>
>I'd like to see a kind of "design document", since it is a bit hard for others 
>to understand.
>  
>
Ok. I send one with this mail. Perhaps it would be good to add a folder for
developpement docs and standartisize the format. What about /devdocs and
html?

>We must wait until your assignment is finished. How is it going?
>
>  
>

It's strange. It's already a month that I sent my assignment and I've
still nothing received.

                                                                        
               Vladimir
------------------------------------------------------------------

The scripting engine is separated into 2 parts: parser and executer.
Parser is wirtten with bison using hand-written yylex. It transforms one
command into grub_script_commandlist. This structure represents a chain
of commands in the form of linked list. Every single command is
represented by grub_script_command. Which has the following fields:
enum grub_script_command_type type
which indicates what command it is:
GRUB_SCRIPT_COMMAND_NORMAL - just a non-scripting command
GRUB_SCRIPT_COMMAND_FORIN - used for for..in..
GRUB_SCRIPT_COMMAND_LOOKUP - used for block-end keyword like done, fi
indicating to interpreter to relaunch or end the loop
enum grub_script_command_chain
which indicates how this command is linked with previous: independent,
with && or with ||.
flags: command flags. Now only GRUB_SCRIPT_COMMAND_FLAG_NOT (command was
with !) is defined.
non-scripting command:
struct grub_script_superchars *normal - a non-scripting command to execute.
for...in:
struct grub_script_superchars *var - a variable to set
struct grub_script_superchars *vals - the values to set to var
struct grub_script_commandlist *lookup - where the end of loop is.

grub_script_sueprchar is used to store the strings. char * is
unappropriated because value of the string is unknown at parsing time.
it's separated in chunks which are represented in linked list. There are
4 types of chunks: plain (just a string), variable ($var), arithmethic
($((expression)))  and command (`cmd` or $(cmd)) to transform to char* 
superchartostring is used.

grub_script_superchars is used to store array of strings like command
with arguments a variable list. supercharstostrings is used to transform
to char**

terminal tokens:
ENTER: '\n'
FOR: "for" keyword
SEMICOLON: ';'
IN: "in" keyword
DO: "do" keyword
DONE: "done" keyword
NOP: not used
WORD: any word, that is not a keyword. Represented like superchars
OR: "||" keyword
AND: "&&" keyword
NOT: '!' keyword

other symbols
out: output
commandlist  : list of commands
arglist : list of words (like not scripting command with arguments or
vallist for for..in)
command :
execlist : list of inter-linked (by || or &&) commands

pre_command : solitary command that waits for ||, &&, ; or newline
cmdend: end of execlist (; or newline)

I hope that this small design document will help. All propositions and
questions are welcome.




^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2005-09-25 11:55 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-14  9:18 [DISCUSSION] Scripts and menus Vladimir Serbinenko
2005-08-14 13:29 ` Douglas Wade Needham
2005-08-14 13:53   ` Vladimir Serbinenko
2005-08-14 15:12   ` Yoshinori K. Okuji
2005-08-14 22:54     ` Douglas Wade Needham
2005-08-14 23:09       ` Yoshinori K. Okuji
2005-08-15  7:27       ` [DISCUSSION] Grub2 Improvements marm.mm
2005-08-15  8:37         ` Yoshinori K. Okuji
2005-08-14 14:35 ` [DISCUSSION] Scripts and menus Yoshinori K. Okuji
2005-08-14 16:03   ` Vladimir Serbinenko
2005-08-14 18:01     ` Yoshinori K. Okuji
2005-08-14 18:30       ` Vladimir Serbinenko
2005-08-15 17:37         ` Marco Gerards
2005-08-24  9:36           ` [Patch] Scripting engine Vladimir Serbinenko
2005-08-28 12:55             ` Yoshinori K. Okuji
2005-08-28 14:11               ` Vladimir Serbinenko
2005-09-25 11:40               ` Vladimir Serbinenko
2005-08-31 19:22             ` Marco Gerards
2005-09-04 13:23               ` Vladimir Serbinenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.