   _        ___  ____ ____  ____          __
  |_|_ _   / _ \/ ___/ ___||  _ \    ___ / _| __ _
  _|_||_| | | | \___ \___ \| |_) |  / __| |_ / _` |
 |_||_|_| | |_| |___) |__) |  __/  | (__|  _| (_| |
  |_|_|_|  \___/|____/____/|_|      \___|_|  \__, |
                                             |___/
  OSSP cfg - Configuration Parsing

  TODO

  o finish/fix implementation of cfg_node_select()
  o implement cfg_node_find()
  o fix internal linkage with "left sibling" pointer
  o support for prefixes of all non-static symbols to better support embedding
  o finish cfg.pod manual page (function description!)
  o add ts-based test suite
  o add line tracking support
  o add pre-processor with at least includes
  o add config tree verification!
  o cfg.tok: in scanner: use an combination of dynamic buffer and atomic
    symbol/token sub-library to allow first tokens of mostly arbitrary
    size and then to store the tokens redundancy-free.
  o named parameters [--]name=value (options)

  ==================================================================================

- Problem: \x00 oder \x{00} wird zu NUL-terminator -> use ptr+len instead
- caStr/cpStr durch yyless/yymore??
- syntax verification
- command line query tool
- error checking in scanner?
- OSSP ex support
- wieso geht sample.cfg nicht als Arg bei "make check"?

- newline in error message
$ ./cfg_test sample2.cfg
ERROR: <line 7, column 1: `1b;
<}> quu'>

- cfg_t

rewrite-uri <regex> <subst> { <rewrite-cond> }
rewrite-uri ^/(.*) /path/$1 --redirect=permanent q{
    %{SOURCE} != "x"
};


Directory [--foo=A]

Argument:
  - type:
    - keyword ("foo") via name
    - option ("--foo=BAR") via name & regex
    - argument ("foo") via regex
  - amount:
    - 1
    - 0/1  ?
    - 0..n *
    - 1..n +
  - location:
    - by position
    - by name
  - lookup via:
    - name
    - position
    - regex match

foo   * bar
foo   = bar|quux|...
foo   (bar baz quux)

foo  ::= bar*         ;   kleene closure
foo  ::= bar|baz|quux ;   union
foo  ::= bar baz quux ;   concatenation

foo  ::= {foo;...}    ;   sequence of ...
foo  ::= (...)        ;   grouping
foo  ::= "bar"        ;   fixed terminal
foo  ::= /bar/        ;   regex terminal
foo  ::= <A>          ;   arbitrary argument
foo  ::= <O>          ;   arbitrary option

SEQ ::= "{" DIR DIR* "}"
DIR ::= TOK (" " TOK)* ";"
TOK ::= ...

SEQ ::= DIR*     SEQ(dir,dir,...)
DIR ::= TOK+     DIR(tok,tok,...)
TOK ::= string   "..."

config        ::= SEQ(directory|user|rewrite|access)
directory     ::= DIR("directory",<O>*,<A>)
dir_options   ::=
user          ::= DIR("user",/^[a-z]$/)
rewrite       ::=
access        ::= "access" ("allow"|"deny"):action SEQ(access_list):acl
access_list   ::= m/^!?%{ID}$/

acl           ::= "acl" TOK:name acl_list
acl_list      ::= SEQ(acl_entry)
acl_entry     ::= acl_action "from" net-addr:src "to" net-addr:dst
acl_action    ::= "allow"|"deny"
net_addr      ::= net_hostname | net_ipv4addr | net_ipv6addr

sequence all {
    directive --class 1;
};
directive --class 1 "foo" {
    option "bar" --occur=1
};

---------------------------------------------------------------------------

foo on;
bar /bla {
    foo off;
    baz --fuck {
        b1; b2 --nase=baer; b3; b4; b5;
    } --fuck2;
};
quux a1 a2 a3 a4;
quux;

---------------------------------------------------------------------------

sequence ROOT {
    directive foo;
    directive bar;
    directive quux --count=1:oo;
};
sequence bar-seq {
    directive foo --count=0:1;
    directive baz --count=1:oo;
};
directive foo {
    token - on|off|yes|no;
};
directive bar {
    token path /.*;
    sequence bar-seq;
};
directive baz {
    option fuck;
    option fuck2;
    sequence {
        directive foo {
            option nase (baer|hugo);
            option foo [0-9];
            token ip-address;
        };
    };
};
directive quux {
    token --count=0:oo a.*;
};
token ip-address b1|b2|b3|b4|b5;

-------------------------------------------------------------------------------

<config>     ::= "sequence" <count>? <name>;
               | "sequence" <count>? <name>? "{" <directive>* "}";
<directive>  ::= "directive" <token-count>? <name>;
               | "directive" <token-count>? <name>? "{" <option>* <token>+ };
<option>     ::= "option" <name> <regex>?;
<token>      ::= "token" <name>? <regex>;
<count>      ::= /^(\+|\*|\?|[0-9]+,[0-9]*|[0-9]*,[0-9]+|[0-9]+)$/
<name>       ::= /^[a-zA-Z][a-zA-Z0-9_.-]*$/
<regex>      ::= ...

-------------------------------------------------------------------------------

sequence ROOT {
    directive * "directive" {

    directive * token-1 {
        token token "token";
        token name  /^[a-zA-Z][a-zA-Z0-9_.-]*$/;
        token regex /^.+$/;
    }
};

-------------------------------------------------------------------------------

directive token {
    opt1      { /.../ opt2=/.../ } {
    directive { /^token$/ };
    name      { m/.../; m/^[a-zA-Z][a-zA-Z0-9_.-]*$/ } ?;
    name      { m/(...|[a-zA-Z][a-zA-Z0-9_.-]*$)/ } ?;
    regex     { m/^.+$/ };
};
directive acl   { directive=/^acl$/ addr=/^...|...$/+ };

-------------------------------------------------------------------------------

a?b((c|d)+e)?f

A m/a/ ?
B m/b/
{
    {
        C m/c/ ;
        D m/d/
    } +
    E m/e/
} ?
F f

<directive-match> ::= <token-match>+
<token-match> ::= <name>? <regex> <quant>?

-------------------------------------------------------------------------------

<config>     ::= "sequence" <count>? <name>;
               | "sequence" <count>? <name>? "{" <directive>* "}";
<directive>  ::= "directive" <name>;
               | "directive" <name>? "{" <options> "}" "{" <tokens> "}";

<options>     ::= <tok-match>+
<tokens>      ::= <dir-match>+

<dir-match>   ::= <tok-match>+
<tok-match>   ::= <name>? <node-match> <quant>?
<node-match>  ::= "{" <dir-match> "}" | <regex>

<option>     ::= "option" <name> <regex>?;
<token>      ::= "token" <name>? <regex>;

<count>      ::= /^(\+|\*|\?|[0-9]+,[0-9]*|[0-9]*,[0-9]+|[0-9]+)$/
<name>       ::= /^[a-zA-Z][a-zA-Z0-9_.-]*$/
<regex>      ::= ...

