Testing
Testing


Topsy Configure System:                                   Author: Claudio Jeker
=======================                                       claudio@topsy.net

Version: $Id: README.config 2911 2007-03-07 13:27:12Z rnatau $


This document describes the Topsy Configure System and its Config Language.
config.in files are written in this language.

The first Section is generic Info about the Topsy Configure System and 
everybody should read it.


Generic Info:
=============

Most subdirectories have a config.in file which will be parsed and displayed.
The Config directory contains the master config.in and the different scripts 
for parsing and displaying. Also a generic defaults file is in Config.

On startup the master config.in file will be parsed and the if a defaults file
is present it will be sourced. 

The defaults file is one of:
  - if the environment variable CONF_DEFAULTS is set, this will be used
  - else if there is a config.default file in the Topsy main directory,
    this will be used
  - else use Config/defaults

NOTES:
 - the Config Language is not 'sh' or 'bash'.
 - because config will write multiple temporary files a temporary directory
   will be created so we do not pollute the Topsy Tree. The default name is 
   .config.tmp. The environment variable CONF_TMP_DIR sets the temporary dir.
 - after a successful configuration a new file config.default will be written
   containing the current settings.


PLEASE read this file carefully if you want to modify/write a config.in file.


Topsy config.in Syntax:
=======================

The Topsy config.in syntax is similar to the syntax of linux's config.in files.
It is mostly sh syntax but use ONLY the specified syntax, because the files are
normaly parsed. 

Although it looks, and usually acts, like a subset of the 'sh' language,
Config Language has a restricted syntax and different semantics.

Here is a basic guideline for Config Language programming: use only the
programming idioms that you see in existing Config.in files.  People often
draw on their shell programming experience to invent idioms that look
reasonable to shell programmers, but silently fail in Config Language.

**** BUT the Config Language is not 'sh' or 'bash'. ****

Don't tell me I did not warn you.



=== Statements

A Config Language script is a list of statements.  There are 20 simple
statements; an 'if' statement; 3 block statements; and a 'source' statement.

A '\' at the end of a line marks a line continuation.

'#' usually introduces a comment, which continues to the end of the line.

Newlines are significant.  You may not substitute semicolons for newlines.
The 'if' statement does accept a semicolon in one position; you may use
a newline in that position instead.

Block Statements have a start keyword and a end keyword normaly 
'end"start keyword"'. They group following statements togehter.


=== Grammar Elements:
<TEXT>:
    A <TEXT> is a single-quoted string or a double-quoted string.
    If the <TEXT> is double-quoted, it may not have any $ substitutions.
    For printing a $ use a single-quoted string or \$. Escaping of " and '
    is also allowed. <TEXT> may be multiline but pay attetion to idents.

<TITLE>:
    A <TITLE> is a <TEXT>. Normaly it should be singleline.

<VAR>:
    A <VAR> is a single unquoted word.  A <VAR> must have a name of
    the form CONFIG_*.  mkdep relies on this convention in order
    to generate dependencies on individual CONFIG_* symbols.

<VALUE>:
    A <VALUE> is a single unquoted word, a single-quoted string, or a
    double-quoted string.  If the <VALUE> is unquoted or double quoted,
    then $-substitution will be performed on the <VALUE>.

<TAG>:
     <TAG> is a single unquoted word. The $-substitution will be performed
     on the <TAG>.

<FILE>:
     <FILE> is single unquoted relative path starting from the Topsy main
     directory. No $-substitution will be performed on the <FILE>.

<EXPR>:
    An <EXPR> is a sh-like expression using the operators
    '=', '!=', '-a', '-o', and '!'. The $-substitution will be performed.

<STATEMENT>:
    A <STATEMENT> is a line or multiline containing one Keyword plus 
    some other grammar elements


=== Keywords and Statements

Menu Statement: (Block statement)
  menu <TITLE>
    <STATEMENT>
    ...
  endmenu

Help Statement:
  help <VAR> <TEXT>

Define Statements:
  define <VAR>=<VALUE> ...
  define_bool <VAR> <VALUE>
  define_hexint <VAR> <VALUE>
  define_int <VAR> <VALUE>
  define_multistate <VAR> <VALUE>
  define_text <VAR> <VALUE>
  undefine <VAR> ...

Ask/Menu Statements:
  bool <TITLE> <VAR>
  multistate <TITLE> <VAR>
  int <TITLE> <VAR>
  hexint <TITLE> <VAR>
  text <TITLE> <VAR>
  seperator

Block Ask Statements
  radiolist <TITLE> <VAR>
    value <TITLE> <TAG>
    ...
  endradiolist
  chooselist <TITLE> <VAR>
    value <TITLE> <TAG>
    ...
  endchooselist
  

Dependent ask statements:
  dep_bool <TITLE> <VAR> "<EXPR>" ... 
  dep_multistate <TITLE> <VAR> "<EXPR>" ... 
  dep_int <TITLE> <VAR> "<EXPR>" ... 
  dep_hexint <TITLE> <VAR> "<EXPR>" ... 
  dep_text <TITLE> <VAR> "<EXPR>" ... 
  probably dep_chooselist and dep_radiolist will be added. 

Source statement:
  source <FILE>
  
If statements:
  if [ <EXPR> ] ; then
    <STATEMENT>
    ...
  (elif [ <EXPR> ] ; then
    <STATEMENT>
    ... )
  (else
    <STATEMENT>
    ... )
  fi
  
  or
  if [ <EXPR> ]
  then  
    <STATEMENT>
    ...
  ...


