grub-devel
[Top][All Lists]
Advanced

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

Scripting (IMPORTANT!)


From: Marco Gerards
Subject: Scripting (IMPORTANT!)
Date: Thu, 05 Oct 2006 15:41:09 +0200
User-agent: Gnus/5.110004 (No Gnus v0.4) Emacs/21.4 (gnu/linux)

Hi,

As you noticed I put important in the topic.  I personally consider
scripting one of the most important features that has to be
implemented before GRUB 2 can be used in distributions.

It's also one of the features that we all have to talk about before we
determine it will not be changed.  After GRUB 2 is being used by
everyone it will be hard, if not impossible, to make changes that make
different GRUB 2 versions incompatible.

So it is important that most active developers read my ideas about
scripting and what I currently implemented.  As you might have
noticed, I wrote this in little time and thus it will be a bit chaotic
and it is not well written.  But I hope I can start this important
discussion this way.

Another thing I want to discuss soon is using "cd" and "pwd" commands
to change the current directory instead of what we have now.  I would
like to make this change as well.

I'm looking forwards to your ideas, questions, suggestions, criticism
and bug reports. :-)

--
Marco


=========
Variables
=========

In GRUB 2 there are two types of variables.  The difference is like in
bash: the scope.  Variables either have a local or global (exported)
scope.  Initially all new added variables have the local scope.  By
using the export command they can be made global.

Some variables have a special purpose and will be created by GRUB.
These are:

- root: The active disk/partition (rw, global)
- prefix: The pathname used to load grub.cfg and the modules (rw, global)
- platform: Set to the platform, eg. EFI, IEEE1275, PCBIOS, etc. (ro, global)
- processor: Processor architecture GRUB was compiled for, eg. PPC, x86 (ro, 
global).
- debug: Print debugging messages for certain parts of the code, or
  all messages when set to all.  (rw, global?)
- pager: When set to `1', wait for a key when the bottom of the screen was 
reached.

(more will be added, like variables to read time/date, random, etc)

To include a file two commands can be used.  The first is source,
which does not change the scope.  The second is `configfile' which
opens a new scope.

Variables can be used like in bash.  You can use set to set or list
variables.  Explicit assignments (`foo=bar' instead of `set foo=bar')
is possible.  You can include variables in command lines by using the
`$' prefix, for example $foo.  To use it to concatenate variable
contents and text, you can use the ${foo} syntax.  Sometimes you want
to use the `$' in commands (for example, multiboot lines for the Hurd)
without meaning a variable, in that case you can use single quotes for
escaping (for example, '$foo').

==> Currently unimplemented: The export command, special variables
    other than root, prefix, debug and pager.  Concatenating with
    variables is currently broken.

=========
Functions
=========

Functions can be created as follows:

function funcname { code }

After that they can be called just like any other command.

Arguments can be passed to functions.  In the function body they can
be accessed as in bash ($1, $2, etc).

==> Currently unimplemented: Function arguments.

==> Idea: Exporting functions to be full featured commands that can be
    tab completed, documented, etc.  This way functions can be
    implemented by scripts instead of C code.

====
 If
====

The if command is also quite similar to the if command in bash.  It
has the following syntax:

if command ; then commands fi
OR:
if command ; then commands else commands fi

The command that follows the if contains the condition that is tested
for.  You can use any command and check the return status like this.
The most useful command to use here is the `test' (or `[') command.
It is similar to the test command in bash, although it can not check
for certain filesystem bits like file protection and certain
filetypes.

==> Currently unimplemented: The test command (although it is almost
    finished).

============
Menu entries
============

Menu entries are added with `menuentry' (or its alias `@').  It's
important to notice this is not a command.  Because it's part of the
scripting syntax, it can have unique features.  A menuentry is like a
function, especially because it can have arguments!

Syntax: menuentry "Entry name" [arguments...] { body }

Make sure the entry name is properly escaped, otherwise spaces can not
be included and will be seen as separator.  The arguments will become
semi-variables like #1, #2, etc.  These can be used so one menuentry
can be used as a template for a lot of menuentries.  This can best be
explained with an example:

(inside loop that sets i = 1...x)
@ "Partition $i" $i { linux /vmlinuz root=/dev/hda#{1} }

This will set #1 to $i (it's the first argument).  The menuentry
command is executed for i=1...9 and will generate 9 different menu
entries.  This is useful for automatic generation of menu entries.

==> Currently unimplemented: Arguments for automatic generation of
    menuentries.
==> Discussion: Perhaps I will change the #1 into $1, although this is
    not really a variable.

=====
 for
=====

The for command can be used to iterate over a set of data.  I don't
like the idea of implementing this *exactly* like in bash.  Personally
I am thinking of the following syntax:

Iterating over files:
for x in (hd0,3)/foo/* ; do commands ; done

The commands will be executed for each file in the directory.

Iterating over disks:
for x in (*) ; do commands ; done

Iterating over partitions:
for x in (*,*); do commands ; done

An alternative syntax which I think is more natural could be:

foreach x in files ; do commands ; done
foreach x in disks ; do commands ; done
foreach x in partitions (hd0) ; do commands ; done
foreach x in modules ; do commands ; done

The foreach syntax makes it possible to add named iterators with
arguments.  In that case modules can be written that add new
iterators.  Perhaps even scrips can be used for this.  I don't like
the idea of using the standard output of files for this, because I am
afraid this will get messy and tricky.

==> Currently unimplemented: All of this.

===========================
 Other language constructs
===========================

Other language constructs can and will be implemented.  Like: elif,
 while, case, select, etc.
  
==> Currently unimplemented: All these constructs.

===============================
 Commands useful for scripting
===============================

- echo: Prints text.
- cmp: Compares files.
- configfile/source: Including other files.
- search: Search for files, labels, etc. and set a variable.
- test: Test certain conditions.

==> Currently unimplemented: Echo can't "beep".

================
 Error handling
================

Every command can return an error value.  This error value will be
available as $?.  This variable will be checked by if, while, etc.  In
scripts all parsing errors will be non fatal so the system is not left
unbootable.

Unparsable menu entries will be added, but will not be executable,
only the editor is available.

One special purpose variable $ERROR will be added.  It will contain
the error strings when $? is set to non-zero.  In that case you can do
error handling in scripts.

After every command an error is printed by default.  You don't want
this to be silent, otherwise users can not detect errors.  But it
should be able to set error handling to silent because a certain
script or function does its own error handling.  This can be done by
setting $ERRORS=0 (default it is set to 1).

==> Currently unimplemented: $ERROR, $ERRORS, a lot of this logic is
    far from perfect.





reply via email to

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