$Id: config-semantics 4792 2001-06-21 08:59:39Z rra $

Groups in a configuration file have a well-defined order, namely the order
in which the groups would be encountered in a depth-first traversal of the
parse tree.

The supported operations on a configuration file parse tree for reading
are:

 * Search.  Find the first group of a given type in a given tree.  This is
   done via depth-first search.

 * Next.  Find the next group of a given type, starting from some group.
   This is done via depth-first search.

 * Query.  Look up the value of a given parameter in a given group (with
   inheritance).  Note that the expected type of the parameter value must
   be provided by the caller; the parsing library doesn't know the types
   of parameters.

 * Prune.  Limit one's view of the configuration file to only a given set
   of group types and everything underneath them; any other group types
   encountered won't be parsed (and therefore everything under them, even
   groups of the wanted type, won't be seen).

Therefore, the *only* significance of nested group structure is parameter
inheritence and pruning.  In the absence of pruning, it would always be
possible, by duplicating parameter settings that were inherited and laying
out the groups in depth-first traversal order, to transform any
configuration file into an entirely equivalent one that contains no nested
groups.  This isn't true in the presence of pruning, but pruning is
intended to be used primarily for performance (ignoring the parts of the
configuration that don't apply to a given parsing library client).

The expected way for clients to use the parsing library is to follow one
of these two access patterns:

 * Search for a particular configuration group and then query it for a set
   of parameters (either one by one as they're used, or all at once to
   collapse the parameters into a struct for faster access later).  This
   is expected to be the common pattern for finding and looking up
   settings for a particular program.  There will generally only be a
   single group per group type for groups of this sort; it doesn't make
   sense to have multiple groups setting general configuration options for
   a program and have to iterate through them and merge them in some
   fashion.

 * Iterate through all groups of a given type, building a list of them (or
   of the data they contain).  This is the model used by, for example,
   storage classes; each storage class has a set of parameters, and the
   storage subsystem needs to know about the full list of classes.

Note that neither of these operations directly reveal the tree structure;
the tree structure is intended for the convenience of the user in setting
defaults for various parameters so that they don't have to be repeated in
each group, and to allow some top-level pruning.  It's not intended to be
semantically significant other than that.

Here are some suggested general conventions:

 * General options for a particular program should be separated out into a
   their own group.  For example, a group innwatch in inn.conf to set the
   various options only used by innwatch.  Note that pruning is inclusive
   rather than exclusive, so programs should ideally only need to care
   about a short list of groups.

 * Groups used only for grouping and setting default parameters, ones that
   won't be searched for explicitly by any program, should use the type
   "group".  This can be used uniformly in all configuration files so that
   whenever a user sees a group of type "group", they know that it's just
   syntactic convenience to avoid having to repeat a bunch of parameter
   settings and isn't otherwise significant.

 * Groups that are searched for or iterated through shouldn't be nested;
   for example, if a configuration file defines a list of access groups,
   nesting one access group inside another is discouraged (in favor of
   putting both groups inside an enclosing group of type "group" that sets
   the parameters they have in common).  This is to cut down on user
   confusion, since otherwise the nesting appears to be significant.
