Blame src/conf.c

Packit 4a16fb
/**
Packit 4a16fb
 * \file conf.c
Packit 4a16fb
 * \ingroup Configuration
Packit 4a16fb
 * \brief Configuration helper functions
Packit 4a16fb
 * \author Abramo Bagnara <abramo@alsa-project.org>
Packit 4a16fb
 * \author Jaroslav Kysela <perex@perex.cz>
Packit 4a16fb
 * \date 2000-2001
Packit 4a16fb
 *
Packit 4a16fb
 * Tree based, full nesting configuration functions.
Packit 4a16fb
 *
Packit 4a16fb
 * See the \ref conf page for more details.
Packit 4a16fb
 */
Packit 4a16fb
/*
Packit 4a16fb
 *  Configuration helper functions
Packit 4a16fb
 *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>,
Packit 4a16fb
 *			  Jaroslav Kysela <perex@perex.cz>
Packit 4a16fb
 *
Packit 4a16fb
 *
Packit 4a16fb
 *   This library is free software; you can redistribute it and/or modify
Packit 4a16fb
 *   it under the terms of the GNU Lesser General Public License as
Packit 4a16fb
 *   published by the Free Software Foundation; either version 2.1 of
Packit 4a16fb
 *   the License, or (at your option) any later version.
Packit 4a16fb
 *
Packit 4a16fb
 *   This program is distributed in the hope that it will be useful,
Packit 4a16fb
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 4a16fb
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 4a16fb
 *   GNU Lesser General Public License for more details.
Packit 4a16fb
 *
Packit 4a16fb
 *   You should have received a copy of the GNU Lesser General Public
Packit 4a16fb
 *   License along with this library; if not, write to the Free Software
Packit 4a16fb
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 4a16fb
 *
Packit 4a16fb
 */