Now I should explain the statements, but first I write the parser...
... done


=== Menu Statement: (Block statement)
  menu <TITLE>
    <STATEMENT>
    ...
  endmenu

This will group all enclosing statements into one menu node. There is no 
limitation of statements. (Side note: don't use to many nested menus, the 
user will thank you). The <TITLE> will be shown as the menu title but is also
usd as the name of a menu entry in the parent menu.
Developper Note: There is a implicit main menu node ("Topsy Main Menu") which
is automagicaly created by the parser (with the load and store entries)


=== Help Statement:
  help <VAR> <TEXT>

Help text for a specific option/variable. The text will be displayed if help
for this option/variable is requested.
Developper Note: XXX make it possible to add helptext for a menu


=== Define Statements:
  define <VAR>=<VALUE> ...
  define_bool <VAR> <VALUE>
  define_hexint <VAR> <VALUE>
  define_int <VAR> <VALUE>
  define_multistate <VAR> <VALUE>
  define_text <VAR> <VALUE>
  undefine <VAR> ...

Used to predefine a value or to cleare a value. The generic define should not
be used, instead use the corresponding define.
Developper Note: correctness of defines is only tested on write.


=== Ask/Menu Statements:
  bool <TITLE> <VAR>
  multistate <TITLE> <VAR>
  int <TITLE> <VAR>
  hexint <TITLE> <VAR>
  text <TITLE> <VAR>
  seperator

Menuelemets: shows <TITLE> and let the user modify <VAR>
 - Bool: <VAR> can be set to Yes (y) or No (n)
 - Multistate: <VAR> can be set to Yes (y), Module (m), PlugIn (p) or No (n)
 - int: <VAR> can be set to a figure, input can be either hex (starting 
        with 0x) or int
 - hexint: same as int only that it will be stored as hex value
 - text: generic text field, no checks are done.
 - seperator: menu seperator to group menu entries.
Developper Note: The conversion from hex to int and vice versa is done when 
writing the configuration.


=== Block Ask Statements
  radiolist <TITLE> <VAR>
    value <TITLE> <TAG>
    ...
  endradiolist
  chooselist <TITLE> <VAR>
    value <TITLE> <TAG>
    ...
  endchooselist

Generate a radiolist or chooselist with the following values. In both blocks
only value statements and if statements may be used. All other statements are
not allowed. In radiolist there is only one <TAG> set in <VAR> where in 
chooselist multiple may be set.


=== Source statement:
  source <FILE>

Tells the parser to source the <FILE>, so it is possible to to have multiple
config.in files building a complete configuration.
Developper Note: it is good practise to source complete menu blocks and not to
add partial stuff. Especially for the master config.in.


=== Dependent ask statements:
  dep_bool <TITLE> <VAR> '<EXPR>' ... 
  dep_multistate <TITLE> <VAR> '<EXPR>' ... 
  dep_int <TITLE> <VAR> '<EXPR>' ... 
  dep_hexint <TITLE> <VAR> '<EXPR>' ... 
  dep_text <TITLE> <VAR> '<EXPR>' ... 
  probably dep_chooselist and dep_radiolist will be added. 

Dependent ask statements are used when a variable depend on some others.
If all expressions expand to true the intput range of the variable is free,
else if one or more expressions are false the <VAR> is blocked. The meaning
of blocked depends on the <VAR> type:
 - Bool and Multistate: if blocked it is set to No (n) and a non selectable
                        menu entry is generated
 - Int, Hexint, Text:   if blocked it is set to the empty string and no menu
                        entry is generated
XXX test if this is usable. or if we should just test <VAR> instead of <EXPR>


=== If statements:
  if [ <EXPR> ] ; then
    <STATEMENT>
    ...
  (elif [ <EXPR> ] ; then
    <STATEMENT>
    ... )
  (else
    <STATEMENT>
    ... )
  fi

This is a conditional statement, with an optional 'else' clause.  You may
substitute a newline for the semicolon if you choose.

<EXPR> may contain the following atoms and operators.  Note that, unlike
shell, you must use double quotes around every atom.

  <ATOM>:
    "..."               a literal
    "$..."              a variable

  <EXPR>:
    <ATOM>  = <ATOM>    true if atoms have identical value
    <ATOM> != <ATOM>    true if atoms have different value

  <EXPR>:
    <EXPR> -o <EXPR>    true if either expression is true
    <EXPR> -a <EXPR>    true if both expressions are true
    ! <EXPR>            true if expression is not true

Note that a naked <ATOM> is not a valid <EXPR>.  If you try to use it
as such:

    # Do not do this.
    if [ "$CONFIG_EXPERIMENTAL" ]; then
        bool 'Bogus experimental feature' CONFIG_BOGUS
    fi

    # Correct.
    if [ "$CONFIG_EXPERIMENTAL" == "y" ]; then
        bool 'Bogus experimental feature' CONFIG_BOGUS
    fi

... then you will be surprised, because CONFIG_EXPERIMENTAL never has a
value of the empty string!  It is always "y" or "n", and both of these
are treated as true (non-empty).
Normaly it should be checked against "y" because "n" and "" are equal and 
both are valid.

=== END

If you think you have found a bug in this document or a spelling error in on 
of the scripts you can send a bug report to claudio@topsy.net