Packit 4a16fb
Packit 4a16fb
/*! \page conf Configuration files
Packit 4a16fb
Packit 4a16fb

Configuration files use a simple format allowing modern

Packit 4a16fb
data description like nesting and array assignments.

Packit 4a16fb
Packit 4a16fb
\section conf_whitespace Whitespace
Packit 4a16fb
Packit 4a16fb
Whitespace is the collective name given to spaces (blanks), horizontal and
Packit 4a16fb
vertical tabs, newline characters, and comments. Whitespace can
Packit 4a16fb
indicate where configuration tokens start and end, but beyond this function,
Packit 4a16fb
any surplus whitespace is discarded. For example, the two sequences
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
  a 1 b 2
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
and
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
  a 1 
Packit 4a16fb
     b 2
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
are lexically equivalent and parse identically to give the four tokens:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a
Packit 4a16fb
1
Packit 4a16fb
b
Packit 4a16fb
2
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
The ASCII characters representing whitespace can occur within literal
Packit 4a16fb
strings, in which case they are protected from the normal parsing process
Packit 4a16fb
(they remain as part of the string). For example:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
  name "John Smith"
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
parses to two tokens, including the single literal-string token "John
Packit 4a16fb
Smith".
Packit 4a16fb
Packit 4a16fb
\section conf_linesplicing Line continuation with \
Packit 4a16fb
Packit 4a16fb
A special case occurs if a newline character in a string is preceded
Packit 4a16fb
by a backslash (\). The backslash and the new line are both discarded,
Packit 4a16fb
allowing two physical lines of text to be treated as one unit.
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
"John \
Packit 4a16fb
Smith"
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
is parsed as "John Smith".
Packit 4a16fb
Packit 4a16fb
\section conf_comments Comments
Packit 4a16fb
Packit 4a16fb
A single-line comment begins with the character #. The comment can start
Packit 4a16fb
at any position, and extends to the end of the line.
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
  a 1  # this is a comment
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section conf_include Including configuration files
Packit 4a16fb
Packit 4a16fb
To include another configuration file, write the file name in angle brackets.
Packit 4a16fb
The prefix \c confdir: will reference the global configuration directory.
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
</etc/alsa1.conf>
Packit 4a16fb
<confdir:pcm/surround.conf>
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section conf_punctuators Punctuators
Packit 4a16fb
Packit 4a16fb
The configuration punctuators (also known as separators) are:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
  {} [] , ; = . ' " new-line form-feed carriage-return whitespace
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\subsection conf_braces Braces
Packit 4a16fb
Packit 4a16fb
Opening and closing braces { } indicate the start and end of a compound
Packit 4a16fb
statement:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a {
Packit 4a16fb
  b 1
Packit 4a16fb
}
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\subsection conf_brackets Brackets
Packit 4a16fb
Packit 4a16fb
Opening and closing brackets indicate a single array definition. The
Packit 4a16fb
identifiers are automatically generated starting with zero.
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a [
Packit 4a16fb
  "first"
Packit 4a16fb
  "second"
Packit 4a16fb
]
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
The above code is equal to
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a.0 "first"
Packit 4a16fb
a.1 "second"
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\subsection conf_comma_semicolon Comma and semicolon
Packit 4a16fb
Packit 4a16fb
The comma (,) or semicolon (;) can separate value assignments. It is not
Packit 4a16fb
strictly required to use these separators because whitespace suffices to
Packit 4a16fb
separate tokens.
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a 1;
Packit 4a16fb
b 1,
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\subsection conf_equal Equal sign
Packit 4a16fb
Packit 4a16fb
The equal sign (=) can separate variable declarations from
Packit 4a16fb
initialization lists:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a=1
Packit 4a16fb
b=2
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
Using equal signs is not required because whitespace suffices to separate
Packit 4a16fb
tokens.
Packit 4a16fb
Packit 4a16fb
\section conf_assigns Assignments
Packit 4a16fb
Packit 4a16fb
The configuration file defines id (key) and value pairs. The id (key) can be
Packit 4a16fb
composed from ASCII digits, characters from a to z and A to Z, and the
Packit 4a16fb
underscore (_). The value can be either a string, an integer, a real number,
Packit 4a16fb
or a compound statement.
Packit 4a16fb
Packit 4a16fb
\subsection conf_single Single assignments
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a 1	# is equal to
Packit 4a16fb
a=1	# is equal to
Packit 4a16fb
a=1;	# is equal to
Packit 4a16fb
a 1,
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\subsection conf_compound Compound assignments (definitions using braces)
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a {
Packit 4a16fb
  b = 1
Packit 4a16fb
}
Packit 4a16fb
a={
Packit 4a16fb
  b 1,
Packit 4a16fb
}
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section conf_compound1 Compound assignments (one key definitions)
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a.b 1
Packit 4a16fb
a.b=1
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\subsection conf_array Array assignments (definitions using brackets)
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a [
Packit 4a16fb
  "first"
Packit 4a16fb
  "second"
Packit 4a16fb
]
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\subsection conf_array1 Array assignments (one key definitions)
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
a.0 "first"
Packit 4a16fb
a.1 "second"
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section conf_mode Operation modes for parsing nodes
Packit 4a16fb
Packit 4a16fb
By default, the node operation mode is 'merge+create', i.e., if
Packit 4a16fb
a configuration node is not present a new one is created, otherwise
Packit 4a16fb
the latest assignment is merged (if possible - type checking). The
Packit 4a16fb
'merge+create' operation mode is specified with the prefix character plus (+).
Packit 4a16fb
Packit 4a16fb
The operation mode 'merge' merges the node with the old one (which must
Packit 4a16fb
exist). Type checking is done, so strings cannot be assigned to integers
Packit 4a16fb
and so on. This mode is specified with the prefix character minus (-).
Packit 4a16fb
Packit 4a16fb
The operation mode 'do not override' ignores a new configuration node
Packit 4a16fb
if a configuration node with the same name exists. This mode is specified with
Packit 4a16fb
the prefix character question mark (?).
Packit 4a16fb
Packit 4a16fb
The operation mode 'override' always overrides the old configuration node
Packit 4a16fb
with new contents. This mode is specified with the prefix character
Packit 4a16fb
exclamation mark (!).
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
defaults.pcm.!device 1
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section conf_syntax_summary Syntax summary
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
# Configuration file syntax
Packit 4a16fb
Packit 4a16fb
# Include a new configuration file
Packit 4a16fb
<filename>
Packit 4a16fb
Packit 4a16fb
# Simple assignment
Packit 4a16fb
name [=] value [,|;]
Packit 4a16fb
Packit 4a16fb
# Compound assignment (first style)
Packit 4a16fb
name [=] {
Packit 4a16fb
        name1 [=] value [,|;]
Packit 4a16fb
        ...
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
# Compound assignment (second style)
Packit 4a16fb
name.name1 [=] value [,|;]
Packit 4a16fb
Packit 4a16fb
# Array assignment (first style)
Packit 4a16fb
name [
Packit 4a16fb
        value0 [,|;]
Packit 4a16fb
        value1 [,|;]
Packit 4a16fb
        ...
Packit 4a16fb
]
Packit 4a16fb
Packit 4a16fb
# Array assignment (second style)
Packit 4a16fb
name.0 [=] value0 [,|;]
Packit 4a16fb
name.1 [=] value1 [,|;]
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section conf_syntax_ref References
Packit 4a16fb
Packit 4a16fb
\ref confarg
Packit 4a16fb
\ref conffunc
Packit 4a16fb
\ref confhooks
Packit 4a16fb
Packit 4a16fb
*/
Packit 4a16fb
Packit 4a16fb
/*! \page confarg Runtime arguments in configuration files
Packit 4a16fb
Packit 4a16fb

The ALSA library can accept runtime arguments for some configuration

Packit 4a16fb
blocks. This extension is built on top of the basic configuration file
Packit 4a16fb
syntax.

Packit 4a16fb
Packit 4a16fb
\section confarg_define Defining arguments
Packit 4a16fb
Packit 4a16fb
Arguments are defined using the id (key) \c \@args and array values containing
Packit 4a16fb
the string names of the arguments:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
@args [ CARD ]	# or
Packit 4a16fb
@args.0 CARD
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section confarg_type Defining argument types and default values
Packit 4a16fb
Packit 4a16fb
An argument's type is specified with the id (key) \c \@args and the argument
Packit 4a16fb
name. The type and the default value are specified in the compound block:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
@args.CARD {
Packit 4a16fb
  type string
Packit 4a16fb
  default "abcd"
Packit 4a16fb
}
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section confarg_refer Referring to arguments
Packit 4a16fb
Packit 4a16fb
Arguments are referred to with a dollar-sign ($) and the name of the argument:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
  card $CARD
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section confarg_usage Usage
Packit 4a16fb
Packit 4a16fb
To use a block with arguments, write the argument values after the key,
Packit 4a16fb
separated with a colon (:). For example, all these names for PCM interfaces
Packit 4a16fb
give the same result:
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
hw:0,1
Packit 4a16fb
hw:CARD=0,DEV=1
Packit 4a16fb
hw:{CARD 0 DEV 1}
Packit 4a16fb
plug:"hw:0,1"
Packit 4a16fb
plug:{SLAVE="hw:{CARD 0 DEV 1}"}
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
As you see, arguments can be specified in their proper order or by name.
Packit 4a16fb
Note that arguments enclosed in braces are parsed in the same way as in
Packit 4a16fb
configuration files, but using the override method by default.
Packit 4a16fb
Packit 4a16fb
\section confarg_example Example
Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
pcm.demo {
Packit 4a16fb
	@args [ CARD DEVICE ]
Packit 4a16fb
	@args.CARD {
Packit 4a16fb
		type string
Packit 4a16fb
		default "supersonic"
Packit 4a16fb
	}
Packit 4a16fb
	@args.DEVICE {
Packit 4a16fb
		type integer
Packit 4a16fb
		default 0
Packit 4a16fb
	}
Packit 4a16fb
	type hw
Packit 4a16fb
	card $CARD
Packit 4a16fb
	device $DEVICE
Packit 4a16fb
}
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
*/
Packit 4a16fb
Packit 4a16fb
/*! \page conffunc Runtime functions in configuration files
Packit 4a16fb
Packit 4a16fb

The ALSA library can modify the configuration at runtime.

Packit 4a16fb
Several built-in functions are available.

Packit 4a16fb
Packit 4a16fb

A function is defined with the id \c \@func and the function name. All other

Packit 4a16fb
values in the current compound are used as configuration for the function.
Packit 4a16fb
If the compound func.\<function_name\> is defined in the root node, then the
Packit 4a16fb
library and function from this compound configuration are used, otherwise
Packit 4a16fb
'snd_func_' is prefixed to the string and code from the ALSA library is used.
Packit 4a16fb
The definition of a function looks like:

Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
func.remove_first_char {
Packit 4a16fb
	lib "/usr/lib/libasoundextend.so"
Packit 4a16fb
	func "extend_remove_first_char"
Packit 4a16fb
}
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
*/
Packit 4a16fb
Packit 4a16fb
/*! \page confhooks Hooks in configuration files
Packit 4a16fb
Packit 4a16fb

The hook extension in the ALSA library allows expansion of configuration

Packit 4a16fb
nodes at run-time. The existence of a hook is determined by the
Packit 4a16fb
presence of a \@hooks compound node.

Packit 4a16fb
Packit 4a16fb

This example defines a hook which loads two configuration files at the

Packit 4a16fb
beginning:

Packit 4a16fb
Packit 4a16fb
\code
Packit 4a16fb
@hooks [
Packit 4a16fb
	{
Packit 4a16fb
		func load
Packit 4a16fb
		files [
Packit 4a16fb
			"/etc/asound.conf"
Packit 4a16fb
			"~/.asoundrc"
Packit 4a16fb
		]
Packit 4a16fb
		errors false
Packit 4a16fb
	}
Packit 4a16fb
]
Packit 4a16fb
\endcode
Packit 4a16fb
Packit 4a16fb
\section confhooks_ref Function reference
Packit 4a16fb
Packit 4a16fb
    Packit 4a16fb
      
  • The function load - \c snd_config_hook_load() - loads and parses the
  • Packit 4a16fb
          given configuration files.
    Packit 4a16fb
      
  • The function load_for_all_cards - \c snd_config_hook_load_for_all_cards() -
  • Packit 4a16fb
          loads and parses the given configuration files for each installed sound
    Packit 4a16fb
          card. The driver name (the type of the sound card) is passed in the
    Packit 4a16fb
          private configuration node.
    Packit 4a16fb
    Packit 4a16fb
    Packit 4a16fb
    */
    Packit 4a16fb
    Packit 4a16fb
    Packit 4a16fb
    #include "local.h"
    Packit 4a16fb
    #include <stdarg.h>
    Packit Service f36a15
    #include <stdbool.h>
    Packit 4a16fb
    #include <limits.h>
    Packit 4a16fb
    #include <sys/stat.h>
    Packit 4a16fb
    #include <dirent.h>
    Packit 4a16fb
    #include <locale.h>
    Packit 4a16fb
    #ifdef HAVE_LIBPTHREAD
    Packit 4a16fb
    #include <pthread.h>
    Packit 4a16fb
    #endif
    Packit 4a16fb
    Packit 4a16fb
    #ifndef DOC_HIDDEN
    Packit 4a16fb
    Packit 4a16fb
    #ifdef HAVE_LIBPTHREAD
    Packit 4a16fb
    static pthread_mutex_t snd_config_update_mutex;
    Packit 4a16fb
    static pthread_once_t snd_config_update_mutex_once = PTHREAD_ONCE_INIT;
    Packit 4a16fb
    #endif
    Packit 4a16fb
    Packit 4a16fb
    struct _snd_config {
    Packit 4a16fb
    	char *id;
    Packit 4a16fb
    	snd_config_type_t type;
    Packit 4a16fb
    	int refcount; /* default = 0 */
    Packit 4a16fb
    	union {
    Packit 4a16fb
    		long integer;
    Packit 4a16fb
    		long long integer64;
    Packit 4a16fb
    		char *string;
    Packit 4a16fb
    		double real;
    Packit 4a16fb
    		const void *ptr;
    Packit 4a16fb
    		struct {
    Packit 4a16fb
    			struct list_head fields;
    Packit Service f36a15
    			bool join;
    Packit 4a16fb
    		} compound;
    Packit 4a16fb
    	} u;
    Packit 4a16fb
    	struct list_head list;
    Packit 4a16fb
    	snd_config_t *parent;
    Packit 4a16fb
    	int hop;
    Packit 4a16fb
    };
    Packit 4a16fb
    Packit 4a16fb
    struct filedesc {
    Packit 4a16fb
    	char *name;
    Packit 4a16fb
    	snd_input_t *in;
    Packit 4a16fb
    	unsigned int line, column;
    Packit 4a16fb
    	struct filedesc *next;
    Packit 4a16fb
    Packit 4a16fb
    	/* list of the include paths (configuration directories),
    Packit 4a16fb
    	 * defined by <searchdir:relative-path/to/top-alsa-conf-dir>,
    Packit 4a16fb
    	 * for searching its included files.
    Packit 4a16fb
    	 */
    Packit 4a16fb
    	struct list_head include_paths;
    Packit 4a16fb
    };
    Packit 4a16fb
    Packit 4a16fb
    /* path to search included files */
    Packit 4a16fb
    struct include_path {
    Packit 4a16fb
    	char *dir;
    Packit 4a16fb
    	struct list_head list;
    Packit 4a16fb
    };
    Packit 4a16fb
    Packit 4a16fb
    #define LOCAL_ERROR			(-0x68000000)
    Packit 4a16fb
    Packit 4a16fb
    #define LOCAL_UNTERMINATED_STRING 	(LOCAL_ERROR - 0)
    Packit 4a16fb
    #define LOCAL_UNTERMINATED_QUOTE	(LOCAL_ERROR - 1)
    Packit 4a16fb
    #define LOCAL_UNEXPECTED_CHAR		(LOCAL_ERROR - 2)
    Packit 4a16fb
    #define LOCAL_UNEXPECTED_EOF		(LOCAL_ERROR - 3)
    Packit 4a16fb
    Packit 4a16fb
    typedef struct {
    Packit 4a16fb
    	struct filedesc *current;
    Packit 4a16fb
    	int unget;
    Packit 4a16fb
    	int ch;
    Packit 4a16fb
    } input_t;
    Packit 4a16fb
    Packit 4a16fb
    #ifdef HAVE_LIBPTHREAD
    Packit 4a16fb
    Packit 4a16fb
    static void snd_config_init_mutex(void)
    Packit 4a16fb
    {
    Packit 4a16fb
    	pthread_mutexattr_t attr;
    Packit 4a16fb
    Packit 4a16fb
    	pthread_mutexattr_init(&attr);
    Packit 4a16fb
    #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE
    Packit 4a16fb
    	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    Packit 4a16fb
    #endif
    Packit 4a16fb
    	pthread_mutex_init(&snd_config_update_mutex, &attr);
    Packit 4a16fb
    	pthread_mutexattr_destroy(&attr);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static inline void snd_config_lock(void)
    Packit 4a16fb
    {
    Packit 4a16fb
    	pthread_once(&snd_config_update_mutex_once, snd_config_init_mutex);
    Packit 4a16fb
    	pthread_mutex_lock(&snd_config_update_mutex);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static inline void snd_config_unlock(void)
    Packit 4a16fb
    {
    Packit 4a16fb
    	pthread_mutex_unlock(&snd_config_update_mutex);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    #else
    Packit 4a16fb
    Packit 4a16fb
    static inline void snd_config_lock(void) { }
    Packit 4a16fb
    static inline void snd_config_unlock(void) { }
    Packit 4a16fb
    Packit 4a16fb
    #endif
    Packit 4a16fb
    Packit 4a16fb
    /*
    Packit 4a16fb
     * Add a diretory to the paths to search included files.
    Packit 4a16fb
     * param fd -  File object that owns these paths to search files included by it.
    Packit 4a16fb
     * param dir - Path of the directory to add. Allocated externally and need to
    Packit 4a16fb
    *              be freed manually later.
    Packit 4a16fb
     * return - Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The direcotry should be a subdiretory of top configuration directory
    Packit 4a16fb
     * "/usr/share/alsa/".
    Packit 4a16fb
     */
    Packit 4a16fb
    static int add_include_path(struct filedesc *fd, const char *dir)
    Packit 4a16fb
    {
    Packit 4a16fb
    	struct include_path *path;
    Packit 4a16fb
    	struct filedesc *fd1;
    Packit 4a16fb
    	struct list_head *pos;
    Packit 4a16fb
    Packit 4a16fb
    	/* check, if dir is already registered (also in parents) */
    Packit 4a16fb
    	for (fd1 = fd; fd1; fd1 = fd1->next) {
    Packit 4a16fb
    		list_for_each(pos, &fd1->include_paths) {
    Packit 4a16fb
    			path = list_entry(pos, struct include_path, list);
    Packit 4a16fb
    			if (strcmp(path->dir, dir) == 0)
    Packit 4a16fb
    				return 0;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	}
    Packit 4a16fb
    Packit 4a16fb
    	path = calloc(1, sizeof(*path));
    Packit 4a16fb
    	if (!path)
    Packit 4a16fb
    		return -ENOMEM;
    Packit 4a16fb
    Packit 4a16fb
    	path->dir = strdup(dir);
    Packit 4a16fb
    	if (path->dir == NULL) {
    Packit 4a16fb
    		free(path);
    Packit 4a16fb
    		return -ENOMEM;
    Packit 4a16fb
    	}
    Packit 4a16fb
    Packit 4a16fb
    	list_add_tail(&path->list, &fd->include_paths);
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /*
    Packit 4a16fb
     * Free all include paths of a file descriptor.
    Packit 4a16fb
     * param fd - File object that owns these paths to search files included by it.
    Packit 4a16fb
     */
    Packit 4a16fb
    static void free_include_paths(struct filedesc *fd)
    Packit 4a16fb
    {
    Packit 4a16fb
    	struct list_head *pos, *npos, *base;
    Packit 4a16fb
    	struct include_path *path;
    Packit 4a16fb
    Packit 4a16fb
    	base = &fd->include_paths;
    Packit 4a16fb
    	list_for_each_safe(pos, npos, base) {
    Packit 4a16fb
    		path = list_entry(pos, struct include_path, list);
    Packit 4a16fb
    		list_del(&path->list);
    Packit 4a16fb
    		if (path->dir)
    Packit 4a16fb
    			free(path->dir);
    Packit 4a16fb
    		free(path);
    Packit 4a16fb
    	}
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the default top-level config directory
    Packit 4a16fb
     * \return The top-level config directory path string
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function returns the string of the top-level config directory path.
    Packit 4a16fb
     * If the path is specified via the environment variable \c ALSA_CONFIG_DIR
    Packit 4a16fb
     * and the value is a valid path, it returns this value.  If unspecified, it
    Packit 4a16fb
     * returns the default value, "/usr/share/alsa".
    Packit 4a16fb
     */
    Packit 4a16fb
    const char *snd_config_topdir(void)
    Packit 4a16fb
    {
    Packit 4a16fb
    	static char *topdir;
    Packit 4a16fb
    Packit 4a16fb
    	if (!topdir) {
    Packit 4a16fb
    		topdir = getenv("ALSA_CONFIG_DIR");
    Packit 4a16fb
    		if (!topdir || *topdir != '/' || strlen(topdir) >= PATH_MAX)
    Packit 4a16fb
    			topdir = ALSA_CONFIG_DIR;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return topdir;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static char *_snd_config_path(const char *name)
    Packit 4a16fb
    {
    Packit 4a16fb
    	const char *root = snd_config_topdir();
    Packit 4a16fb
    	char *path = malloc(strlen(root) + strlen(name) + 2);
    Packit 4a16fb
    	if (!path)
    Packit 4a16fb
    		return NULL;
    Packit 4a16fb
    	sprintf(path, "%s/%s", root, name);
    Packit 4a16fb
    	return path;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /*
    Packit 4a16fb
     * Search and open a file, and creates a new input object reading from the file.
    Packit 4a16fb
     * param inputp - The functions puts the pointer to the new input object
    Packit 4a16fb
     *               at the address specified by \p inputp.
    Packit 4a16fb
     * param file - Name of the configuration file.
    Packit 4a16fb
     * param include_paths - Optional, addtional directories to search the file.
    Packit 4a16fb
     * return - Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function will search and open the file in the following order
    Packit 4a16fb
     * of priority:
    Packit 4a16fb
     * 1. directly open the file by its name (only if absolute)
    Packit 4a16fb
     * 2. search for the file name in in additional configuration directories
    Packit 4a16fb
     *    specified by users, via alsaconf syntax
    Packit 4a16fb
     *    <searchdir:relative-path/to/user/share/alsa>;
    Packit 4a16fb
     *    These directories should be subdirectories of /usr/share/alsa.
    Packit 4a16fb
     */
    Packit 4a16fb
    static int input_stdio_open(snd_input_t **inputp, const char *file,
    Packit 4a16fb
    			    struct filedesc *current)
    Packit 4a16fb
    {
    Packit 4a16fb
    	struct list_head *pos;
    Packit 4a16fb
    	struct include_path *path;
    Packit 4a16fb
    	char full_path[PATH_MAX];
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    Packit 4a16fb
    	if (file[0] == '/')
    Packit 4a16fb
    		return snd_input_stdio_open(inputp, file, "r");
    Packit 4a16fb
    Packit 4a16fb
    	/* search file in user specified include paths. These directories
    Packit 4a16fb
    	 * are subdirectories of /usr/share/alsa.
    Packit 4a16fb
    	 */
    Packit 4a16fb
    	err = -ENOENT;
    Packit 4a16fb
    	while (current) {
    Packit 4a16fb
    		list_for_each(pos, &current->include_paths) {
    Packit 4a16fb
    			path = list_entry(pos, struct include_path, list);
    Packit 4a16fb
    			if (!path->dir)
    Packit 4a16fb
    				continue;
    Packit 4a16fb
    Packit 4a16fb
    			snprintf(full_path, PATH_MAX, "%s/%s", path->dir, file);
    Packit 4a16fb
    			err = snd_input_stdio_open(inputp, full_path, "r");
    Packit 4a16fb
    			if (err == 0)
    Packit 4a16fb
    				return 0;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		current = current->next;
    Packit 4a16fb
    	}
    Packit 4a16fb
    Packit 4a16fb
    	return err;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int safe_strtoll(const char *str, long long *val)
    Packit 4a16fb
    {
    Packit 4a16fb
    	long long v;
    Packit 4a16fb
    	int endidx;
    Packit 4a16fb
    	if (!*str)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	errno = 0;
    Packit 4a16fb
    	if (sscanf(str, "%lli%n", &v, &endidx) < 1)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	if (str[endidx])
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	*val = v;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    int safe_strtol(const char *str, long *val)
    Packit 4a16fb
    {
    Packit 4a16fb
    	char *end;
    Packit 4a16fb
    	long v;
    Packit 4a16fb
    	if (!*str)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	errno = 0;
    Packit 4a16fb
    	v = strtol(str, &end, 0);
    Packit 4a16fb
    	if (errno)
    Packit 4a16fb
    		return -errno;
    Packit 4a16fb
    	if (*end)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	*val = v;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int safe_strtod(const char *str, double *val)
    Packit 4a16fb
    {
    Packit 4a16fb
    	char *end;
    Packit 4a16fb
    	double v;
    Packit 4a16fb
    #ifdef HAVE_USELOCALE
    Packit 4a16fb
    	locale_t saved_locale, c_locale;
    Packit 4a16fb
    #else
    Packit 4a16fb
    	char *saved_locale;
    Packit 4a16fb
    	char locstr[64]; /* enough? */
    Packit 4a16fb
    #endif
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    Packit 4a16fb
    	if (!*str)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    #ifdef HAVE_USELOCALE
    Packit 4a16fb
    	c_locale = newlocale(LC_NUMERIC_MASK, "C", 0);
    Packit 4a16fb
    	saved_locale = uselocale(c_locale);
    Packit 4a16fb
    #else
    Packit 4a16fb
    	saved_locale = setlocale(LC_NUMERIC, NULL);
    Packit 4a16fb
    	if (saved_locale) {
    Packit 4a16fb
    		snprintf(locstr, sizeof(locstr), "%s", saved_locale);
    Packit 4a16fb
    		setlocale(LC_NUMERIC, "C");
    Packit 4a16fb
    	}
    Packit 4a16fb
    #endif
    Packit 4a16fb
    	errno = 0;
    Packit 4a16fb
    	v = strtod(str, &end;;
    Packit 4a16fb
    	err = -errno;
    Packit 4a16fb
    #ifdef HAVE_USELOCALE
    Packit 4a16fb
    	if (c_locale != (locale_t)0) {
    Packit 4a16fb
    		uselocale(saved_locale);
    Packit 4a16fb
    		freelocale(c_locale);
    Packit 4a16fb
    	}
    Packit 4a16fb
    #else
    Packit 4a16fb
    	if (saved_locale)
    Packit 4a16fb
    		setlocale(LC_NUMERIC, locstr);
    Packit 4a16fb
    #endif
    Packit 4a16fb
    	if (err)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	if (*end)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	*val = v;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int get_char(input_t *input)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int c;
    Packit 4a16fb
    	struct filedesc *fd;
    Packit 4a16fb
    	if (input->unget) {
    Packit 4a16fb
    		input->unget = 0;
    Packit 4a16fb
    		return input->ch;
    Packit 4a16fb
    	}
    Packit 4a16fb
     again:
    Packit 4a16fb
    	fd = input->current;
    Packit 4a16fb
    	c = snd_input_getc(fd->in);
    Packit 4a16fb
    	switch (c) {
    Packit 4a16fb
    	case '\n':
    Packit 4a16fb
    		fd->column = 0;
    Packit 4a16fb
    		fd->line++;
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case '\t':
    Packit 4a16fb
    		fd->column += 8 - fd->column % 8;
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case EOF:
    Packit 4a16fb
    		if (fd->next) {
    Packit 4a16fb
    			snd_input_close(fd->in);
    Packit 4a16fb
    			free(fd->name);
    Packit 4a16fb
    			input->current = fd->next;
    Packit 4a16fb
    			free(fd);
    Packit 4a16fb
    			goto again;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		return LOCAL_UNEXPECTED_EOF;
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		fd->column++;
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return (unsigned char)c;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static void unget_char(int c, input_t *input)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(!input->unget);
    Packit 4a16fb
    	input->ch = c;
    Packit 4a16fb
    	input->unget = 1;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int get_delimstring(char **string, int delim, input_t *input);
    Packit 4a16fb
    Packit 4a16fb
    static int get_char_skip_comments(input_t *input)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int c;
    Packit 4a16fb
    	while (1) {
    Packit 4a16fb
    		c = get_char(input);
    Packit 4a16fb
    		if (c == '<') {
    Packit 4a16fb
    			char *str;
    Packit 4a16fb
    			snd_input_t *in;
    Packit 4a16fb
    			struct filedesc *fd;
    Packit 4a16fb
    			DIR *dirp;
    Packit 4a16fb
    			int err = get_delimstring(&str, '>', input);
    Packit 4a16fb
    			if (err < 0)
    Packit 4a16fb
    				return err;
    Packit 4a16fb
    Packit 4a16fb
    			if (!strncmp(str, "searchdir:", 10)) {
    Packit 4a16fb
    				/* directory to search included files */
    Packit 4a16fb
    				char *tmp = _snd_config_path(str + 10);
    Packit 4a16fb
    				free(str);
    Packit 4a16fb
    				if (tmp == NULL)
    Packit 4a16fb
    					return -ENOMEM;
    Packit 4a16fb
    				str = tmp;
    Packit 4a16fb
    Packit 4a16fb
    				dirp = opendir(str);
    Packit 4a16fb
    				if (!dirp) {
    Packit 4a16fb
    					SNDERR("Invalid search dir %s", str);
    Packit 4a16fb
    					free(str);
    Packit 4a16fb
    					return -EINVAL;
    Packit 4a16fb
    				}
    Packit 4a16fb
    				closedir(dirp);
    Packit 4a16fb
    Packit 4a16fb
    				err = add_include_path(input->current, str);
    Packit 4a16fb
    				free(str);
    Packit 4a16fb
    				if (err < 0) {
    Packit 4a16fb
    					SNDERR("Cannot add search dir %s", str);
    Packit 4a16fb
    					return err;
    Packit 4a16fb
    				}
    Packit 4a16fb
    				continue;
    Packit 4a16fb
    			}
    Packit 4a16fb
    Packit 4a16fb
    			if (!strncmp(str, "confdir:", 8)) {
    Packit 4a16fb
    				/* file in the specified directory */
    Packit 4a16fb
    				char *tmp = _snd_config_path(str + 8);
    Packit 4a16fb
    				free(str);
    Packit 4a16fb
    				if (tmp == NULL)
    Packit 4a16fb
    					return -ENOMEM;
    Packit 4a16fb
    				str = tmp;
    Packit 4a16fb
    				err = snd_input_stdio_open(&in, str, "r");
    Packit 4a16fb
    			} else { /* absolute or relative file path */
    Packit 4a16fb
    				err = input_stdio_open(&in, str, input->current);
    Packit 4a16fb
    			}
    Packit 4a16fb
    Packit 4a16fb
    			if (err < 0) {
    Packit 4a16fb
    				SNDERR("Cannot access file %s", str);
    Packit 4a16fb
    				free(str);
    Packit 4a16fb
    				return err;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			fd = malloc(sizeof(*fd));
    Packit 4a16fb
    			if (!fd) {
    Packit 4a16fb
    				free(str);
    Packit 4a16fb
    				return -ENOMEM;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			fd->name = str;
    Packit 4a16fb
    			fd->in = in;
    Packit 4a16fb
    			fd->next = input->current;
    Packit 4a16fb
    			fd->line = 1;
    Packit 4a16fb
    			fd->column = 0;
    Packit 4a16fb
    			INIT_LIST_HEAD(&fd->include_paths);
    Packit 4a16fb
    			input->current = fd;
    Packit 4a16fb
    			continue;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		if (c != '#')
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		while (1) {
    Packit 4a16fb
    			c = get_char(input);
    Packit 4a16fb
    			if (c < 0)
    Packit 4a16fb
    				return c;
    Packit 4a16fb
    			if (c == '\n')
    Packit 4a16fb
    				break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	}
    Packit 4a16fb
    		
    Packit 4a16fb
    	return c;
    Packit 4a16fb
    }
    Packit 4a16fb
    			
    Packit 4a16fb
    Packit 4a16fb
    static int get_nonwhite(input_t *input)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int c;
    Packit 4a16fb
    	while (1) {
    Packit 4a16fb
    		c = get_char_skip_comments(input);
    Packit 4a16fb
    		switch (c) {
    Packit 4a16fb
    		case ' ':
    Packit 4a16fb
    		case '\f':
    Packit 4a16fb
    		case '\t':
    Packit 4a16fb
    		case '\n':
    Packit 4a16fb
    		case '\r':
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		default:
    Packit 4a16fb
    			return c;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	}
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit Service f36a15
    static inline int get_hexachar(input_t *input)
    Packit Service f36a15
    {
    Packit Service f36a15
    	int c, num = 0;
    Packit Service f36a15
    Packit Service f36a15
    	c = get_char(input);
    Packit Service f36a15
    	if (c >= '0' && c <= '9') num |= (c - '0') << 4;
    Packit Service f36a15
    	else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 4;
    Packit Service f36a15
    	else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 4;
    Packit Service f36a15
    	c = get_char(input);
    Packit Service f36a15
    	if (c >= '0' && c <= '9') num |= (c - '0') << 0;
    Packit Service f36a15
    	else if (c >= 'a' && c <= 'f') num |= (c - 'a') << 0;
    Packit Service f36a15
    	else if (c >= 'A' && c <= 'F') num |= (c - 'A') << 0;
    Packit Service f36a15
    	return c;
    Packit Service f36a15
    }
    Packit Service f36a15
    Packit 4a16fb
    static int get_quotedchar(input_t *input)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int c;
    Packit 4a16fb
    	c = get_char(input);
    Packit 4a16fb
    	switch (c) {
    Packit 4a16fb
    	case 'n':
    Packit 4a16fb
    		return '\n';
    Packit 4a16fb
    	case 't':
    Packit 4a16fb
    		return '\t';
    Packit 4a16fb
    	case 'v':
    Packit 4a16fb
    		return '\v';
    Packit 4a16fb
    	case 'b':
    Packit 4a16fb
    		return '\b';
    Packit 4a16fb
    	case 'r':
    Packit 4a16fb
    		return '\r';
    Packit 4a16fb
    	case 'f':
    Packit 4a16fb
    		return '\f';
    Packit Service f36a15
    	case 'x':
    Packit Service f36a15
    		return get_hexachar(input);
    Packit 4a16fb
    	case '0': case '1': case '2': case '3':
    Packit 4a16fb
    	case '4': case '5': case '6': case '7':
    Packit 4a16fb
    	{
    Packit 4a16fb
    		int num = c - '0';
    Packit 4a16fb
    		int i = 1;
    Packit 4a16fb
    		do {
    Packit 4a16fb
    			c = get_char(input);
    Packit 4a16fb
    			if (c < '0' || c > '7') {
    Packit 4a16fb
    				unget_char(c, input);
    Packit 4a16fb
    				break;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			num = num * 8 + c - '0';
    Packit 4a16fb
    			i++;
    Packit 4a16fb
    		} while (i < 3);
    Packit 4a16fb
    		return num;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		return c;
    Packit 4a16fb
    	}
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    #define LOCAL_STR_BUFSIZE	64
    Packit 4a16fb
    struct local_string {
    Packit 4a16fb
    	char *buf;
    Packit 4a16fb
    	size_t alloc;
    Packit 4a16fb
    	size_t idx;
    Packit 4a16fb
    	char tmpbuf[LOCAL_STR_BUFSIZE];
    Packit 4a16fb
    };
    Packit 4a16fb
    Packit 4a16fb
    static void init_local_string(struct local_string *s)
    Packit 4a16fb
    {
    Packit 4a16fb
    	memset(s, 0, sizeof(*s));
    Packit 4a16fb
    	s->buf = s->tmpbuf;
    Packit 4a16fb
    	s->alloc = LOCAL_STR_BUFSIZE;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static void free_local_string(struct local_string *s)
    Packit 4a16fb
    {
    Packit 4a16fb
    	if (s->buf != s->tmpbuf)
    Packit 4a16fb
    		free(s->buf);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int add_char_local_string(struct local_string *s, int c)
    Packit 4a16fb
    {
    Packit 4a16fb
    	if (s->idx >= s->alloc) {
    Packit 4a16fb
    		size_t nalloc = s->alloc * 2;
    Packit 4a16fb
    		if (s->buf == s->tmpbuf) {
    Packit 4a16fb
    			s->buf = malloc(nalloc);
    Packit 4a16fb
    			if (s->buf == NULL)
    Packit 4a16fb
    				return -ENOMEM;
    Packit 4a16fb
    			memcpy(s->buf, s->tmpbuf, s->alloc);
    Packit 4a16fb
    		} else {
    Packit 4a16fb
    			char *ptr = realloc(s->buf, nalloc);
    Packit 4a16fb
    			if (ptr == NULL)
    Packit 4a16fb
    				return -ENOMEM;
    Packit 4a16fb
    			s->buf = ptr;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		s->alloc = nalloc;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	s->buf[s->idx++] = c;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static char *copy_local_string(struct local_string *s)
    Packit 4a16fb
    {
    Packit 4a16fb
    	char *dst = malloc(s->idx + 1);
    Packit 4a16fb
    	if (dst) {
    Packit 4a16fb
    		memcpy(dst, s->buf, s->idx);
    Packit 4a16fb
    		dst[s->idx] = '\0';
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return dst;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int get_freestring(char **string, int id, input_t *input)
    Packit 4a16fb
    {
    Packit 4a16fb
    	struct local_string str;
    Packit 4a16fb
    	int c;
    Packit 4a16fb
    Packit 4a16fb
    	init_local_string(&str);
    Packit 4a16fb
    	while (1) {
    Packit 4a16fb
    		c = get_char(input);
    Packit 4a16fb
    		if (c < 0) {
    Packit 4a16fb
    			if (c == LOCAL_UNEXPECTED_EOF) {
    Packit 4a16fb
    				*string = copy_local_string(&str);
    Packit 4a16fb
    				if (! *string)
    Packit 4a16fb
    					c = -ENOMEM;
    Packit 4a16fb
    				else
    Packit 4a16fb
    					c = 0;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		switch (c) {
    Packit 4a16fb
    		case '.':
    Packit 4a16fb
    			if (!id)
    Packit 4a16fb
    				break;
    Packit 4a16fb
    			/* fall through */
    Packit 4a16fb
    		case ' ':
    Packit 4a16fb
    		case '\f':
    Packit 4a16fb
    		case '\t':
    Packit 4a16fb
    		case '\n':
    Packit 4a16fb
    		case '\r':
    Packit 4a16fb
    		case '=':
    Packit 4a16fb
    		case ',':
    Packit 4a16fb
    		case ';':
    Packit 4a16fb
    		case '{':
    Packit 4a16fb
    		case '}':
    Packit 4a16fb
    		case '[':
    Packit 4a16fb
    		case ']':
    Packit 4a16fb
    		case '\'':
    Packit 4a16fb
    		case '"':
    Packit 4a16fb
    		case '\\':
    Packit 4a16fb
    		case '#':
    Packit 4a16fb
    			*string = copy_local_string(&str);
    Packit 4a16fb
    			if (! *string)
    Packit 4a16fb
    				c = -ENOMEM;
    Packit 4a16fb
    			else {
    Packit 4a16fb
    				unget_char(c, input);
    Packit 4a16fb
    				c = 0;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			goto _out;
    Packit 4a16fb
    		default:
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		if (add_char_local_string(&str, c) < 0) {
    Packit 4a16fb
    			c = -ENOMEM;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	}
    Packit 4a16fb
     _out:
    Packit 4a16fb
    	free_local_string(&str);
    Packit 4a16fb
    	return c;
    Packit 4a16fb
    }
    Packit 4a16fb
    			
    Packit 4a16fb
    static int get_delimstring(char **string, int delim, input_t *input)
    Packit 4a16fb
    {
    Packit 4a16fb
    	struct local_string str;
    Packit 4a16fb
    	int c;
    Packit 4a16fb
    Packit 4a16fb
    	init_local_string(&str);
    Packit 4a16fb
    	while (1) {
    Packit 4a16fb
    		c = get_char(input);
    Packit 4a16fb
    		if (c < 0)
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		if (c == '\\') {
    Packit 4a16fb
    			c = get_quotedchar(input);
    Packit 4a16fb
    			if (c < 0)
    Packit 4a16fb
    				break;
    Packit 4a16fb
    			if (c == '\n')
    Packit 4a16fb
    				continue;
    Packit 4a16fb
    		} else if (c == delim) {
    Packit 4a16fb
    			*string = copy_local_string(&str);
    Packit 4a16fb
    			if (! *string)
    Packit 4a16fb
    				c = -ENOMEM;
    Packit 4a16fb
    			else
    Packit 4a16fb
    				c = 0;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		if (add_char_local_string(&str, c) < 0) {
    Packit 4a16fb
    			c = -ENOMEM;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	}
    Packit 4a16fb
    	 free_local_string(&str);
    Packit 4a16fb
    	 return c;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /* Return 0 for free string, 1 for delimited string */
    Packit 4a16fb
    static int get_string(char **string, int id, input_t *input)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int c = get_nonwhite(input), err;
    Packit 4a16fb
    	if (c < 0)
    Packit 4a16fb
    		return c;
    Packit 4a16fb
    	switch (c) {
    Packit 4a16fb
    	case '=':
    Packit 4a16fb
    	case ',':
    Packit 4a16fb
    	case ';':
    Packit 4a16fb
    	case '.':
    Packit 4a16fb
    	case '{':
    Packit 4a16fb
    	case '}':
    Packit 4a16fb
    	case '[':
    Packit 4a16fb
    	case ']':
    Packit 4a16fb
    	case '\\':
    Packit 4a16fb
    		return LOCAL_UNEXPECTED_CHAR;
    Packit 4a16fb
    	case '\'':
    Packit 4a16fb
    	case '"':
    Packit 4a16fb
    		err = get_delimstring(string, c, input);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    		return 1;
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		unget_char(c, input);
    Packit 4a16fb
    		err = get_freestring(string, id, input);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
    Packit 4a16fb
    {
    Packit 4a16fb
    	snd_config_t *n;
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	n = calloc(1, sizeof(*n));
    Packit 4a16fb
    	if (n == NULL) {
    Packit 4a16fb
    		if (*id) {
    Packit 4a16fb
    			free(*id);
    Packit 4a16fb
    			*id = NULL;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		return -ENOMEM;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (id) {
    Packit 4a16fb
    		n->id = *id;
    Packit 4a16fb
    		*id = NULL;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	n->type = type;
    Packit 4a16fb
    	if (type == SND_CONFIG_TYPE_COMPOUND)
    Packit 4a16fb
    		INIT_LIST_HEAD(&n->u.compound.fields);
    Packit 4a16fb
    	*config = n;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    	
    Packit 4a16fb
    Packit 4a16fb
    static int _snd_config_make_add(snd_config_t **config, char **id,
    Packit 4a16fb
    				snd_config_type_t type, snd_config_t *parent)
    Packit 4a16fb
    {
    Packit 4a16fb
    	snd_config_t *n;
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	assert(parent->type == SND_CONFIG_TYPE_COMPOUND);
    Packit 4a16fb
    	err = _snd_config_make(&n, id, type);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	n->parent = parent;
    Packit 4a16fb
    	list_add_tail(&n->list, &parent->u.compound.fields);
    Packit 4a16fb
    	*config = n;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int _snd_config_search(snd_config_t *config, 
    Packit 4a16fb
    			      const char *id, int len, snd_config_t **result)
    Packit 4a16fb
    {
    Packit 4a16fb
    	snd_config_iterator_t i, next;
    Packit 4a16fb
    	snd_config_for_each(i, next, config) {
    Packit 4a16fb
    		snd_config_t *n = snd_config_iterator_entry(i);
    Packit 4a16fb
    		if (len < 0) {
    Packit 4a16fb
    			if (strcmp(n->id, id) != 0)
    Packit 4a16fb
    				continue;
    Packit 4a16fb
    		} else if (strlen(n->id) != (size_t) len ||
    Packit 4a16fb
    			   memcmp(n->id, id, (size_t) len) != 0)
    Packit 4a16fb
    				continue;
    Packit 4a16fb
    		if (result)
    Packit 4a16fb
    			*result = n;
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return -ENOENT;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int parse_value(snd_config_t **_n, snd_config_t *parent, input_t *input, char **id, int skip)
    Packit 4a16fb
    {
    Packit 4a16fb
    	snd_config_t *n = *_n;
    Packit 4a16fb
    	char *s;
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    Packit 4a16fb
    	err = get_string(&s, 0, input);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	if (skip) {
    Packit 4a16fb
    		free(s);
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (err == 0 && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) {
    Packit 4a16fb
    		long long i;
    Packit 4a16fb
    		errno = 0;
    Packit 4a16fb
    		err = safe_strtoll(s, &i);
    Packit 4a16fb
    		if (err < 0) {
    Packit 4a16fb
    			double r;
    Packit 4a16fb
    			err = safe_strtod(s, &r);
    Packit 4a16fb
    			if (err >= 0) {
    Packit 4a16fb
    				free(s);
    Packit 4a16fb
    				if (n) {
    Packit 4a16fb
    					if (n->type != SND_CONFIG_TYPE_REAL) {
    Packit 4a16fb
    						SNDERR("%s is not a real", *id);
    Packit 4a16fb
    						return -EINVAL;
    Packit 4a16fb
    					}
    Packit 4a16fb
    				} else {
    Packit 4a16fb
    					err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, parent);
    Packit 4a16fb
    					if (err < 0)
    Packit 4a16fb
    						return err;
    Packit 4a16fb
    				}
    Packit 4a16fb
    				n->u.real = r;
    Packit 4a16fb
    				*_n = n;
    Packit 4a16fb
    				return 0;
    Packit 4a16fb
    			}
    Packit 4a16fb
    		} else {
    Packit 4a16fb
    			free(s);
    Packit 4a16fb
    			if (n) {
    Packit 4a16fb
    				if (n->type != SND_CONFIG_TYPE_INTEGER && n->type != SND_CONFIG_TYPE_INTEGER64) {
    Packit 4a16fb
    					SNDERR("%s is not an integer", *id);
    Packit 4a16fb
    					return -EINVAL;
    Packit 4a16fb
    				}
    Packit 4a16fb
    			} else {
    Packit 4a16fb
    				if (i <= INT_MAX) 
    Packit 4a16fb
    					err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, parent);
    Packit 4a16fb
    				else
    Packit 4a16fb
    					err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER64, parent);
    Packit 4a16fb
    				if (err < 0)
    Packit 4a16fb
    					return err;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			if (n->type == SND_CONFIG_TYPE_INTEGER) 
    Packit 4a16fb
    				n->u.integer = (long) i;
    Packit 4a16fb
    			else 
    Packit 4a16fb
    				n->u.integer64 = i;
    Packit 4a16fb
    			*_n = n;
    Packit 4a16fb
    			return 0;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (n) {
    Packit 4a16fb
    		if (n->type != SND_CONFIG_TYPE_STRING) {
    Packit 4a16fb
    			SNDERR("%s is not a string", *id);
    Packit 4a16fb
    			free(s);
    Packit 4a16fb
    			return -EINVAL;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	} else {
    Packit 4a16fb
    		err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, parent);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	free(n->u.string);
    Packit 4a16fb
    	n->u.string = s;
    Packit 4a16fb
    	*_n = n;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override);
    Packit 4a16fb
    static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override);
    Packit 4a16fb
    Packit Service f36a15
    static int parse_array_def(snd_config_t *parent, input_t *input, int *idx, int skip, int override)
    Packit 4a16fb
    {
    Packit 4a16fb
    	char *id = NULL;
    Packit 4a16fb
    	int c;
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	snd_config_t *n = NULL;
    Packit 4a16fb
    Packit 4a16fb
    	if (!skip) {
    Packit Service f36a15
    		snd_config_t *g;
    Packit 4a16fb
    		char static_id[12];
    Packit Service f36a15
    		while (1) {
    Packit Service f36a15
    			snprintf(static_id, sizeof(static_id), "%i", *idx);
    Packit Service f36a15
    			if (_snd_config_search(parent, static_id, -1, &g) == 0) {
    Packit Service f36a15
    				if (override) {
    Packit Service f36a15
    					snd_config_delete(n);
    Packit Service f36a15
    				} else {
    Packit Service f36a15
    					/* merge */
    Packit Service f36a15
    					(*idx)++;
    Packit Service f36a15
    					continue;
    Packit Service f36a15
    				}
    Packit Service f36a15
    			}
    Packit Service f36a15
    			break;
    Packit Service f36a15
    		}
    Packit 4a16fb
    		id = strdup(static_id);
    Packit 4a16fb
    		if (id == NULL)
    Packit 4a16fb
    			return -ENOMEM;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	c = get_nonwhite(input);
    Packit 4a16fb
    	if (c < 0) {
    Packit 4a16fb
    		err = c;
    Packit 4a16fb
    		goto __end;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	switch (c) {
    Packit 4a16fb
    	case '{':
    Packit 4a16fb
    	case '[':
    Packit 4a16fb
    	{
    Packit 4a16fb
    		char endchr;
    Packit 4a16fb
    		if (!skip) {
    Packit 4a16fb
    			if (n) {
    Packit 4a16fb
    				if (n->type != SND_CONFIG_TYPE_COMPOUND) {
    Packit 4a16fb
    					SNDERR("%s is not a compound", id);
    Packit 4a16fb
    					err = -EINVAL;
    Packit 4a16fb
    					goto __end;
    Packit 4a16fb
    				}
    Packit 4a16fb
    			} else {
    Packit 4a16fb
    				err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
    Packit 4a16fb
    				if (err < 0)
    Packit 4a16fb
    					goto __end;
    Packit 4a16fb
    			}
    Packit 4a16fb
    		}
    Packit 4a16fb
    		if (c == '{') {
    Packit 4a16fb
    			err = parse_defs(n, input, skip, override);
    Packit 4a16fb
    			endchr = '}';
    Packit 4a16fb
    		} else {
    Packit 4a16fb
    			err = parse_array_defs(n, input, skip, override);
    Packit 4a16fb
    			endchr = ']';
    Packit 4a16fb
    		}
    Packit 4a16fb
    		c = get_nonwhite(input);
    Packit 4a16fb
    		if (c < 0) {
    Packit 4a16fb
    			err = c;
    Packit 4a16fb
    			goto __end;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		if (c != endchr) {
    Packit 4a16fb
    			if (n)
    Packit 4a16fb
    				snd_config_delete(n);
    Packit 4a16fb
    			err = LOCAL_UNEXPECTED_CHAR;
    Packit 4a16fb
    			goto __end;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		unget_char(c, input);
    Packit 4a16fb
    		err = parse_value(&n, parent, input, &id, skip);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			goto __end;
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	err = 0;
    Packit 4a16fb
          __end:
    Packit 4a16fb
    	free(id);
    Packit 4a16fb
          	return err;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int parse_array_defs(snd_config_t *parent, input_t *input, int skip, int override)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int idx = 0;
    Packit 4a16fb
    	while (1) {
    Packit 4a16fb
    		int c = get_nonwhite(input), err;
    Packit 4a16fb
    		if (c < 0)
    Packit 4a16fb
    			return c;
    Packit 4a16fb
    		unget_char(c, input);
    Packit 4a16fb
    		if (c == ']')
    Packit 4a16fb
    			return 0;
    Packit Service f36a15
    		err = parse_array_def(parent, input, &idx, skip, override);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit Service f36a15
    		idx++;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int parse_def(snd_config_t *parent, input_t *input, int skip, int override)
    Packit 4a16fb
    {
    Packit 4a16fb
    	char *id = NULL;
    Packit 4a16fb
    	int c;
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	snd_config_t *n;
    Packit 4a16fb
    	enum {MERGE_CREATE, MERGE, OVERRIDE, DONT_OVERRIDE} mode;
    Packit 4a16fb
    	while (1) {
    Packit 4a16fb
    		c = get_nonwhite(input);
    Packit 4a16fb
    		if (c < 0)
    Packit 4a16fb
    			return c;
    Packit 4a16fb
    		switch (c) {
    Packit 4a16fb
    		case '+':
    Packit 4a16fb
    			mode = MERGE_CREATE;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '-':
    Packit 4a16fb
    			mode = MERGE;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '?':
    Packit 4a16fb
    			mode = DONT_OVERRIDE;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '!':
    Packit 4a16fb
    			mode = OVERRIDE;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		default:
    Packit 4a16fb
    			mode = !override ? MERGE_CREATE : OVERRIDE;
    Packit 4a16fb
    			unget_char(c, input);
    Packit 4a16fb
    		}
    Packit 4a16fb
    		err = get_string(&id, 1, input);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    		c = get_nonwhite(input);
    Packit 4a16fb
    		if (c != '.')
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		if (skip) {
    Packit 4a16fb
    			free(id);
    Packit 4a16fb
    			continue;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		if (_snd_config_search(parent, id, -1, &n) == 0) {
    Packit 4a16fb
    			if (mode == DONT_OVERRIDE) {
    Packit 4a16fb
    				skip = 1;
    Packit 4a16fb
    				free(id);
    Packit 4a16fb
    				continue;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			if (mode != OVERRIDE) {
    Packit 4a16fb
    				if (n->type != SND_CONFIG_TYPE_COMPOUND) {
    Packit 4a16fb
    					SNDERR("%s is not a compound", id);
    Packit 4a16fb
    					return -EINVAL;
    Packit 4a16fb
    				}
    Packit Service f36a15
    				n->u.compound.join = true;
    Packit 4a16fb
    				parent = n;
    Packit 4a16fb
    				free(id);
    Packit 4a16fb
    				continue;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			snd_config_delete(n);
    Packit 4a16fb
    		}
    Packit 4a16fb
    		if (mode == MERGE) {
    Packit 4a16fb
    			SNDERR("%s does not exists", id);
    Packit 4a16fb
    			err = -ENOENT;
    Packit 4a16fb
    			goto __end;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			goto __end;
    Packit Service f36a15
    		n->u.compound.join = true;
    Packit 4a16fb
    		parent = n;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (c == '=') {
    Packit 4a16fb
    		c = get_nonwhite(input);
    Packit 4a16fb
    		if (c < 0)
    Packit 4a16fb
    			return c;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (!skip) {
    Packit 4a16fb
    		if (_snd_config_search(parent, id, -1, &n) == 0) {
    Packit 4a16fb
    			if (mode == DONT_OVERRIDE) {
    Packit 4a16fb
    				skip = 1;
    Packit 4a16fb
    				n = NULL;
    Packit 4a16fb
    			} else if (mode == OVERRIDE) {
    Packit 4a16fb
    				snd_config_delete(n);
    Packit 4a16fb
    				n = NULL;
    Packit 4a16fb
    			}
    Packit 4a16fb
    		} else {
    Packit 4a16fb
    			n = NULL;
    Packit 4a16fb
    			if (mode == MERGE) {
    Packit 4a16fb
    				SNDERR("%s does not exists", id);
    Packit 4a16fb
    				err = -ENOENT;
    Packit 4a16fb
    				goto __end;
    Packit 4a16fb
    			}
    Packit 4a16fb
    		}
    Packit 4a16fb
    	}
    Packit 4a16fb
    	switch (c) {
    Packit 4a16fb
    	case '{':
    Packit 4a16fb
    	case '[':
    Packit 4a16fb
    	{
    Packit 4a16fb
    		char endchr;
    Packit 4a16fb
    		if (!skip) {
    Packit 4a16fb
    			if (n) {
    Packit 4a16fb
    				if (n->type != SND_CONFIG_TYPE_COMPOUND) {
    Packit 4a16fb
    					SNDERR("%s is not a compound", id);
    Packit 4a16fb
    					err = -EINVAL;
    Packit 4a16fb
    					goto __end;
    Packit 4a16fb
    				}
    Packit 4a16fb
    			} else {
    Packit 4a16fb
    				err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
    Packit 4a16fb
    				if (err < 0)
    Packit 4a16fb
    					goto __end;
    Packit 4a16fb
    			}
    Packit 4a16fb
    		}
    Packit 4a16fb
    		if (c == '{') {
    Packit 4a16fb
    			err = parse_defs(n, input, skip, override);
    Packit 4a16fb
    			endchr = '}';
    Packit 4a16fb
    		} else {
    Packit 4a16fb
    			err = parse_array_defs(n, input, skip, override);
    Packit 4a16fb
    			endchr = ']';
    Packit 4a16fb
    		}
    Packit 4a16fb
    		c = get_nonwhite(input);
    Packit 4a16fb
    		if (c != endchr) {
    Packit 4a16fb
    			if (n)
    Packit 4a16fb
    				snd_config_delete(n);
    Packit 4a16fb
    			err = LOCAL_UNEXPECTED_CHAR;
    Packit 4a16fb
    			goto __end;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		unget_char(c, input);
    Packit 4a16fb
    		err = parse_value(&n, parent, input, &id, skip);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			goto __end;
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	c = get_nonwhite(input);
    Packit 4a16fb
    	switch (c) {
    Packit 4a16fb
    	case ';':
    Packit 4a16fb
    	case ',':
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		unget_char(c, input);
    Packit 4a16fb
    	}
    Packit 4a16fb
          __end:
    Packit 4a16fb
    	free(id);
    Packit 4a16fb
    	return err;
    Packit 4a16fb
    }
    Packit 4a16fb
    		
    Packit 4a16fb
    static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int c, err;
    Packit 4a16fb
    	while (1) {
    Packit 4a16fb
    		c = get_nonwhite(input);
    Packit 4a16fb
    		if (c < 0)
    Packit 4a16fb
    			return c == LOCAL_UNEXPECTED_EOF ? 0 : c;
    Packit 4a16fb
    		unget_char(c, input);
    Packit 4a16fb
    		if (c == '}')
    Packit 4a16fb
    			return 0;
    Packit 4a16fb
    		err = parse_def(parent, input, skip, override);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static void string_print(char *str, int id, snd_output_t *out)
    Packit 4a16fb
    {
    Packit 4a16fb
    	unsigned char *p = (unsigned char *)str;
    Packit 4a16fb
    	if (!p || !*p) {
    Packit 4a16fb
    		snd_output_puts(out, "''");
    Packit 4a16fb
    		return;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (!id) {
    Packit 4a16fb
    		switch (*p) {
    Packit 4a16fb
    		case '0': case '1': case '2': case '3': case '4':
    Packit 4a16fb
    		case '5': case '6': case '7': case '8': case '9':
    Packit 4a16fb
    		case '-':
    Packit 4a16fb
    			goto quoted;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	}
    Packit 4a16fb
     loop:
    Packit 4a16fb
    	switch (*p) {
    Packit 4a16fb
    	case 0:
    Packit 4a16fb
    		goto nonquoted;
    Packit 4a16fb
    	case ' ':
    Packit 4a16fb
    	case '=':
    Packit 4a16fb
    	case ';':
    Packit 4a16fb
    	case ',':
    Packit 4a16fb
    	case '.':
    Packit 4a16fb
    	case '{':
    Packit 4a16fb
    	case '}':
    Packit Service f36a15
    	case '[':
    Packit Service f36a15
    	case ']':
    Packit 4a16fb
    	case '\'':
    Packit 4a16fb
    	case '"':
    Packit 4a16fb
    		goto quoted;
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		if (*p <= 31 || *p >= 127)
    Packit 4a16fb
    			goto quoted;
    Packit 4a16fb
    		p++;
    Packit 4a16fb
    		goto loop;
    Packit 4a16fb
    	}
    Packit 4a16fb
     nonquoted:
    Packit 4a16fb
    	snd_output_puts(out, str);
    Packit 4a16fb
    	return;
    Packit 4a16fb
     quoted:
    Packit 4a16fb
    	snd_output_putc(out, '\'');
    Packit 4a16fb
    	p = (unsigned char *)str;
    Packit 4a16fb
    	while (*p) {
    Packit 4a16fb
    		int c;
    Packit 4a16fb
    		c = *p;
    Packit 4a16fb
    		switch (c) {
    Packit 4a16fb
    		case '\n':
    Packit 4a16fb
    			snd_output_putc(out, '\\');
    Packit 4a16fb
    			snd_output_putc(out, 'n');
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '\t':
    Packit 4a16fb
    			snd_output_putc(out, '\\');
    Packit 4a16fb
    			snd_output_putc(out, 't');
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '\v':
    Packit 4a16fb
    			snd_output_putc(out, '\\');
    Packit 4a16fb
    			snd_output_putc(out, 'v');
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '\b':
    Packit 4a16fb
    			snd_output_putc(out, '\\');
    Packit 4a16fb
    			snd_output_putc(out, 'b');
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '\r':
    Packit 4a16fb
    			snd_output_putc(out, '\\');
    Packit 4a16fb
    			snd_output_putc(out, 'r');
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '\f':
    Packit 4a16fb
    			snd_output_putc(out, '\\');
    Packit 4a16fb
    			snd_output_putc(out, 'f');
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case '\'':
    Packit 4a16fb
    			snd_output_putc(out, '\\');
    Packit 4a16fb
    			snd_output_putc(out, c);
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		default:
    Packit 4a16fb
    			if (c >= 32 && c <= 126 && c != '\'')
    Packit 4a16fb
    				snd_output_putc(out, c);
    Packit 4a16fb
    			else
    Packit 4a16fb
    				snd_output_printf(out, "\\%04o", c);
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		p++;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	snd_output_putc(out, '\'');
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
    Packit 4a16fb
    				     unsigned int level, unsigned int joins);
    Packit 4a16fb
    Packit 4a16fb
    static int _snd_config_save_node_value(snd_config_t *n, snd_output_t *out,
    Packit 4a16fb
    				       unsigned int level)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	unsigned int k;
    Packit 4a16fb
    	switch (n->type) {
    Packit 4a16fb
    	case SND_CONFIG_TYPE_INTEGER:
    Packit 4a16fb
    		snd_output_printf(out, "%ld", n->u.integer);
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_INTEGER64:
    Packit 4a16fb
    		snd_output_printf(out, "%lld", n->u.integer64);
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_REAL:
    Packit 4a16fb
    		snd_output_printf(out, "%-16g", n->u.real);
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_STRING:
    Packit 4a16fb
    		string_print(n->u.string, 0, out);
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_POINTER:
    Packit 4a16fb
    		SNDERR("cannot save runtime pointer type");
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_COMPOUND:
    Packit 4a16fb
    		snd_output_putc(out, '{');
    Packit 4a16fb
    		snd_output_putc(out, '\n');
    Packit 4a16fb
    		err = _snd_config_save_children(n, out, level + 1, 0);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    		for (k = 0; k < level; ++k) {
    Packit 4a16fb
    			snd_output_putc(out, '\t');
    Packit 4a16fb
    		}
    Packit 4a16fb
    		snd_output_putc(out, '}');
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins)
    Packit 4a16fb
    {
    Packit 4a16fb
    	if (joins > 0) {
    Packit 4a16fb
    		assert(n->parent);
    Packit 4a16fb
    		id_print(n->parent, out, joins - 1);
    Packit 4a16fb
    		snd_output_putc(out, '.');
    Packit 4a16fb
    	}
    Packit 4a16fb
    	string_print(n->id, 1, out);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
    Packit 4a16fb
    				     unsigned int level, unsigned int joins)
    Packit 4a16fb
    {
    Packit 4a16fb
    	unsigned int k;
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	snd_config_iterator_t i, next;
    Packit 4a16fb
    	assert(config && out);
    Packit 4a16fb
    	snd_config_for_each(i, next, config) {
    Packit 4a16fb
    		snd_config_t *n = snd_config_iterator_entry(i);
    Packit 4a16fb
    		if (n->type == SND_CONFIG_TYPE_COMPOUND &&
    Packit 4a16fb
    		    n->u.compound.join) {
    Packit 4a16fb
    			err = _snd_config_save_children(n, out, level, joins + 1);
    Packit 4a16fb
    			if (err < 0)
    Packit 4a16fb
    				return err;
    Packit 4a16fb
    			continue;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		for (k = 0; k < level; ++k) {
    Packit 4a16fb
    			snd_output_putc(out, '\t');
    Packit 4a16fb
    		}
    Packit 4a16fb
    		id_print(n, out, joins);
    Packit 4a16fb
    #if 0
    Packit 4a16fb
    		snd_output_putc(out, ' ');
    Packit 4a16fb
    		snd_output_putc(out, '=');
    Packit 4a16fb
    #endif
    Packit 4a16fb
    		snd_output_putc(out, ' ');
    Packit 4a16fb
    		err = _snd_config_save_node_value(n, out, level);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    #if 0
    Packit 4a16fb
    		snd_output_putc(out, ';');
    Packit 4a16fb
    #endif
    Packit 4a16fb
    		snd_output_putc(out, '\n');
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    #endif
    Packit 4a16fb
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Substitutes one configuration node to another.
    Packit 4a16fb
     * \param dst Handle to the destination node.
    Packit 4a16fb
     * \param src Handle to the source node. Must not be the same as \a dst.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * If both nodes are compounds, the source compound node members are
    Packit 4a16fb
     * appended to the destination compound node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * If the destination node is a compound and the source node is
    Packit 4a16fb
     * an ordinary type, the compound members are deleted (including
    Packit 4a16fb
     * their contents).
    Packit 4a16fb
     *
    Packit 4a16fb
     * Otherwise, the source node's value replaces the destination node's
    Packit 4a16fb
     * value.
    Packit 4a16fb
     *
    Packit 4a16fb
     * In any case, a successful call to this function frees the source
    Packit 4a16fb
     * node.
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(dst && src);
    Packit 4a16fb
    	if (dst->type == SND_CONFIG_TYPE_COMPOUND &&
    Packit 4a16fb
    	    src->type == SND_CONFIG_TYPE_COMPOUND) {	/* append */
    Packit 4a16fb
    		snd_config_iterator_t i, next;
    Packit 4a16fb
    		snd_config_for_each(i, next, src) {
    Packit 4a16fb
    			snd_config_t *n = snd_config_iterator_entry(i);
    Packit 4a16fb
    			n->parent = dst;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		src->u.compound.fields.next->prev = &dst->u.compound.fields;
    Packit 4a16fb
    		src->u.compound.fields.prev->next = &dst->u.compound.fields;
    Packit 4a16fb
    	} else if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
    Packit 4a16fb
    		int err;
    Packit 4a16fb
    		err = snd_config_delete_compound_members(dst);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	free(dst->id);
    Packit 4a16fb
    	dst->id = src->id;
    Packit 4a16fb
    	dst->type = src->type;
    Packit 4a16fb
    	dst->u = src->u;
    Packit 4a16fb
    	free(src);
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Converts an ASCII string to a configuration node type.
    Packit 4a16fb
     * \param[in] ascii A string containing a configuration node type.
    Packit 4a16fb
     * \param[out] type The node type corresponding to \a ascii.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function recognizes at least the following node types:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    integer
    #SND_CONFIG_TYPE_INTEGER
    Packit 4a16fb
     * 
    integer64
    #SND_CONFIG_TYPE_INTEGER64
    Packit 4a16fb
     * 
    real
    #SND_CONFIG_TYPE_REAL
    Packit 4a16fb
     * 
    string
    #SND_CONFIG_TYPE_STRING
    Packit 4a16fb
     * 
    compound
    #SND_CONFIG_TYPE_COMPOUND
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    Unknown note type in \a type.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(ascii && type);
    Packit 4a16fb
    	if (!strcmp(ascii, "integer")) {
    Packit 4a16fb
    		*type = SND_CONFIG_TYPE_INTEGER;
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (!strcmp(ascii, "integer64")) {
    Packit 4a16fb
    		*type = SND_CONFIG_TYPE_INTEGER64;
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (!strcmp(ascii, "real")) {
    Packit 4a16fb
    		*type = SND_CONFIG_TYPE_REAL;
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (!strcmp(ascii, "string")) {
    Packit 4a16fb
    		*type = SND_CONFIG_TYPE_STRING;
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (!strcmp(ascii, "compound")) {
    Packit 4a16fb
    		*type = SND_CONFIG_TYPE_COMPOUND;
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return -EINVAL;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the type of a configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \return The node's type.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    snd_config_type_t snd_config_get_type(const snd_config_t *config)
    Packit 4a16fb
    {
    Packit 4a16fb
    	return config->type;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit Service f36a15
    static int check_array_item(const char *id, int index)
    Packit Service f36a15
    {
    Packit Service f36a15
    	const char *p;
    Packit Service f36a15
    	long val;
    Packit Service f36a15
    Packit Service f36a15
    	for (p = id; *p; p++) {
    Packit Service f36a15
    		if (*p < '0' || *p > '9')
    Packit Service f36a15
    			return 0;
    Packit Service f36a15
    	}
    Packit Service f36a15
    Packit Service f36a15
    	if (safe_strtol(id, &val))
    Packit Service f36a15
    		return 0;
    Packit Service f36a15
    	return val == index;
    Packit Service f36a15
    }
    Packit Service f36a15
    Packit Service f36a15
    /**
    Packit Service f36a15
     * \brief Returns if the compound is an array.
    Packit Service f36a15
     * \param config Handle to the configuration node.
    Packit Service f36a15
     * \return A positive value when true, zero when false, otherwise a negative error code.
    Packit Service f36a15
     */
    Packit Service f36a15
    int snd_config_is_array(const snd_config_t *config)
    Packit Service f36a15
    {
    Packit Service f36a15
    	int idx;
    Packit Service f36a15
    	snd_config_iterator_t i, next;
    Packit Service f36a15
    	snd_config_t *node;
    Packit Service f36a15
    Packit Service f36a15
    	assert(config);
    Packit Service f36a15
    	if (config->type != SND_CONFIG_TYPE_COMPOUND)
    Packit Service f36a15
    		return -EINVAL;
    Packit Service f36a15
    	idx = 0;
    Packit Service f36a15
    	snd_config_for_each(i, next, config) {
    Packit Service f36a15
    		node = snd_config_iterator_entry(i);
    Packit Service f36a15
    		if (!check_array_item(node->id, idx))
    Packit Service f36a15
    			return 0;
    Packit Service f36a15
    		idx++;
    Packit Service f36a15
    	}
    Packit Service f36a15
    	return 1;
    Packit Service f36a15
    }
    Packit Service f36a15
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the id of a configuration node.
    Packit 4a16fb
     * \param[in] config Handle to the configuration node.
    Packit 4a16fb
     * \param[out] id The function puts the pointer to the id string at the
    Packit 4a16fb
     *                address specified by \a id.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The returned string is owned by the configuration node; the application
    Packit 4a16fb
     * must not modify or delete it, and the string becomes invalid when the
    Packit 4a16fb
     * node's id changes or when the node is freed.
    Packit 4a16fb
     *
    Packit 4a16fb
     * If the node does not have an id, \a *id is set to \c NULL.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_id(const snd_config_t *config, const char **id)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && id);
    Packit 4a16fb
    	*id = config->id;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Sets the id of a configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \param id The new node id, must not be \c NULL.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function stores a copy of \a id in the node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EEXIST
    One of \a config's siblings already has the id \a id.
    Packit 4a16fb
     * 
    -EINVAL
    The id of a node with a parent cannot be set to \c NULL.
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_set_id(snd_config_t *config, const char *id)
    Packit 4a16fb
    {
    Packit 4a16fb
    	snd_config_iterator_t i, next;
    Packit 4a16fb
    	char *new_id;
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (id) {
    Packit 4a16fb
    		if (config->parent) {
    Packit 4a16fb
    			snd_config_for_each(i, next, config->parent) {
    Packit 4a16fb
    				snd_config_t *n = snd_config_iterator_entry(i);
    Packit 4a16fb
    				if (n != config && strcmp(id, n->id) == 0)
    Packit 4a16fb
    					return -EEXIST;
    Packit 4a16fb
    			}
    Packit 4a16fb
    		}
    Packit 4a16fb
    		new_id = strdup(id);
    Packit 4a16fb
    		if (!new_id)
    Packit 4a16fb
    			return -ENOMEM;
    Packit 4a16fb
    	} else {
    Packit 4a16fb
    		if (config->parent)
    Packit 4a16fb
    			return -EINVAL;
    Packit 4a16fb
    		new_id = NULL;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	free(config->id);
    Packit 4a16fb
    	config->id = new_id;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a top level configuration node.
    Packit 4a16fb
     * \param[out] config Handle to the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The returned node is an empty compound node without a parent and
    Packit 4a16fb
     * without an id.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_top(snd_config_t **config)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    #ifndef DOC_HIDDEN
    Packit 4a16fb
    int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in,
    Packit 4a16fb
    				  int override, const char * const *include_paths)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	input_t input;
    Packit 4a16fb
    	struct filedesc *fd, *fd_next;
    Packit 4a16fb
    Packit 4a16fb
    	assert(config && in);
    Packit 4a16fb
    	fd = malloc(sizeof(*fd));
    Packit 4a16fb
    	if (!fd)
    Packit 4a16fb
    		return -ENOMEM;
    Packit 4a16fb
    	fd->name = NULL;
    Packit 4a16fb
    	fd->in = in;
    Packit 4a16fb
    	fd->line = 1;
    Packit 4a16fb
    	fd->column = 0;
    Packit 4a16fb
    	fd->next = NULL;
    Packit 4a16fb
    	INIT_LIST_HEAD(&fd->include_paths);
    Packit 4a16fb
    	if (include_paths) {
    Packit 4a16fb
    		for (; *include_paths; include_paths++) {
    Packit 4a16fb
    			err = add_include_path(fd, *include_paths);
    Packit 4a16fb
    			if (err < 0)
    Packit 4a16fb
    				goto _end;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	} else {
    Packit 4a16fb
    		err = add_include_path(fd, snd_config_topdir());
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			goto _end;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	input.current = fd;
    Packit 4a16fb
    	input.unget = 0;
    Packit 4a16fb
    	err = parse_defs(config, &input, 0, override);
    Packit 4a16fb
    	fd = input.current;
    Packit 4a16fb
    	if (err < 0) {
    Packit 4a16fb
    		const char *str;
    Packit 4a16fb
    		switch (err) {
    Packit 4a16fb
    		case LOCAL_UNTERMINATED_STRING:
    Packit 4a16fb
    			str = "Unterminated string";
    Packit 4a16fb
    			err = -EINVAL;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case LOCAL_UNTERMINATED_QUOTE:
    Packit 4a16fb
    			str = "Unterminated quote";
    Packit 4a16fb
    			err = -EINVAL;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case LOCAL_UNEXPECTED_CHAR:
    Packit 4a16fb
    			str = "Unexpected char";
    Packit 4a16fb
    			err = -EINVAL;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		case LOCAL_UNEXPECTED_EOF:
    Packit 4a16fb
    			str = "Unexpected end of file";
    Packit 4a16fb
    			err = -EINVAL;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		default:
    Packit 4a16fb
    			str = strerror(-err);
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
    Packit 4a16fb
    		goto _end;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (get_char(&input) != LOCAL_UNEXPECTED_EOF) {
    Packit 4a16fb
    		SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
    Packit 4a16fb
    		err = -EINVAL;
    Packit 4a16fb
    		goto _end;
    Packit 4a16fb
    	}
    Packit 4a16fb
     _end:
    Packit 4a16fb
    	while (fd->next) {
    Packit 4a16fb
    		fd_next = fd->next;
    Packit 4a16fb
    		snd_input_close(fd->in);
    Packit 4a16fb
    		free(fd->name);
    Packit 4a16fb
    		free_include_paths(fd);
    Packit 4a16fb
    		free(fd);
    Packit 4a16fb
    		fd = fd_next;
    Packit 4a16fb
    	}
    Packit 4a16fb
    Packit 4a16fb
    	free_include_paths(fd);
    Packit 4a16fb
    	free(fd);
    Packit 4a16fb
    	return err;
    Packit 4a16fb
    }
    Packit 4a16fb
    #endif
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Loads a configuration tree.
    Packit 4a16fb
     * \param config Handle to a top level configuration node.
    Packit 4a16fb
     * \param in Input handle to read the configuration from.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The definitions loaded from the input are added to \a config, which
    Packit 4a16fb
     * must be a compound node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * Any errors encountered when parsing the input or returned by hooks or
    Packit 4a16fb
     * functions.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_load(snd_config_t *config, snd_input_t *in)
    Packit 4a16fb
    {
    Packit 4a16fb
    	return _snd_config_load_with_include(config, in, 0, NULL);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Loads a configuration tree and overrides existing configuration nodes.
    Packit 4a16fb
     * \param config Handle to a top level configuration node.
    Packit 4a16fb
     * \param in Input handle to read the configuration from.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function loads definitions from \a in into \a config like
    Packit 4a16fb
     * #snd_config_load, but the default mode for input nodes is 'override'
    Packit 4a16fb
     * (!) instead of 'merge+create' (+).
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_load_override(snd_config_t *config, snd_input_t *in)
    Packit 4a16fb
    {
    Packit 4a16fb
    	return _snd_config_load_with_include(config, in, 1, NULL);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Adds a child to a compound configuration node.
    Packit 4a16fb
     * \param parent Handle to a compound configuration node.
    Packit 4a16fb
     * \param child Handle to the configuration node to be added.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function makes the node \a child a child of the node \a parent.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The parent node then owns the child node, i.e., the child node gets
    Packit 4a16fb
     * deleted together with its parent.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \a child must have an id.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a child does not have an id.
    Packit 4a16fb
     * 
    -EINVAL
    \a child already has a parent.
    Packit 4a16fb
     * 
    -EEXIST
    \a parent already contains a child node with the same
    Packit 4a16fb
     *                id as \a child.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_add(snd_config_t *parent, snd_config_t *child)
    Packit 4a16fb
    {
    Packit 4a16fb
    	snd_config_iterator_t i, next;
    Packit 4a16fb
    	assert(parent && child);
    Packit 4a16fb
    	if (!child->id || child->parent)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	snd_config_for_each(i, next, parent) {
    Packit 4a16fb
    		snd_config_t *n = snd_config_iterator_entry(i);
    Packit 4a16fb
    		if (strcmp(child->id, n->id) == 0)
    Packit 4a16fb
    			return -EEXIST;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	child->parent = parent;
    Packit 4a16fb
    	list_add_tail(&child->list, &parent->u.compound.fields);
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Adds a child after another child configuration node.
    Packit 4a16fb
     * \param after Handle to the start configuration node.
    Packit 4a16fb
     * \param child Handle to the configuration node to be added.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function makes the node \a child a child of the parent of
    Packit 4a16fb
     * the node \a after.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The parent node then owns the child node, i.e., the child node gets
    Packit 4a16fb
     * deleted together with its parent.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \a child must have an id.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a child does not have an id.
    Packit 4a16fb
     * 
    -EINVAL
    \a child already has a parent.
    Packit 4a16fb
     * 
    -EEXIST
    \a parent already contains a child node with the same
    Packit 4a16fb
     *                id as \a child.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_add_after(snd_config_t *after, snd_config_t *child)
    Packit 4a16fb
    {
    Packit 4a16fb
    	snd_config_iterator_t i, next;
    Packit 4a16fb
    	snd_config_t *parent;
    Packit 4a16fb
    	assert(after && child);
    Packit 4a16fb
    	parent = after->parent;
    Packit 4a16fb
    	assert(parent);
    Packit 4a16fb
    	if (!child->id || child->parent)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	snd_config_for_each(i, next, parent) {
    Packit 4a16fb
    		snd_config_t *n = snd_config_iterator_entry(i);
    Packit 4a16fb
    		if (strcmp(child->id, n->id) == 0)
    Packit 4a16fb
    			return -EEXIST;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	child->parent = parent;
    Packit 4a16fb
    	list_insert(&child->list, &after->list, after->list.next);
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Adds a child before another child configuration node.
    Packit 4a16fb
     * \param before Handle to the start configuration node.
    Packit 4a16fb
     * \param child Handle to the configuration node to be added.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function makes the node \a child a child of the parent of
    Packit 4a16fb
     * the node \a before.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The parent node then owns the child node, i.e., the child node gets
    Packit 4a16fb
     * deleted together with its parent.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \a child must have an id.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a child does not have an id.
    Packit 4a16fb
     * 
    -EINVAL
    \a child already has a parent.
    Packit 4a16fb
     * 
    -EEXIST
    \a parent already contains a child node with the same
    Packit 4a16fb
     *                id as \a child.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_add_before(snd_config_t *before, snd_config_t *child)
    Packit 4a16fb
    {
    Packit 4a16fb
    	snd_config_iterator_t i, next;
    Packit 4a16fb
    	snd_config_t *parent;
    Packit 4a16fb
    	assert(before && child);
    Packit 4a16fb
    	parent = before->parent;
    Packit 4a16fb
    	assert(parent);
    Packit 4a16fb
    	if (!child->id || child->parent)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	snd_config_for_each(i, next, parent) {
    Packit 4a16fb
    		snd_config_t *n = snd_config_iterator_entry(i);
    Packit 4a16fb
    		if (strcmp(child->id, n->id) == 0)
    Packit 4a16fb
    			return -EEXIST;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	child->parent = parent;
    Packit 4a16fb
    	list_insert(&child->list, before->list.prev, &before->list);
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Removes a configuration node from its tree.
    Packit 4a16fb
     * \param config Handle to the configuration node to be removed.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function makes \a config a top-level node, i.e., if \a config
    Packit 4a16fb
     * has a parent, then \a config is removed from the list of the parent's
    Packit 4a16fb
     * children.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This functions does \e not free the removed node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \sa snd_config_delete
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_remove(snd_config_t *config)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (config->parent)
    Packit 4a16fb
    		list_del(&config->list);
    Packit 4a16fb
    	config->parent = NULL;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Frees a configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node to be deleted.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function frees a configuration node and all its resources.
    Packit 4a16fb
     *
    Packit 4a16fb
     * If the node is a child node, it is removed from the tree before being
    Packit 4a16fb
     * deleted.
    Packit 4a16fb
     *
    Packit 4a16fb
     * If the node is a compound node, its descendants (the whole subtree)
    Packit 4a16fb
     * are deleted recursively.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The function is supposed to be called only for locally copied config
    Packit 4a16fb
     * trees.  For the global tree, take the reference via #snd_config_update_ref
    Packit 4a16fb
     * and free it via #snd_config_unref.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     *
    Packit 4a16fb
     * \sa snd_config_remove
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_delete(snd_config_t *config)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (config->refcount > 0) {
    Packit 4a16fb
    		config->refcount--;
    Packit 4a16fb
    		return 0;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	switch (config->type) {
    Packit 4a16fb
    	case SND_CONFIG_TYPE_COMPOUND:
    Packit 4a16fb
    	{
    Packit 4a16fb
    		int err;
    Packit 4a16fb
    		struct list_head *i;
    Packit 4a16fb
    		i = config->u.compound.fields.next;
    Packit 4a16fb
    		while (i != &config->u.compound.fields) {
    Packit 4a16fb
    			struct list_head *nexti = i->next;
    Packit 4a16fb
    			snd_config_t *child = snd_config_iterator_entry(i);
    Packit 4a16fb
    			err = snd_config_delete(child);
    Packit 4a16fb
    			if (err < 0)
    Packit 4a16fb
    				return err;
    Packit 4a16fb
    			i = nexti;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	case SND_CONFIG_TYPE_STRING:
    Packit 4a16fb
    		free(config->u.string);
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (config->parent)
    Packit 4a16fb
    		list_del(&config->list);
    Packit 4a16fb
    	free(config->id);
    Packit 4a16fb
    	free(config);
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Deletes the children of a node.
    Packit 4a16fb
     * \param config Handle to the compound configuration node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function removes and frees all children of a configuration node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * Any compound nodes among the children of \a config are deleted
    Packit 4a16fb
     * recursively.
    Packit 4a16fb
     *
    Packit 4a16fb
     * After a successful call to this function, \a config is an empty
    Packit 4a16fb
     * compound node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a compound node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_delete_compound_members(const snd_config_t *config)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	struct list_head *i;
    Packit 4a16fb
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_COMPOUND)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	i = config->u.compound.fields.next;
    Packit 4a16fb
    	while (i != &config->u.compound.fields) {
    Packit 4a16fb
    		struct list_head *nexti = i->next;
    Packit 4a16fb
    		snd_config_t *child = snd_config_iterator_entry(i);
    Packit 4a16fb
    		err = snd_config_delete(child);
    Packit 4a16fb
    		if (err < 0)
    Packit 4a16fb
    			return err;
    Packit 4a16fb
    		i = nexti;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a configuration node.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \param[in] type The type of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This functions creates a new node of the specified type.
    Packit 4a16fb
     * The new node has id \a id, which may be \c NULL.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The value of the new node is zero (for numbers), or \c NULL (for
    Packit 4a16fb
     * strings and pointers), or empty (for compound nodes).
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_make(snd_config_t **config, const char *id,
    Packit 4a16fb
    		    snd_config_type_t type)
    Packit 4a16fb
    {
    Packit 4a16fb
    	char *id1;
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (id) {
    Packit 4a16fb
    		id1 = strdup(id);
    Packit 4a16fb
    		if (!id1)
    Packit 4a16fb
    			return -ENOMEM;
    Packit 4a16fb
    	} else
    Packit 4a16fb
    		id1 = NULL;
    Packit 4a16fb
    	return _snd_config_make(config, &id1, type);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates an integer configuration node.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
    Packit 4a16fb
     * with value \c 0.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     *
    Packit 4a16fb
     * \sa snd_config_imake_integer
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_make_integer(snd_config_t **config, const char *id)
    Packit 4a16fb
    {
    Packit 4a16fb
    	return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a 64-bit-integer configuration node.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
    Packit 4a16fb
     * and with value \c 0.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     *
    Packit 4a16fb
     * \sa snd_config_imake_integer64
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_make_integer64(snd_config_t **config, const char *id)
    Packit 4a16fb
    {
    Packit 4a16fb
    	return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a real number configuration node.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
    Packit 4a16fb
     * with value \c 0.0.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \sa snd_config_imake_real
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_make_real(snd_config_t **config, const char *id)
    Packit 4a16fb
    {
    Packit 4a16fb
    	return snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a string configuration node.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
    Packit 4a16fb
     * with value \c NULL.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     *
    Packit 4a16fb
     * \sa snd_config_imake_string
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_make_string(snd_config_t **config, const char *id)
    Packit 4a16fb
    {
    Packit 4a16fb
    	return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a pointer configuration node.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
    Packit 4a16fb
     * with value \c NULL.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \sa snd_config_imake_pointer
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_make_pointer(snd_config_t **config, const char *id)
    Packit 4a16fb
    {
    Packit 4a16fb
    	return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates an empty compound configuration node.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \param[in] join Join flag.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new empty node of type
    Packit 4a16fb
     * #SND_CONFIG_TYPE_COMPOUND.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \a join determines how the compound node's id is printed when the
    Packit 4a16fb
     * configuration is saved to a text file.  For example, if the join flag
    Packit 4a16fb
     * of compound node \c a is zero, the output will look as follows:
    Packit 4a16fb
     * \code
    Packit 4a16fb
     * a {
    Packit 4a16fb
     *     b "hello"
    Packit 4a16fb
     *     c 42
    Packit 4a16fb
     * }
    Packit 4a16fb
     * \endcode
    Packit 4a16fb
     * If, however, the join flag of \c a is nonzero, its id will be joined
    Packit 4a16fb
     * with its children's ids, like this:
    Packit 4a16fb
     * \code
    Packit 4a16fb
     * a.b "hello"
    Packit 4a16fb
     * a.c 42
    Packit 4a16fb
     * \endcode
    Packit 4a16fb
     * An \e empty compound node with its join flag set would result in no
    Packit 4a16fb
     * output, i.e., after saving and reloading the configuration file, that
    Packit 4a16fb
     * compound node would be lost.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_make_compound(snd_config_t **config, const char *id,
    Packit 4a16fb
    			     int join)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	(*config)->u.compound.join = join;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates an integer configuration node with the given initial value.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \param[in] value The initial value of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
    Packit 4a16fb
     * with value \a value.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_imake_integer(snd_config_t **config, const char *id, const long value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	
    Packit 4a16fb
    	err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	(*config)->u.integer = value;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a 64-bit-integer configuration node with the given initial value.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \param[in] value The initial value of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
    Packit 4a16fb
     * and with value \a value.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	
    Packit 4a16fb
    	err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	(*config)->u.integer64 = value;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a real number configuration node with the given initial value.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \param[in] value The initial value of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
    Packit 4a16fb
     * with value \a value.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_imake_real(snd_config_t **config, const char *id, const double value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	
    Packit 4a16fb
    	err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	(*config)->u.real = value;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a string configuration node with the given initial value.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \param[in] value The initial value of the new node.  May be \c NULL.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
    Packit 4a16fb
     * with a copy of the string \c value.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_imake_string(snd_config_t **config, const char *id, const char *value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	snd_config_t *tmp;
    Packit 4a16fb
    	
    Packit 4a16fb
    	err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	if (value) {
    Packit 4a16fb
    		tmp->u.string = strdup(value);
    Packit 4a16fb
    		if (!tmp->u.string) {
    Packit 4a16fb
    			snd_config_delete(tmp);
    Packit 4a16fb
    			return -ENOMEM;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	} else {
    Packit 4a16fb
    		tmp->u.string = NULL;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	*config = tmp;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    int snd_config_imake_safe_string(snd_config_t **config, const char *id, const char *value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	snd_config_t *tmp;
    Packit 4a16fb
    	char *c;
    Packit 4a16fb
    Packit 4a16fb
    	err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	if (value) {
    Packit 4a16fb
    		tmp->u.string = strdup(value);
    Packit 4a16fb
    		if (!tmp->u.string) {
    Packit 4a16fb
    			snd_config_delete(tmp);
    Packit 4a16fb
    			return -ENOMEM;
    Packit 4a16fb
    		}
    Packit 4a16fb
    Packit 4a16fb
    		for (c = tmp->u.string; *c; c++) {
    Packit 4a16fb
    			if (*c == ' ' || *c == '-' || *c == '_' ||
    Packit 4a16fb
    				(*c >= '0' && *c <= '9') ||
    Packit 4a16fb
    				(*c >= 'a' && *c <= 'z') ||
    Packit 4a16fb
    				(*c >= 'A' && *c <= 'Z'))
    Packit 4a16fb
    					continue;
    Packit 4a16fb
    			*c = '_';
    Packit 4a16fb
    		}
    Packit 4a16fb
    	} else {
    Packit 4a16fb
    		tmp->u.string = NULL;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	*config = tmp;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Creates a pointer configuration node with the given initial value.
    Packit 4a16fb
     * \param[out] config The function puts the handle to the new node at
    Packit 4a16fb
     *                    the address specified by \a config.
    Packit 4a16fb
     * \param[in] id The id of the new node.
    Packit 4a16fb
     * \param[in] value The initial value of the new node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
    Packit 4a16fb
     * with value \c value.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	int err;
    Packit 4a16fb
    	
    Packit 4a16fb
    	err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
    Packit 4a16fb
    	if (err < 0)
    Packit 4a16fb
    		return err;
    Packit 4a16fb
    	(*config)->u.ptr = value;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Changes the value of an integer configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \param value The new value for the node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not an integer node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_set_integer(snd_config_t *config, long value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_INTEGER)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	config->u.integer = value;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Changes the value of a 64-bit-integer configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \param value The new value for the node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a 64-bit-integer node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_set_integer64(snd_config_t *config, long long value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_INTEGER64)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	config->u.integer64 = value;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Changes the value of a real-number configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \param value The new value for the node.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a real-number node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_set_real(snd_config_t *config, double value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_REAL)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	config->u.real = value;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Changes the value of a string configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \param value The new value for the node.  May be \c NULL.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function deletes the old string in the node and stores a copy of
    Packit 4a16fb
     * \a value string in the node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a string node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_set_string(snd_config_t *config, const char *value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	char *new_string;
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_STRING)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	if (value) {
    Packit 4a16fb
    		new_string = strdup(value);
    Packit 4a16fb
    		if (!new_string)
    Packit 4a16fb
    			return -ENOMEM;
    Packit 4a16fb
    	} else {
    Packit 4a16fb
    		new_string = NULL;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	free(config->u.string);
    Packit 4a16fb
    	config->u.string = new_string;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Changes the value of a pointer configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \param value The new value for the node.  May be \c NULL.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function does not free the old pointer in the node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a pointer node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_set_pointer(snd_config_t *config, const void *value)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_POINTER)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	config->u.ptr = value;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Changes the value of a configuration node.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \param ascii The new value for the node, as an ASCII string.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function changes the node's value to a new value that is parsed
    Packit 4a16fb
     * from the string \a ascii.  \a ascii must not be \c NULL, not even for
    Packit 4a16fb
     * a string node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The node's type does not change, i.e., the string must contain a
    Packit 4a16fb
     * valid value with the same type as the node's type.  For a string
    Packit 4a16fb
     * node, the node's new value is a copy of \a ascii.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a number or string node.
    Packit 4a16fb
     * 
    -EINVAL
    The value in \a ascii cannot be parsed.
    Packit 4a16fb
     * 
    -ERANGE
    The value in \a ascii is too big for the node's type.
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_set_ascii(snd_config_t *config, const char *ascii)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && ascii);
    Packit 4a16fb
    	switch (config->type) {
    Packit 4a16fb
    	case SND_CONFIG_TYPE_INTEGER:
    Packit 4a16fb
    		{
    Packit 4a16fb
    			long i;
    Packit 4a16fb
    			int err = safe_strtol(ascii, &i);
    Packit 4a16fb
    			if (err < 0)
    Packit 4a16fb
    				return err;
    Packit 4a16fb
    			config->u.integer = i;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_INTEGER64:
    Packit 4a16fb
    		{
    Packit 4a16fb
    			long long i;
    Packit 4a16fb
    			int err = safe_strtoll(ascii, &i);
    Packit 4a16fb
    			if (err < 0)
    Packit 4a16fb
    				return err;
    Packit 4a16fb
    			config->u.integer64 = i;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_REAL:
    Packit 4a16fb
    		{
    Packit 4a16fb
    			double d;
    Packit 4a16fb
    			int err = safe_strtod(ascii, &d);
    Packit 4a16fb
    			if (err < 0)
    Packit 4a16fb
    				return err;
    Packit 4a16fb
    			config->u.real = d;
    Packit 4a16fb
    			break;
    Packit 4a16fb
    		}
    Packit 4a16fb
    	case SND_CONFIG_TYPE_STRING:
    Packit 4a16fb
    		{
    Packit 4a16fb
    			char *ptr = strdup(ascii);
    Packit 4a16fb
    			if (ptr == NULL)
    Packit 4a16fb
    				return -ENOMEM;
    Packit 4a16fb
    			free(config->u.string);
    Packit 4a16fb
    			config->u.string = ptr;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the value of an integer configuration node.
    Packit 4a16fb
     * \param[in] config Handle to the configuration node.
    Packit 4a16fb
     * \param[out] ptr The node's value.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not an integer node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_integer(const snd_config_t *config, long *ptr)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && ptr);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_INTEGER)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	*ptr = config->u.integer;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the value of a 64-bit-integer configuration node.
    Packit 4a16fb
     * \param[in] config Handle to the configuration node.
    Packit 4a16fb
     * \param[out] ptr The node's value.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a 64-bit-integer node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_integer64(const snd_config_t *config, long long *ptr)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && ptr);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_INTEGER64)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	*ptr = config->u.integer64;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the value of a real-number configuration node.
    Packit 4a16fb
     * \param[in] config Handle to the configuration node.
    Packit 4a16fb
     * \param[out] ptr The node's value.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a real-number node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_real(const snd_config_t *config, double *ptr)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && ptr);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_REAL)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	*ptr = config->u.real;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the value of a real or integer configuration node.
    Packit 4a16fb
     * \param[in] config Handle to the configuration node.
    Packit 4a16fb
     * \param[out] ptr The node's value.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * If the node's type is integer or integer64, the value is converted
    Packit 4a16fb
     * to the \c double type on the fly.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a number node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_ireal(const snd_config_t *config, double *ptr)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && ptr);
    Packit 4a16fb
    	if (config->type == SND_CONFIG_TYPE_REAL)
    Packit 4a16fb
    		*ptr = config->u.real;
    Packit 4a16fb
    	else if (config->type == SND_CONFIG_TYPE_INTEGER)
    Packit 4a16fb
    		*ptr = config->u.integer;
    Packit 4a16fb
    	else if (config->type == SND_CONFIG_TYPE_INTEGER64)
    Packit 4a16fb
    		*ptr = config->u.integer64;
    Packit 4a16fb
    	else
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the value of a string configuration node.
    Packit 4a16fb
     * \param[in] config Handle to the configuration node.
    Packit 4a16fb
     * \param[out] ptr The function puts the node's value at the address
    Packit 4a16fb
     *                 specified by \a ptr.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The returned string is owned by the configuration node; the
    Packit 4a16fb
     * application must not modify or delete it, and the string becomes
    Packit 4a16fb
     * invalid when the node's value changes or when the node is freed.
    Packit 4a16fb
     *
    Packit 4a16fb
     * The string may be \c NULL.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a string node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_string(const snd_config_t *config, const char **ptr)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && ptr);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_STRING)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	*ptr = config->u.string;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the value of a pointer configuration node.
    Packit 4a16fb
     * \param[in] config Handle to the configuration node.
    Packit 4a16fb
     * \param[out] ptr The function puts the node's value at the address
    Packit 4a16fb
     *                 specified by \a ptr.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a string node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && ptr);
    Packit 4a16fb
    	if (config->type != SND_CONFIG_TYPE_POINTER)
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	*ptr = config->u.ptr;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Returns the value of a configuration node as a string.
    Packit 4a16fb
     * \param[in] config Handle to the configuration node.
    Packit 4a16fb
     * \param[out] ascii The function puts the pointer to the returned
    Packit 4a16fb
     *                   string at the address specified by \a ascii.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function dynamically allocates the returned string.  The
    Packit 4a16fb
     * application is responsible for deleting it with \c free() when it is
    Packit 4a16fb
     * no longer used.
    Packit 4a16fb
     *
    Packit 4a16fb
     * For a string node with \c NULL value, the returned string is \c NULL.
    Packit 4a16fb
     *
    Packit 4a16fb
     * Supported node types are #SND_CONFIG_TYPE_INTEGER,
    Packit 4a16fb
     * #SND_CONFIG_TYPE_INTEGER64, #SND_CONFIG_TYPE_REAL, and
    Packit 4a16fb
     * #SND_CONFIG_TYPE_STRING.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    \a config is not a (64-bit) integer or real number or
    Packit 4a16fb
     *                string node.
    Packit 4a16fb
     * 
    -ENOMEM
    Out of memory.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_get_ascii(const snd_config_t *config, char **ascii)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && ascii);
    Packit 4a16fb
    	switch (config->type) {
    Packit 4a16fb
    	case SND_CONFIG_TYPE_INTEGER:
    Packit 4a16fb
    		{
    Packit 4a16fb
    			char res[12];
    Packit 4a16fb
    			int err;
    Packit 4a16fb
    			err = snprintf(res, sizeof(res), "%li", config->u.integer);
    Packit 4a16fb
    			if (err < 0 || err == sizeof(res)) {
    Packit 4a16fb
    				assert(0);
    Packit 4a16fb
    				return -ENOMEM;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			*ascii = strdup(res);
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_INTEGER64:
    Packit 4a16fb
    		{
    Packit 4a16fb
    			char res[32];
    Packit 4a16fb
    			int err;
    Packit 4a16fb
    			err = snprintf(res, sizeof(res), "%lli", config->u.integer64);
    Packit 4a16fb
    			if (err < 0 || err == sizeof(res)) {
    Packit 4a16fb
    				assert(0);
    Packit 4a16fb
    				return -ENOMEM;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			*ascii = strdup(res);
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_REAL:
    Packit 4a16fb
    		{
    Packit 4a16fb
    			char res[32];
    Packit 4a16fb
    			int err;
    Packit 4a16fb
    			err = snprintf(res, sizeof(res), "%-16g", config->u.real);
    Packit 4a16fb
    			if (err < 0 || err == sizeof(res)) {
    Packit 4a16fb
    				assert(0);
    Packit 4a16fb
    				return -ENOMEM;
    Packit 4a16fb
    			}
    Packit 4a16fb
    			if (res[0]) {		/* trim the string */
    Packit 4a16fb
    				char *ptr;
    Packit 4a16fb
    				ptr = res + strlen(res) - 1;
    Packit 4a16fb
    				while (ptr != res && *ptr == ' ')
    Packit 4a16fb
    					ptr--;
    Packit 4a16fb
    				if (*ptr != ' ')
    Packit 4a16fb
    					ptr++;
    Packit 4a16fb
    				*ptr = '\0';
    Packit 4a16fb
    			}
    Packit 4a16fb
    			*ascii = strdup(res);
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	case SND_CONFIG_TYPE_STRING:
    Packit 4a16fb
    		if (config->u.string)
    Packit 4a16fb
    			*ascii = strdup(config->u.string);
    Packit 4a16fb
    		else {
    Packit 4a16fb
    			*ascii = NULL;
    Packit 4a16fb
    			return 0;
    Packit 4a16fb
    		}
    Packit 4a16fb
    		break;
    Packit 4a16fb
    	default:
    Packit 4a16fb
    		return -EINVAL;
    Packit 4a16fb
    	}
    Packit 4a16fb
    	if (*ascii == NULL)
    Packit 4a16fb
    		return -ENOMEM;
    Packit 4a16fb
    	return 0;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Compares the id of a configuration node to a given string.
    Packit 4a16fb
     * \param config Handle to the configuration node.
    Packit 4a16fb
     * \param id ASCII id.
    Packit 4a16fb
     * \return The same value as the result of the \c strcmp function, i.e.,
    Packit 4a16fb
     *         less than zero if \a config's id is lexicographically less
    Packit 4a16fb
     *         than \a id, zero if \a config's id is equal to id, greater
    Packit 4a16fb
     *         than zero otherwise.
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_test_id(const snd_config_t *config, const char *id)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && id);
    Packit 4a16fb
    	if (config->id)
    Packit 4a16fb
    		return strcmp(config->id, id);
    Packit 4a16fb
    	else
    Packit 4a16fb
    		return -1;
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Dumps the contents of a configuration node or tree.
    Packit 4a16fb
     * \param config Handle to the (root) configuration node.
    Packit 4a16fb
     * \param out Output handle.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function writes a textual representation of \a config's value to
    Packit 4a16fb
     * the output \a out.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -EINVAL
    A node in the tree has a type that cannot be printed,
    Packit 4a16fb
     *                i.e., #SND_CONFIG_TYPE_POINTER.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_save(snd_config_t *config, snd_output_t *out)
    Packit 4a16fb
    {
    Packit 4a16fb
    	assert(config && out);
    Packit 4a16fb
    	if (config->type == SND_CONFIG_TYPE_COMPOUND)
    Packit 4a16fb
    		return _snd_config_save_children(config, out, 0, 0);
    Packit 4a16fb
    	else
    Packit 4a16fb
    		return _snd_config_save_node_value(config, out, 0);
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /*
    Packit 4a16fb
     *  *** search macros ***
    Packit 4a16fb
     */
    Packit 4a16fb
    Packit 4a16fb
    #ifndef DOC_HIDDEN
    Packit 4a16fb
    Packit 4a16fb
    #define SND_CONFIG_SEARCH(config, key, result, extra_code) \
    Packit 4a16fb
    { \
    Packit 4a16fb
    	snd_config_t *n; \
    Packit 4a16fb
    	int err; \
    Packit 4a16fb
    	const char *p; \
    Packit 4a16fb
    	assert(config && key); \
    Packit 4a16fb
    	while (1) { \
    Packit 4a16fb
    		if (config->type != SND_CONFIG_TYPE_COMPOUND) \
    Packit 4a16fb
    			return -ENOENT; \
    Packit 4a16fb
    		{ extra_code ; } \
    Packit 4a16fb
    		p = strchr(key, '.'); \
    Packit 4a16fb
    		if (p) { \
    Packit 4a16fb
    			err = _snd_config_search(config, key, p - key, &n); \
    Packit 4a16fb
    			if (err < 0) \
    Packit 4a16fb
    				return err; \
    Packit 4a16fb
    			config = n; \
    Packit 4a16fb
    			key = p + 1; \
    Packit 4a16fb
    		} else \
    Packit 4a16fb
    			return _snd_config_search(config, key, -1, result); \
    Packit 4a16fb
    	} \
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    #define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \
    Packit 4a16fb
    { \
    Packit 4a16fb
    	snd_config_t *n; \
    Packit 4a16fb
    	int err; \
    Packit 4a16fb
    	const char *p; \
    Packit 4a16fb
    	assert(config && key); \
    Packit 4a16fb
    	while (1) { \
    Packit 4a16fb
    		if (config->type != SND_CONFIG_TYPE_COMPOUND) { \
    Packit 4a16fb
    			if (snd_config_get_string(config, &p) < 0) \
    Packit 4a16fb
    				return -ENOENT; \
    Packit 4a16fb
    			err = fcn(root, root, p, &config); \
    Packit 4a16fb
    			if (err < 0) \
    Packit 4a16fb
    				return err; \
    Packit 4a16fb
    		} \
    Packit 4a16fb
    		{ extra_code ; } \
    Packit 4a16fb
    		p = strchr(key, '.'); \
    Packit 4a16fb
    		if (p) { \
    Packit 4a16fb
    			err = _snd_config_search(config, key, p - key, &n); \
    Packit 4a16fb
    			if (err < 0) \
    Packit 4a16fb
    				return err; \
    Packit 4a16fb
    			config = n; \
    Packit 4a16fb
    			key = p + 1; \
    Packit 4a16fb
    		} else \
    Packit 4a16fb
    			return _snd_config_search(config, key, -1, result); \
    Packit 4a16fb
    	} \
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    #define SND_CONFIG_SEARCHV(config, result, fcn) \
    Packit 4a16fb
    { \
    Packit 4a16fb
    	snd_config_t *n; \
    Packit 4a16fb
    	va_list arg; \
    Packit 4a16fb
    	assert(config); \
    Packit 4a16fb
    	va_start(arg, result); \
    Packit 4a16fb
    	while (1) { \
    Packit 4a16fb
    		const char *k = va_arg(arg, const char *); \
    Packit 4a16fb
    		int err; \
    Packit 4a16fb
    		if (!k) \
    Packit 4a16fb
    			break; \
    Packit 4a16fb
    		err = fcn(config, k, &n); \
    Packit 4a16fb
    		if (err < 0) { \
    Packit 4a16fb
    			va_end(arg); \
    Packit 4a16fb
    			return err; \
    Packit 4a16fb
    		} \
    Packit 4a16fb
    		config = n; \
    Packit 4a16fb
    	} \
    Packit 4a16fb
    	va_end(arg); \
    Packit 4a16fb
    	if (result) \
    Packit 4a16fb
    		*result = n; \
    Packit 4a16fb
    	return 0; \
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    #define SND_CONFIG_SEARCHVA(root, config, result, fcn) \
    Packit 4a16fb
    { \
    Packit 4a16fb
    	snd_config_t *n; \
    Packit 4a16fb
    	va_list arg; \
    Packit 4a16fb
    	assert(config); \
    Packit 4a16fb
    	va_start(arg, result); \
    Packit 4a16fb
    	while (1) { \
    Packit 4a16fb
    		const char *k = va_arg(arg, const char *); \
    Packit 4a16fb
    		int err; \
    Packit 4a16fb
    		if (!k) \
    Packit 4a16fb
    			break; \
    Packit 4a16fb
    		err = fcn(root, config, k, &n); \
    Packit 4a16fb
    		if (err < 0) { \
    Packit 4a16fb
    			va_end(arg); \
    Packit 4a16fb
    			return err; \
    Packit 4a16fb
    		} \
    Packit 4a16fb
    		config = n; \
    Packit 4a16fb
    	} \
    Packit 4a16fb
    	va_end(arg); \
    Packit 4a16fb
    	if (result) \
    Packit 4a16fb
    		*result = n; \
    Packit 4a16fb
    	return 0; \
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    #define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
    Packit 4a16fb
    { \
    Packit 4a16fb
    	snd_config_t *res = NULL; \
    Packit 4a16fb
    	char *old_key; \
    Packit 4a16fb
    	int err, first = 1, maxloop = 1000; \
    Packit 4a16fb
    	assert(config && key); \
    Packit 4a16fb
    	while (1) { \
    Packit 4a16fb
    		old_key = strdup(key); \
    Packit 4a16fb
    		if (old_key == NULL) { \
    Packit 4a16fb
    			err = -ENOMEM; \
    Packit 4a16fb
    			res = NULL; \
    Packit 4a16fb
    			break; \
    Packit 4a16fb
    		} \
    Packit 4a16fb
    		err = first && base ? -EIO : fcn1(config, config, key, &res;; \
    Packit 4a16fb
    		if (err < 0) { \
    Packit 4a16fb
    			if (!base) \
    Packit 4a16fb
    				break; \
    Packit 4a16fb
    			err = fcn2(config, config, &res, base, key, NULL); \
    Packit 4a16fb
    			if (err < 0) \
    Packit 4a16fb
    				break; \
    Packit 4a16fb
    		} \
    Packit 4a16fb
    		if (snd_config_get_string(res, &key) < 0) \
    Packit 4a16fb
    			break; \
    Packit 4a16fb
    		assert(key); \
    Packit 4a16fb
    		if (!first && (strcmp(key, old_key) == 0 || maxloop <= 0)) { \
    Packit 4a16fb
    			if (maxloop == 0) \
    Packit 4a16fb
    				SNDERR("maximum loop count reached (circular configuration?)"); \
    Packit 4a16fb
    			else \
    Packit 4a16fb
    				SNDERR("key %s refers to itself", key); \
    Packit 4a16fb
    			err = -EINVAL; \
    Packit 4a16fb
    			res = NULL; \
    Packit 4a16fb
    			break; \
    Packit 4a16fb
    		} \
    Packit 4a16fb
    		free(old_key); \
    Packit 4a16fb
    		first = 0; \
    Packit 4a16fb
    		maxloop--; \
    Packit 4a16fb
    	} \
    Packit 4a16fb
    	free(old_key); \
    Packit 4a16fb
    	if (!res) \
    Packit 4a16fb
    		return err; \
    Packit 4a16fb
    	if (result) \
    Packit 4a16fb
    		*result = res; \
    Packit 4a16fb
    	return 0; \
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    #endif /* DOC_HIDDEN */
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Searches for a node in a configuration tree.
    Packit 4a16fb
     * \param[in] config Handle to the root of the configuration (sub)tree to search.
    Packit 4a16fb
     * \param[in] key Search key: one or more node ids, separated with dots.
    Packit 4a16fb
     * \param[out] result When \a result != \c NULL, the function puts the
    Packit 4a16fb
     *                    handle to the node found at the address specified
    Packit 4a16fb
     *                    by \a result.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This function searches for a child node of \a config that is
    Packit 4a16fb
     * identified by \a key, which contains either the id of a direct child
    Packit 4a16fb
     * node of \a config, or a series of ids, separated with dots, where
    Packit 4a16fb
     * each id specifies a node that is contained in the previous compound
    Packit 4a16fb
     * node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * In the following example, the comment after each node shows the
    Packit 4a16fb
     * search key to find that node, assuming that \a config is a handle to
    Packit 4a16fb
     * the compound node with id \c config:
    Packit 4a16fb
     * \code
    Packit 4a16fb
     * config {
    Packit 4a16fb
     *     a 42               # "a"
    Packit 4a16fb
     *     b {                # "b"
    Packit 4a16fb
     *         c "cee"        # "b.c"
    Packit 4a16fb
     *         d {            # "b.d"
    Packit 4a16fb
     *             e 2.71828  # "b.d.e"
    Packit 4a16fb
     *         }
    Packit 4a16fb
     *     }
    Packit 4a16fb
     * }
    Packit 4a16fb
     * \endcode
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOENT
    An id in \a key does not exist.
    Packit 4a16fb
     * 
    -ENOENT
    \a config or one of its child nodes to be searched is
    Packit 4a16fb
     *                not a compound node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Conforming to:
    Packit 4a16fb
     * LSB 3.2
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
    Packit 4a16fb
    {
    Packit 4a16fb
    	SND_CONFIG_SEARCH(config, key, result, );
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Searches for a node in a configuration tree, expanding aliases.
    Packit 4a16fb
     * \param[in] root Handle to the root configuration node containing
    Packit 4a16fb
     *                 alias definitions.
    Packit 4a16fb
     * \param[in] config Handle to the root of the configuration (sub)tree to search.
    Packit 4a16fb
     * \param[in] key Search key: one or more node keys, separated with dots.
    Packit 4a16fb
     * \param[out] result When \a result != \c NULL, the function puts the
    Packit 4a16fb
     *                    handle to the node found at the address specified
    Packit 4a16fb
     *                    by \a result.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This functions searches for a child node of \a config like
    Packit 4a16fb
     * #snd_config_search.  However, any compound node can also be
    Packit 4a16fb
     * identified by an alias, which is a string node whose value is taken
    Packit 4a16fb
     * as the id of a compound node below \a root.
    Packit 4a16fb
     *
    Packit 4a16fb
     * \a root must be a compound node.
    Packit 4a16fb
     * \a root and \a config may be the same node.
    Packit 4a16fb
     *
    Packit 4a16fb
     * For example, with the following configuration, the call
    Packit 4a16fb
     * \code
    Packit 4a16fb
     * snd_config_searcha(root, config, "a.b.c.d", &result);
    Packit 4a16fb
     * \endcode
    Packit 4a16fb
     * would return the node with id \c d:
    Packit 4a16fb
     * \code
    Packit 4a16fb
     * config {
    Packit 4a16fb
     *     a {
    Packit 4a16fb
     *         b bb
    Packit 4a16fb
     *     }
    Packit 4a16fb
     * }
    Packit 4a16fb
     * root {
    Packit 4a16fb
     *     bb {
    Packit 4a16fb
     *         c cc
    Packit 4a16fb
     *     }
    Packit 4a16fb
     *     cc ccc
    Packit 4a16fb
     *     ccc {
    Packit 4a16fb
     *         d {
    Packit 4a16fb
     *             x "icks"
    Packit 4a16fb
     *         }
    Packit 4a16fb
     *     }
    Packit 4a16fb
     * }
    Packit 4a16fb
     * \endcode
    Packit 4a16fb
     *
    Packit 4a16fb
     * \par Errors:
    Packit 4a16fb
     * 
    Packit 4a16fb
     * 
    -ENOENT
    An id in \a key or an alias id does not exist.
    Packit 4a16fb
     * 
    -ENOENT
    \a config or one of its child nodes to be searched is
    Packit 4a16fb
     *                not a compound or string node.
    Packit 4a16fb
     * 
    Packit 4a16fb
     */
    Packit 4a16fb
    int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
    Packit 4a16fb
    {
    Packit 4a16fb
    	SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, );
    Packit 4a16fb
    }
    Packit 4a16fb
    Packit 4a16fb
    /**
    Packit 4a16fb
     * \brief Searches for a node in a configuration tree.
    Packit 4a16fb
     * \param[in] config Handle to the root of the configuration (sub)tree to search.
    Packit 4a16fb
     * \param[out] result When \a result != \c NULL, the function puts the
    Packit 4a16fb
     *                    handle to the node found at the address specified
    Packit 4a16fb
     *                    by \a result.
    Packit 4a16fb
     * \param[in] ... One or more concatenated dot-separated search keys,
    Packit 4a16fb
     *                terminated with \c NULL.
    Packit 4a16fb
     * \return Zero if successful, otherwise a negative error code.
    Packit 4a16fb
     *
    Packit 4a16fb
     * This functions searches for a child node of \a config like
    Packit 4a16fb
     * #snd_config_search, but the search key is the concatenation of all
    Packit 4a16fb
     * passed search key strings.  For example, the call
    Packit 4a16fb
     * \code
    Packit 4a16fb
     * snd_config_searchv(cfg, &res, "a", "b.c", "d.e", NULL);
    Packit 4a16fb
     * \endcode
    Packit 4a16fb
     * is equivalent to the call
    Packit 4a16fb
     * \code
    Packit 4a16fb
     * snd_config_search(cfg, "a.b.c.d.e", &res;;
    Packit 4a16fb
     * \endcode
    Packit 4a16fb