1/**
2 * \file conf.c
3 * \ingroup Configuration
4 * \brief Configuration helper functions
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \author Jaroslav Kysela <perex@perex.cz>
7 * \date 2000-2001
8 *
9 * Tree based, full nesting configuration functions.
10 *
11 * See the \ref conf page for more details.
12 */
13/*
14 *  Configuration helper functions
15 *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>,
16 *			  Jaroslav Kysela <perex@perex.cz>
17 *
18 *
19 *   This library is free software; you can redistribute it and/or modify
20 *   it under the terms of the GNU Lesser General Public License as
21 *   published by the Free Software Foundation; either version 2.1 of
22 *   the License, or (at your option) any later version.
23 *
24 *   This program is distributed in the hope that it will be useful,
25 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
26 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27 *   GNU Lesser General Public License for more details.
28 *
29 *   You should have received a copy of the GNU Lesser General Public
30 *   License along with this library; if not, write to the Free Software
31 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
32 *
33 */
34
35/*! \page conf Configuration files
36
37<P>Configuration files use a simple format allowing modern
38data description like nesting and array assignments.</P>
39
40\section conf_whitespace Whitespace
41
42Whitespace is the collective name given to spaces (blanks), horizontal and
43vertical tabs, newline characters, and comments. Whitespace can
44indicate where configuration tokens start and end, but beyond this function,
45any surplus whitespace is discarded. For example, the two sequences
46
47\code
48  a 1 b 2
49\endcode
50
51and
52
53\code
54  a 1
55     b 2
56\endcode
57
58are lexically equivalent and parse identically to give the four tokens:
59
60\code
61a
621
63b
642
65\endcode
66
67The ASCII characters representing whitespace can occur within literal
68strings, in which case they are protected from the normal parsing process
69(they remain as part of the string). For example:
70
71\code
72  name "John Smith"
73\endcode
74
75parses to two tokens, including the single literal-string token "John
76Smith".
77
78\section conf_linesplicing Line continuation with \
79
80A special case occurs if a newline character in a string is preceded
81by a backslash (\). The backslash and the new line are both discarded,
82allowing two physical lines of text to be treated as one unit.
83
84\code
85"John \
86Smith"
87\endcode
88
89is parsed as "John Smith".
90
91\section conf_comments Comments
92
93A single-line comment begins with the character #. The comment can start
94at any position, and extends to the end of the line.
95
96\code
97  a 1  # this is a comment
98\endcode
99
100\section conf_include Including configuration files
101
102To include another configuration file, write the file name in angle brackets.
103The prefix \c confdir: will reference the global configuration directory.
104
105\code
106</etc/alsa1.conf>
107<confdir:pcm/surround.conf>
108\endcode
109
110\section conf_punctuators Punctuators
111
112The configuration punctuators (also known as separators) are:
113
114\code
115  {} [] , ; = . ' " new-line form-feed carriage-return whitespace
116\endcode
117
118\subsection conf_braces Braces
119
120Opening and closing braces { } indicate the start and end of a compound
121statement:
122
123\code
124a {
125  b 1
126}
127\endcode
128
129\subsection conf_brackets Brackets
130
131Opening and closing brackets indicate a single array definition. The
132identifiers are automatically generated starting with zero.
133
134\code
135a [
136  "first"
137  "second"
138]
139\endcode
140
141The above code is equal to
142
143\code
144a.0 "first"
145a.1 "second"
146\endcode
147
148\subsection conf_comma_semicolon Comma and semicolon
149
150The comma (,) or semicolon (;) can separate value assignments. It is not
151strictly required to use these separators because whitespace suffices to
152separate tokens.
153
154\code
155a 1;
156b 1,
157\endcode
158
159\subsection conf_equal Equal sign
160
161The equal sign (=) can separate variable declarations from
162initialization lists:
163
164\code
165a=1
166b=2
167\endcode
168
169Using equal signs is not required because whitespace suffices to separate
170tokens.
171
172\section conf_assigns Assignments
173
174The configuration file defines id (key) and value pairs. The id (key) can be
175composed from ASCII digits, characters from a to z and A to Z, and the
176underscore (_). The value can be either a string, an integer, a real number,
177or a compound statement.
178
179\subsection conf_single Single assignments
180
181\code
182a 1	# is equal to
183a=1	# is equal to
184a=1;	# is equal to
185a 1,
186\endcode
187
188\subsection conf_compound Compound assignments (definitions using braces)
189
190\code
191a {
192  b = 1
193}
194a={
195  b 1,
196}
197\endcode
198
199\section conf_compound1 Compound assignments (one key definitions)
200
201\code
202a.b 1
203a.b=1
204\endcode
205
206\subsection conf_array Array assignments (definitions using brackets)
207
208\code
209a [
210  "first"
211  "second"
212]
213\endcode
214
215\subsection conf_array1 Array assignments (one key definitions)
216
217\code
218a.0 "first"
219a.1 "second"
220\endcode
221
222\section conf_mode Operation modes for parsing nodes
223
224By default, the node operation mode is 'merge+create', i.e., if
225a configuration node is not present a new one is created, otherwise
226the latest assignment is merged (if possible - type checking). The
227'merge+create' operation mode is specified with the prefix character plus (+).
228
229The operation mode 'merge' merges the node with the old one (which must
230exist). Type checking is done, so strings cannot be assigned to integers
231and so on. This mode is specified with the prefix character minus (-).
232
233The operation mode 'do not override' ignores a new configuration node
234if a configuration node with the same name exists. This mode is specified with
235the prefix character question mark (?).
236
237The operation mode 'override' always overrides the old configuration node
238with new contents. This mode is specified with the prefix character
239exclamation mark (!).
240
241\code
242defaults.pcm.!device 1
243\endcode
244
245\section conf_syntax_summary Syntax summary
246
247\code
248# Configuration file syntax
249
250# Include a new configuration file
251<filename>
252
253# Simple assignment
254name [=] value [,|;]
255
256# Compound assignment (first style)
257name [=] {
258        name1 [=] value [,|;]
259        ...
260}
261
262# Compound assignment (second style)
263name.name1 [=] value [,|;]
264
265# Array assignment (first style)
266name [
267        value0 [,|;]
268        value1 [,|;]
269        ...
270]
271
272# Array assignment (second style)
273name.0 [=] value0 [,|;]
274name.1 [=] value1 [,|;]
275\endcode
276
277\section conf_syntax_ref References
278
279\ref confarg
280\ref conffunc
281\ref confhooks
282
283*/
284
285/*! \page confarg Runtime arguments in configuration files
286
287<P>The ALSA library can accept runtime arguments for some configuration
288blocks. This extension is built on top of the basic configuration file
289syntax.<P>
290
291\section confarg_define Defining arguments
292
293Arguments are defined using the id (key) \c \@args and array values containing
294the string names of the arguments:
295
296\code
297@args [ CARD ]	# or
298@args.0 CARD
299\endcode
300
301\section confarg_type Defining argument types and default values
302
303An argument's type is specified with the id (key) \c \@args and the argument
304name. The type and the default value are specified in the compound block:
305
306\code
307@args.CARD {
308  type string
309  default "abcd"
310}
311\endcode
312
313\section confarg_refer Referring to arguments
314
315Arguments are referred to with a dollar-sign ($) and the name of the argument:
316
317\code
318  card $CARD
319\endcode
320
321\section confarg_usage Usage
322
323To use a block with arguments, write the argument values after the key,
324separated with a colon (:). For example, all these names for PCM interfaces
325give the same result:
326
327\code
328hw:0,1
329hw:CARD=0,DEV=1
330hw:{CARD 0 DEV 1}
331plug:"hw:0,1"
332plug:{SLAVE="hw:{CARD 0 DEV 1}"}
333\endcode
334
335As you see, arguments can be specified in their proper order or by name.
336Note that arguments enclosed in braces are parsed in the same way as in
337configuration files, but using the override method by default.
338
339\section confarg_example Example
340
341\code
342pcm.demo {
343	@args [ CARD DEVICE ]
344	@args.CARD {
345		type string
346		default "supersonic"
347	}
348	@args.DEVICE {
349		type integer
350		default 0
351	}
352	type hw
353	card $CARD
354	device $DEVICE
355}
356\endcode
357
358*/
359
360/*! \page conffunc Runtime functions in configuration files
361
362<P>The ALSA library can modify the configuration at runtime.
363Several built-in functions are available.</P>
364
365<P>A function is defined with the id \c \@func and the function name. All other
366values in the current compound are used as configuration for the function.
367If the compound func.\<function_name\> is defined in the root node, then the
368library and function from this compound configuration are used, otherwise
369'snd_func_' is prefixed to the string and code from the ALSA library is used.
370The definition of a function looks like:</P>
371
372\code
373func.remove_first_char {
374	lib "/usr/lib/libasoundextend.so"
375	func "extend_remove_first_char"
376}
377\endcode
378
379*/
380
381/*! \page confhooks Hooks in configuration files
382
383<P>The hook extension in the ALSA library allows expansion of configuration
384nodes at run-time. The existence of a hook is determined by the
385presence of a \@hooks compound node.</P>
386
387<P>This example defines a hook which loads two configuration files at the
388beginning:</P>
389
390\code
391@hooks [
392	{
393		func load
394		files [
395			"/etc/asound.conf"
396			"~/.asoundrc"
397		]
398		errors false
399	}
400]
401\endcode
402
403\section confhooks_ref Function reference
404
405<UL>
406  <LI>The function load - \c snd_config_hook_load() - loads and parses the
407      given configuration files.
408  <LI>The function load_for_all_cards - \c snd_config_hook_load_for_all_cards() -
409      loads and parses the given configuration files for each installed sound
410      card. The driver name (the type of the sound card) is passed in the
411      private configuration node.
412</UL>
413
414*/
415
416
417#include <stdarg.h>
418#include <limits.h>
419#include <sys/stat.h>
420#include <dirent.h>
421#include <locale.h>
422#include "local.h"
423#ifdef HAVE_LIBPTHREAD
424#include <pthread.h>
425#endif
426
427#ifndef DOC_HIDDEN
428
429#ifdef HAVE_LIBPTHREAD
430static pthread_mutex_t snd_config_update_mutex =
431				PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
432#endif
433
434struct _snd_config {
435	char *id;
436	snd_config_type_t type;
437	union {
438		long integer;
439		long long integer64;
440		char *string;
441		double real;
442		const void *ptr;
443		struct {
444			struct list_head fields;
445			int join;
446		} compound;
447	} u;
448	struct list_head list;
449	snd_config_t *parent;
450	int hop;
451};
452
453struct filedesc {
454	char *name;
455	snd_input_t *in;
456	unsigned int line, column;
457	struct filedesc *next;
458};
459
460#define LOCAL_ERROR			(-0x68000000)
461
462#define LOCAL_UNTERMINATED_STRING 	(LOCAL_ERROR - 0)
463#define LOCAL_UNTERMINATED_QUOTE	(LOCAL_ERROR - 1)
464#define LOCAL_UNEXPECTED_CHAR		(LOCAL_ERROR - 2)
465#define LOCAL_UNEXPECTED_EOF		(LOCAL_ERROR - 3)
466
467typedef struct {
468	struct filedesc *current;
469	int unget;
470	int ch;
471} input_t;
472
473#ifdef HAVE_LIBPTHREAD
474
475static inline void snd_config_lock(void)
476{
477	pthread_mutex_lock(&snd_config_update_mutex);
478}
479
480static inline void snd_config_unlock(void)
481{
482	pthread_mutex_unlock(&snd_config_update_mutex);
483}
484
485#else
486
487static inline void snd_config_lock(void) { }
488static inline void snd_config_unlock(void) { }
489
490#endif
491
492static int safe_strtoll(const char *str, long long *val)
493{
494	long long v;
495	int endidx;
496	if (!*str)
497		return -EINVAL;
498	errno = 0;
499	if (sscanf(str, "%lli%n", &v, &endidx) < 1)
500		return -EINVAL;
501	if (str[endidx])
502		return -EINVAL;
503	*val = v;
504	return 0;
505}
506
507int safe_strtol(const char *str, long *val)
508{
509	char *end;
510	long v;
511	if (!*str)
512		return -EINVAL;
513	errno = 0;
514	v = strtol(str, &end, 0);
515	if (errno)
516		return -errno;
517	if (*end)
518		return -EINVAL;
519	*val = v;
520	return 0;
521}
522
523static int safe_strtod(const char *str, double *val)
524{
525	char *end;
526	double v;
527#ifdef HAVE_USELOCALE
528	locale_t saved_locale, c_locale;
529#else
530	char *saved_locale;
531	char locstr[64]; /* enough? */
532#endif
533	int err;
534
535	if (!*str)
536		return -EINVAL;
537#ifdef HAVE_USELOCALE
538	c_locale = newlocale(LC_NUMERIC_MASK, "C", 0);
539	saved_locale = uselocale(c_locale);
540#else
541	saved_locale = setlocale(LC_NUMERIC, NULL);
542	if (saved_locale) {
543		snprintf(locstr, sizeof(locstr), "%s", saved_locale);
544		setlocale(LC_NUMERIC, "C");
545	}
546#endif
547	errno = 0;
548	v = strtod(str, &end);
549	err = -errno;
550#ifdef HAVE_USELOCALE
551	if (c_locale != (locale_t)0) {
552		uselocale(saved_locale);
553		freelocale(c_locale);
554	}
555#else
556	if (saved_locale)
557		setlocale(LC_NUMERIC, locstr);
558#endif
559	if (err)
560		return err;
561	if (*end)
562		return -EINVAL;
563	*val = v;
564	return 0;
565}
566
567static int get_char(input_t *input)
568{
569	int c;
570	struct filedesc *fd;
571	if (input->unget) {
572		input->unget = 0;
573		return input->ch;
574	}
575 again:
576	fd = input->current;
577	c = snd_input_getc(fd->in);
578	switch (c) {
579	case '\n':
580		fd->column = 0;
581		fd->line++;
582		break;
583	case '\t':
584		fd->column += 8 - fd->column % 8;
585		break;
586	case EOF:
587		if (fd->next) {
588			snd_input_close(fd->in);
589			free(fd->name);
590			input->current = fd->next;
591			free(fd);
592			goto again;
593		}
594		return LOCAL_UNEXPECTED_EOF;
595	default:
596		fd->column++;
597		break;
598	}
599	return (unsigned char)c;
600}
601
602static void unget_char(int c, input_t *input)
603{
604	assert(!input->unget);
605	input->ch = c;
606	input->unget = 1;
607}
608
609static int get_delimstring(char **string, int delim, input_t *input);
610
611static int get_char_skip_comments(input_t *input)
612{
613	int c;
614	while (1) {
615		c = get_char(input);
616		if (c == '<') {
617			char *str;
618			snd_input_t *in;
619			struct filedesc *fd;
620			int err = get_delimstring(&str, '>', input);
621			if (err < 0)
622				return err;
623			if (!strncmp(str, "confdir:", 8)) {
624				char *tmp = malloc(strlen(ALSA_CONFIG_DIR) + 1 + strlen(str + 8) + 1);
625				if (tmp == NULL) {
626					free(str);
627					return -ENOMEM;
628				}
629				sprintf(tmp, ALSA_CONFIG_DIR "/%s", str + 8);
630				free(str);
631				str = tmp;
632			}
633			err = snd_input_stdio_open(&in, str, "r");
634			if (err < 0) {
635				SNDERR("Cannot access file %s", str);
636				free(str);
637				return err;
638			}
639			fd = malloc(sizeof(*fd));
640			if (!fd) {
641				free(str);
642				return -ENOMEM;
643			}
644			fd->name = str;
645			fd->in = in;
646			fd->next = input->current;
647			fd->line = 1;
648			fd->column = 0;
649			input->current = fd;
650			continue;
651		}
652		if (c != '#')
653			break;
654		while (1) {
655			c = get_char(input);
656			if (c < 0)
657				return c;
658			if (c == '\n')
659				break;
660		}
661	}
662
663	return c;
664}
665
666
667static int get_nonwhite(input_t *input)
668{
669	int c;
670	while (1) {
671		c = get_char_skip_comments(input);
672		switch (c) {
673		case ' ':
674		case '\f':
675		case '\t':
676		case '\n':
677		case '\r':
678			break;
679		default:
680			return c;
681		}
682	}
683}
684
685static int get_quotedchar(input_t *input)
686{
687	int c;
688	c = get_char(input);
689	switch (c) {
690	case 'n':
691		return '\n';
692	case 't':
693		return '\t';
694	case 'v':
695		return '\v';
696	case 'b':
697		return '\b';
698	case 'r':
699		return '\r';
700	case 'f':
701		return '\f';
702	case '0' ... '7':
703	{
704		int num = c - '0';
705		int i = 1;
706		do {
707			c = get_char(input);
708			if (c < '0' || c > '7') {
709				unget_char(c, input);
710				break;
711			}
712			num = num * 8 + c - '0';
713			i++;
714		} while (i < 3);
715		return num;
716	}
717	default:
718		return c;
719	}
720}
721
722#define LOCAL_STR_BUFSIZE	64
723struct local_string {
724	char *buf;
725	size_t alloc;
726	size_t idx;
727	char tmpbuf[LOCAL_STR_BUFSIZE];
728};
729
730static void init_local_string(struct local_string *s)
731{
732	memset(s, 0, sizeof(*s));
733	s->buf = s->tmpbuf;
734	s->alloc = LOCAL_STR_BUFSIZE;
735}
736
737static void free_local_string(struct local_string *s)
738{
739	if (s->buf != s->tmpbuf)
740		free(s->buf);
741}
742
743static int add_char_local_string(struct local_string *s, int c)
744{
745	if (s->idx >= s->alloc) {
746		size_t nalloc = s->alloc * 2;
747		if (s->buf == s->tmpbuf) {
748			s->buf = malloc(nalloc);
749			if (s->buf == NULL)
750				return -ENOMEM;
751			memcpy(s->buf, s->tmpbuf, s->alloc);
752		} else {
753			char *ptr = realloc(s->buf, nalloc);
754			if (ptr == NULL)
755				return -ENOMEM;
756			s->buf = ptr;
757		}
758		s->alloc = nalloc;
759	}
760	s->buf[s->idx++] = c;
761	return 0;
762}
763
764static char *copy_local_string(struct local_string *s)
765{
766	char *dst = malloc(s->idx + 1);
767	if (dst) {
768		memcpy(dst, s->buf, s->idx);
769		dst[s->idx] = '\0';
770	}
771	return dst;
772}
773
774static int get_freestring(char **string, int id, input_t *input)
775{
776	struct local_string str;
777	int c;
778
779	init_local_string(&str);
780	while (1) {
781		c = get_char(input);
782		if (c < 0) {
783			if (c == LOCAL_UNEXPECTED_EOF) {
784				*string = copy_local_string(&str);
785				if (! *string)
786					c = -ENOMEM;
787				else
788					c = 0;
789			}
790			break;
791		}
792		switch (c) {
793		case '.':
794			if (!id)
795				break;
796		case ' ':
797		case '\f':
798		case '\t':
799		case '\n':
800		case '\r':
801		case '=':
802		case ',':
803		case ';':
804		case '{':
805		case '}':
806		case '[':
807		case ']':
808		case '\'':
809		case '"':
810		case '\\':
811		case '#':
812			*string = copy_local_string(&str);
813			if (! *string)
814				c = -ENOMEM;
815			else {
816				unget_char(c, input);
817				c = 0;
818			}
819			goto _out;
820		default:
821			break;
822		}
823		if (add_char_local_string(&str, c) < 0) {
824			c = -ENOMEM;
825			break;
826		}
827	}
828 _out:
829	free_local_string(&str);
830	return c;
831}
832
833static int get_delimstring(char **string, int delim, input_t *input)
834{
835	struct local_string str;
836	int c;
837
838	init_local_string(&str);
839	while (1) {
840		c = get_char(input);
841		if (c < 0)
842			break;
843		if (c == '\\') {
844			c = get_quotedchar(input);
845			if (c < 0)
846				break;
847			if (c == '\n')
848				continue;
849		} else if (c == delim) {
850			*string = copy_local_string(&str);
851			if (! *string)
852				c = -ENOMEM;
853			else
854				c = 0;
855			break;
856		}
857		if (add_char_local_string(&str, c) < 0) {
858			c = -ENOMEM;
859			break;
860		}
861	}
862	 free_local_string(&str);
863	 return c;
864}
865
866/* Return 0 for free string, 1 for delimited string */
867static int get_string(char **string, int id, input_t *input)
868{
869	int c = get_nonwhite(input), err;
870	if (c < 0)
871		return c;
872	switch (c) {
873	case '=':
874	case ',':
875	case ';':
876	case '.':
877	case '{':
878	case '}':
879	case '[':
880	case ']':
881	case '\\':
882		return LOCAL_UNEXPECTED_CHAR;
883	case '\'':
884	case '"':
885		err = get_delimstring(string, c, input);
886		if (err < 0)
887			return err;
888		return 1;
889	default:
890		unget_char(c, input);
891		err = get_freestring(string, id, input);
892		if (err < 0)
893			return err;
894		return 0;
895	}
896}
897
898static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
899{
900	snd_config_t *n;
901	assert(config);
902	n = calloc(1, sizeof(*n));
903	if (n == NULL) {
904		if (*id) {
905			free(*id);
906			*id = NULL;
907		}
908		return -ENOMEM;
909	}
910	if (id) {
911		n->id = *id;
912		*id = NULL;
913	}
914	n->type = type;
915	if (type == SND_CONFIG_TYPE_COMPOUND)
916		INIT_LIST_HEAD(&n->u.compound.fields);
917	*config = n;
918	return 0;
919}
920
921
922static int _snd_config_make_add(snd_config_t **config, char **id,
923				snd_config_type_t type, snd_config_t *parent)
924{
925	snd_config_t *n;
926	int err;
927	assert(parent->type == SND_CONFIG_TYPE_COMPOUND);
928	err = _snd_config_make(&n, id, type);
929	if (err < 0)
930		return err;
931	n->parent = parent;
932	list_add_tail(&n->list, &parent->u.compound.fields);
933	*config = n;
934	return 0;
935}
936
937static int _snd_config_search(snd_config_t *config,
938			      const char *id, int len, snd_config_t **result)
939{
940	snd_config_iterator_t i, next;
941	snd_config_for_each(i, next, config) {
942		snd_config_t *n = snd_config_iterator_entry(i);
943		if (len < 0) {
944			if (strcmp(n->id, id) != 0)
945				continue;
946		} else if (strlen(n->id) != (size_t) len ||
947			   memcmp(n->id, id, (size_t) len) != 0)
948				continue;
949		if (result)
950			*result = n;
951		return 0;
952	}
953	return -ENOENT;
954}
955
956static int parse_value(snd_config_t **_n, snd_config_t *parent, input_t *input, char **id, int skip)
957{
958	snd_config_t *n = *_n;
959	char *s;
960	int err;
961
962	err = get_string(&s, 0, input);
963	if (err < 0)
964		return err;
965	if (skip) {
966		free(s);
967		return 0;
968	}
969	if (err == 0 && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) {
970		long long i;
971		errno = 0;
972		err = safe_strtoll(s, &i);
973		if (err < 0) {
974			double r;
975			err = safe_strtod(s, &r);
976			if (err >= 0) {
977				free(s);
978				if (n) {
979					if (n->type != SND_CONFIG_TYPE_REAL) {
980						SNDERR("%s is not a real", *id);
981						return -EINVAL;
982					}
983				} else {
984					err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, parent);
985					if (err < 0)
986						return err;
987				}
988				n->u.real = r;
989				*_n = n;
990				return 0;
991			}
992		} else {
993			free(s);
994			if (n) {
995				if (n->type != SND_CONFIG_TYPE_INTEGER && n->type != SND_CONFIG_TYPE_INTEGER64) {
996					SNDERR("%s is not an integer", *id);
997					return -EINVAL;
998				}
999			} else {
1000				if (i <= INT_MAX)
1001					err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, parent);
1002				else
1003					err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER64, parent);
1004				if (err < 0)
1005					return err;
1006			}
1007			if (n->type == SND_CONFIG_TYPE_INTEGER)
1008				n->u.integer = (long) i;
1009			else
1010				n->u.integer64 = i;
1011			*_n = n;
1012			return 0;
1013		}
1014	}
1015	if (n) {
1016		if (n->type != SND_CONFIG_TYPE_STRING) {
1017			SNDERR("%s is not a string", *id);
1018			free(s);
1019			return -EINVAL;
1020		}
1021	} else {
1022		err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, parent);
1023		if (err < 0)
1024			return err;
1025	}
1026	free(n->u.string);
1027	n->u.string = s;
1028	*_n = n;
1029	return 0;
1030}
1031
1032static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override);
1033static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override);
1034
1035static int parse_array_def(snd_config_t *parent, input_t *input, int idx, int skip, int override)
1036{
1037	char *id = NULL;
1038	int c;
1039	int err;
1040	snd_config_t *n = NULL;
1041
1042	if (!skip) {
1043		char static_id[12];
1044		snprintf(static_id, sizeof(static_id), "%i", idx);
1045		id = strdup(static_id);
1046		if (id == NULL)
1047			return -ENOMEM;
1048	}
1049	c = get_nonwhite(input);
1050	if (c < 0) {
1051		err = c;
1052		goto __end;
1053	}
1054	switch (c) {
1055	case '{':
1056	case '[':
1057	{
1058		char endchr;
1059		if (!skip) {
1060			if (n) {
1061				if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1062					SNDERR("%s is not a compound", id);
1063					err = -EINVAL;
1064					goto __end;
1065				}
1066			} else {
1067				err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1068				if (err < 0)
1069					goto __end;
1070			}
1071		}
1072		if (c == '{') {
1073			err = parse_defs(n, input, skip, override);
1074			endchr = '}';
1075		} else {
1076			err = parse_array_defs(n, input, skip, override);
1077			endchr = ']';
1078		}
1079		c = get_nonwhite(input);
1080		if (c < 0) {
1081			err = c;
1082			goto __end;
1083		}
1084		if (c != endchr) {
1085			if (n)
1086				snd_config_delete(n);
1087			err = LOCAL_UNEXPECTED_CHAR;
1088			goto __end;
1089		}
1090		break;
1091	}
1092	default:
1093		unget_char(c, input);
1094		err = parse_value(&n, parent, input, &id, skip);
1095		if (err < 0)
1096			goto __end;
1097		break;
1098	}
1099	err = 0;
1100      __end:
1101	free(id);
1102      	return err;
1103}
1104
1105static int parse_array_defs(snd_config_t *parent, input_t *input, int skip, int override)
1106{
1107	int idx = 0;
1108	while (1) {
1109		int c = get_nonwhite(input), err;
1110		if (c < 0)
1111			return c;
1112		unget_char(c, input);
1113		if (c == ']')
1114			return 0;
1115		err = parse_array_def(parent, input, idx++, skip, override);
1116		if (err < 0)
1117			return err;
1118	}
1119	return 0;
1120}
1121
1122static int parse_def(snd_config_t *parent, input_t *input, int skip, int override)
1123{
1124	char *id = NULL;
1125	int c;
1126	int err;
1127	snd_config_t *n;
1128	enum {MERGE_CREATE, MERGE, OVERRIDE, DONT_OVERRIDE} mode;
1129	while (1) {
1130		c = get_nonwhite(input);
1131		if (c < 0)
1132			return c;
1133		switch (c) {
1134		case '+':
1135			mode = MERGE_CREATE;
1136			break;
1137		case '-':
1138			mode = MERGE;
1139			break;
1140		case '?':
1141			mode = DONT_OVERRIDE;
1142			break;
1143		case '!':
1144			mode = OVERRIDE;
1145			break;
1146		default:
1147			mode = !override ? MERGE_CREATE : OVERRIDE;
1148			unget_char(c, input);
1149		}
1150		err = get_string(&id, 1, input);
1151		if (err < 0)
1152			return err;
1153		c = get_nonwhite(input);
1154		if (c != '.')
1155			break;
1156		if (skip) {
1157			free(id);
1158			continue;
1159		}
1160		if (_snd_config_search(parent, id, -1, &n) == 0) {
1161			if (mode == DONT_OVERRIDE) {
1162				skip = 1;
1163				free(id);
1164				continue;
1165			}
1166			if (mode != OVERRIDE) {
1167				if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1168					SNDERR("%s is not a compound", id);
1169					return -EINVAL;
1170				}
1171				n->u.compound.join = 1;
1172				parent = n;
1173				free(id);
1174				continue;
1175			}
1176			snd_config_delete(n);
1177		}
1178		if (mode == MERGE) {
1179			SNDERR("%s does not exists", id);
1180			err = -ENOENT;
1181			goto __end;
1182		}
1183		err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1184		if (err < 0)
1185			goto __end;
1186		n->u.compound.join = 1;
1187		parent = n;
1188	}
1189	if (c == '=') {
1190		c = get_nonwhite(input);
1191		if (c < 0)
1192			return c;
1193	}
1194	if (!skip) {
1195		if (_snd_config_search(parent, id, -1, &n) == 0) {
1196			if (mode == DONT_OVERRIDE) {
1197				skip = 1;
1198				n = NULL;
1199			} else if (mode == OVERRIDE) {
1200				snd_config_delete(n);
1201				n = NULL;
1202			}
1203		} else {
1204			n = NULL;
1205			if (mode == MERGE) {
1206				SNDERR("%s does not exists", id);
1207				err = -ENOENT;
1208				goto __end;
1209			}
1210		}
1211	}
1212	switch (c) {
1213	case '{':
1214	case '[':
1215	{
1216		char endchr;
1217		if (!skip) {
1218			if (n) {
1219				if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1220					SNDERR("%s is not a compound", id);
1221					err = -EINVAL;
1222					goto __end;
1223				}
1224			} else {
1225				err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1226				if (err < 0)
1227					goto __end;
1228			}
1229		}
1230		if (c == '{') {
1231			err = parse_defs(n, input, skip, override);
1232			endchr = '}';
1233		} else {
1234			err = parse_array_defs(n, input, skip, override);
1235			endchr = ']';
1236		}
1237		c = get_nonwhite(input);
1238		if (c != endchr) {
1239			if (n)
1240				snd_config_delete(n);
1241			err = LOCAL_UNEXPECTED_CHAR;
1242			goto __end;
1243		}
1244		break;
1245	}
1246	default:
1247		unget_char(c, input);
1248		err = parse_value(&n, parent, input, &id, skip);
1249		if (err < 0)
1250			goto __end;
1251		break;
1252	}
1253	c = get_nonwhite(input);
1254	switch (c) {
1255	case ';':
1256	case ',':
1257		break;
1258	default:
1259		unget_char(c, input);
1260	}
1261      __end:
1262	free(id);
1263	return err;
1264}
1265
1266static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override)
1267{
1268	int c, err;
1269	while (1) {
1270		c = get_nonwhite(input);
1271		if (c < 0)
1272			return c == LOCAL_UNEXPECTED_EOF ? 0 : c;
1273		unget_char(c, input);
1274		if (c == '}')
1275			return 0;
1276		err = parse_def(parent, input, skip, override);
1277		if (err < 0)
1278			return err;
1279	}
1280	return 0;
1281}
1282
1283static void string_print(char *str, int id, snd_output_t *out)
1284{
1285	unsigned char *p = (unsigned char *)str;
1286	if (!p || !*p) {
1287		snd_output_puts(out, "''");
1288		return;
1289	}
1290	if (!id) {
1291		switch (*p) {
1292		case '0' ... '9':
1293		case '-':
1294			goto quoted;
1295		}
1296	}
1297 loop:
1298	switch (*p) {
1299	case 0:
1300		goto nonquoted;
1301	case 1 ... 31:
1302	case 127 ... 255:
1303	case ' ':
1304	case '=':
1305	case ';':
1306	case ',':
1307	case '.':
1308	case '{':
1309	case '}':
1310	case '\'':
1311	case '"':
1312		goto quoted;
1313	default:
1314		p++;
1315		goto loop;
1316	}
1317 nonquoted:
1318	snd_output_puts(out, str);
1319	return;
1320 quoted:
1321	snd_output_putc(out, '\'');
1322	p = (unsigned char *)str;
1323	while (*p) {
1324		int c;
1325		c = *p;
1326		switch (c) {
1327		case '\n':
1328			snd_output_putc(out, '\\');
1329			snd_output_putc(out, 'n');
1330			break;
1331		case '\t':
1332			snd_output_putc(out, '\\');
1333			snd_output_putc(out, 't');
1334			break;
1335		case '\v':
1336			snd_output_putc(out, '\\');
1337			snd_output_putc(out, 'v');
1338			break;
1339		case '\b':
1340			snd_output_putc(out, '\\');
1341			snd_output_putc(out, 'b');
1342			break;
1343		case '\r':
1344			snd_output_putc(out, '\\');
1345			snd_output_putc(out, 'r');
1346			break;
1347		case '\f':
1348			snd_output_putc(out, '\\');
1349			snd_output_putc(out, 'f');
1350			break;
1351		case '\'':
1352			snd_output_putc(out, '\\');
1353			snd_output_putc(out, c);
1354			break;
1355		case 32 ... '\'' - 1:
1356		case '\'' + 1 ... 126:
1357			snd_output_putc(out, c);
1358			break;
1359		default:
1360			snd_output_printf(out, "\\%04o", c);
1361			break;
1362		}
1363		p++;
1364	}
1365	snd_output_putc(out, '\'');
1366}
1367
1368static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1369				     unsigned int level, unsigned int joins);
1370
1371static int _snd_config_save_node_value(snd_config_t *n, snd_output_t *out,
1372				       unsigned int level)
1373{
1374	int err;
1375	unsigned int k;
1376	switch (n->type) {
1377	case SND_CONFIG_TYPE_INTEGER:
1378		snd_output_printf(out, "%ld", n->u.integer);
1379		break;
1380	case SND_CONFIG_TYPE_INTEGER64:
1381		snd_output_printf(out, "%lld", n->u.integer64);
1382		break;
1383	case SND_CONFIG_TYPE_REAL:
1384		snd_output_printf(out, "%-16g", n->u.real);
1385		break;
1386	case SND_CONFIG_TYPE_STRING:
1387		string_print(n->u.string, 0, out);
1388		break;
1389	case SND_CONFIG_TYPE_POINTER:
1390		SNDERR("cannot save runtime pointer type");
1391		return -EINVAL;
1392	case SND_CONFIG_TYPE_COMPOUND:
1393		snd_output_putc(out, '{');
1394		snd_output_putc(out, '\n');
1395		err = _snd_config_save_children(n, out, level + 1, 0);
1396		if (err < 0)
1397			return err;
1398		for (k = 0; k < level; ++k) {
1399			snd_output_putc(out, '\t');
1400		}
1401		snd_output_putc(out, '}');
1402		break;
1403	}
1404	return 0;
1405}
1406
1407static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins)
1408{
1409	if (joins > 0) {
1410		assert(n->parent);
1411		id_print(n->parent, out, joins - 1);
1412		snd_output_putc(out, '.');
1413	}
1414	string_print(n->id, 1, out);
1415}
1416
1417static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1418				     unsigned int level, unsigned int joins)
1419{
1420	unsigned int k;
1421	int err;
1422	snd_config_iterator_t i, next;
1423	assert(config && out);
1424	snd_config_for_each(i, next, config) {
1425		snd_config_t *n = snd_config_iterator_entry(i);
1426		if (n->type == SND_CONFIG_TYPE_COMPOUND &&
1427		    n->u.compound.join) {
1428			err = _snd_config_save_children(n, out, level, joins + 1);
1429			if (err < 0)
1430				return err;
1431			continue;
1432		}
1433		for (k = 0; k < level; ++k) {
1434			snd_output_putc(out, '\t');
1435		}
1436		id_print(n, out, joins);
1437#if 0
1438		snd_output_putc(out, ' ');
1439		snd_output_putc(out, '=');
1440#endif
1441		snd_output_putc(out, ' ');
1442		err = _snd_config_save_node_value(n, out, level);
1443		if (err < 0)
1444			return err;
1445#if 0
1446		snd_output_putc(out, ';');
1447#endif
1448		snd_output_putc(out, '\n');
1449	}
1450	return 0;
1451}
1452#endif
1453
1454
1455/**
1456 * \brief Substitutes one configuration node to another.
1457 * \param dst Handle to the destination node.
1458 * \param src Handle to the source node. Must not be the same as \a dst.
1459 * \return Zero if successful, otherwise a negative error code.
1460 *
1461 * If both nodes are compounds, the source compound node members are
1462 * appended to the destination compound node.
1463 *
1464 * If the destination node is a compound and the source node is
1465 * an ordinary type, the compound members are deleted (including
1466 * their contents).
1467 *
1468 * Otherwise, the source node's value replaces the destination node's
1469 * value.
1470 *
1471 * In any case, a successful call to this function frees the source
1472 * node.
1473 */
1474int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
1475{
1476	assert(dst && src);
1477	if (dst->type == SND_CONFIG_TYPE_COMPOUND &&
1478	    src->type == SND_CONFIG_TYPE_COMPOUND) {	/* append */
1479		snd_config_iterator_t i, next;
1480		snd_config_for_each(i, next, src) {
1481			snd_config_t *n = snd_config_iterator_entry(i);
1482			n->parent = dst;
1483		}
1484		src->u.compound.fields.next->prev = &dst->u.compound.fields;
1485		src->u.compound.fields.prev->next = &dst->u.compound.fields;
1486	} else if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
1487		int err;
1488		err = snd_config_delete_compound_members(dst);
1489		if (err < 0)
1490			return err;
1491	}
1492	free(dst->id);
1493	dst->id = src->id;
1494	dst->type = src->type;
1495	dst->u = src->u;
1496	free(src);
1497	return 0;
1498}
1499
1500/**
1501 * \brief Converts an ASCII string to a configuration node type.
1502 * \param[in] ascii A string containing a configuration node type.
1503 * \param[out] type The node type corresponding to \a ascii.
1504 * \return Zero if successful, otherwise a negative error code.
1505 *
1506 * This function recognizes at least the following node types:
1507 * <dl>
1508 * <dt>integer<dt>#SND_CONFIG_TYPE_INTEGER
1509 * <dt>integer64<dt>#SND_CONFIG_TYPE_INTEGER64
1510 * <dt>real<dt>#SND_CONFIG_TYPE_REAL
1511 * <dt>string<dt>#SND_CONFIG_TYPE_STRING
1512 * <dt>compound<dt>#SND_CONFIG_TYPE_COMPOUND
1513 * </dl>
1514 *
1515 * \par Errors:
1516 * <dl>
1517 * <dt>-EINVAL<dd>Unknown note type in \a type.
1518 * </dl>
1519 */
1520int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
1521{
1522	assert(ascii && type);
1523	if (!strcmp(ascii, "integer")) {
1524		*type = SND_CONFIG_TYPE_INTEGER;
1525		return 0;
1526	}
1527	if (!strcmp(ascii, "integer64")) {
1528		*type = SND_CONFIG_TYPE_INTEGER64;
1529		return 0;
1530	}
1531	if (!strcmp(ascii, "real")) {
1532		*type = SND_CONFIG_TYPE_REAL;
1533		return 0;
1534	}
1535	if (!strcmp(ascii, "string")) {
1536		*type = SND_CONFIG_TYPE_STRING;
1537		return 0;
1538	}
1539	if (!strcmp(ascii, "compound")) {
1540		*type = SND_CONFIG_TYPE_COMPOUND;
1541		return 0;
1542	}
1543	return -EINVAL;
1544}
1545
1546/**
1547 * \brief Returns the type of a configuration node.
1548 * \param config Handle to the configuration node.
1549 * \return The node's type.
1550 *
1551 * \par Conforming to:
1552 * LSB 3.2
1553 */
1554snd_config_type_t snd_config_get_type(const snd_config_t *config)
1555{
1556	return config->type;
1557}
1558
1559/**
1560 * \brief Returns the id of a configuration node.
1561 * \param[in] config Handle to the configuration node.
1562 * \param[out] id The function puts the pointer to the id string at the
1563 *                address specified by \a id.
1564 * \return Zero if successful, otherwise a negative error code.
1565 *
1566 * The returned string is owned by the configuration node; the application
1567 * must not modify or delete it, and the string becomes invalid when the
1568 * node's id changes or when the node is freed.
1569 *
1570 * If the node does not have an id, \a *id is set to \c NULL.
1571 *
1572 * \par Conforming to:
1573 * LSB 3.2
1574 */
1575int snd_config_get_id(const snd_config_t *config, const char **id)
1576{
1577	assert(config && id);
1578	*id = config->id;
1579	return 0;
1580}
1581
1582/**
1583 * \brief Sets the id of a configuration node.
1584 * \param config Handle to the configuration node.
1585 * \param id The new node id, must not be \c NULL.
1586 * \return Zero if successful, otherwise a negative error code.
1587 *
1588 * This function stores a copy of \a id in the node.
1589 *
1590 * \par Errors:
1591 * <dl>
1592 * <dt>-EEXIST<dd>One of \a config's siblings already has the id \a id.
1593 * <dt>-EINVAL<dd>The id of a node with a parent cannot be set to \c NULL.
1594 * <dt>-ENOMEM<dd>Out of memory.
1595 * </dl>
1596 */
1597int snd_config_set_id(snd_config_t *config, const char *id)
1598{
1599	snd_config_iterator_t i, next;
1600	char *new_id;
1601	assert(config);
1602	if (id) {
1603		if (config->parent) {
1604			snd_config_for_each(i, next, config->parent) {
1605				snd_config_t *n = snd_config_iterator_entry(i);
1606				if (n != config && strcmp(id, n->id) == 0)
1607					return -EEXIST;
1608			}
1609		}
1610		new_id = strdup(id);
1611		if (!new_id)
1612			return -ENOMEM;
1613	} else {
1614		if (config->parent)
1615			return -EINVAL;
1616		new_id = NULL;
1617	}
1618	free(config->id);
1619	config->id = new_id;
1620	return 0;
1621}
1622
1623/**
1624 * \brief Creates a top level configuration node.
1625 * \param[out] config Handle to the new node.
1626 * \return Zero if successful, otherwise a negative error code.
1627 *
1628 * The returned node is an empty compound node without a parent and
1629 * without an id.
1630 *
1631 * \par Errors:
1632 * <dl>
1633 * <dt>-ENOMEM<dd>Out of memory.
1634 * </dl>
1635 *
1636 * \par Conforming to:
1637 * LSB 3.2
1638 */
1639int snd_config_top(snd_config_t **config)
1640{
1641	assert(config);
1642	return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
1643}
1644
1645static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override)
1646{
1647	int err;
1648	input_t input;
1649	struct filedesc *fd, *fd_next;
1650	assert(config && in);
1651	fd = malloc(sizeof(*fd));
1652	if (!fd)
1653		return -ENOMEM;
1654	fd->name = NULL;
1655	fd->in = in;
1656	fd->line = 1;
1657	fd->column = 0;
1658	fd->next = NULL;
1659	input.current = fd;
1660	input.unget = 0;
1661	err = parse_defs(config, &input, 0, override);
1662	fd = input.current;
1663	if (err < 0) {
1664		const char *str;
1665		switch (err) {
1666		case LOCAL_UNTERMINATED_STRING:
1667			str = "Unterminated string";
1668			err = -EINVAL;
1669			break;
1670		case LOCAL_UNTERMINATED_QUOTE:
1671			str = "Unterminated quote";
1672			err = -EINVAL;
1673			break;
1674		case LOCAL_UNEXPECTED_CHAR:
1675			str = "Unexpected char";
1676			err = -EINVAL;
1677			break;
1678		case LOCAL_UNEXPECTED_EOF:
1679			str = "Unexpected end of file";
1680			err = -EINVAL;
1681			break;
1682		default:
1683			str = strerror(-err);
1684			break;
1685		}
1686		SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
1687		goto _end;
1688	}
1689	if (get_char(&input) != LOCAL_UNEXPECTED_EOF) {
1690		SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
1691		err = -EINVAL;
1692		goto _end;
1693	}
1694 _end:
1695	while (fd->next) {
1696		fd_next = fd->next;
1697		snd_input_close(fd->in);
1698		free(fd->name);
1699		free(fd);
1700		fd = fd_next;
1701	}
1702	free(fd);
1703	return err;
1704}
1705
1706/**
1707 * \brief Loads a configuration tree.
1708 * \param config Handle to a top level configuration node.
1709 * \param in Input handle to read the configuration from.
1710 * \return Zero if successful, otherwise a negative error code.
1711 *
1712 * The definitions loaded from the input are added to \a config, which
1713 * must be a compound node.
1714 *
1715 * \par Errors:
1716 * Any errors encountered when parsing the input or returned by hooks or
1717 * functions.
1718 *
1719 * \par Conforming to:
1720 * LSB 3.2
1721 */
1722int snd_config_load(snd_config_t *config, snd_input_t *in)
1723{
1724	return snd_config_load1(config, in, 0);
1725}
1726
1727/**
1728 * \brief Loads a configuration tree and overrides existing configuration nodes.
1729 * \param config Handle to a top level configuration node.
1730 * \param in Input handle to read the configuration from.
1731 * \return Zero if successful, otherwise a negative error code.
1732 *
1733 * This function loads definitions from \a in into \a config like
1734 * #snd_config_load, but the default mode for input nodes is 'override'
1735 * (!) instead of 'merge+create' (+).
1736 */
1737int snd_config_load_override(snd_config_t *config, snd_input_t *in)
1738{
1739	return snd_config_load1(config, in, 1);
1740}
1741
1742/**
1743 * \brief Adds a child to a compound configuration node.
1744 * \param parent Handle to a compound configuration node.
1745 * \param child Handle to the configuration node to be added.
1746 * \return Zero if successful, otherwise a negative error code.
1747 *
1748 * This function makes the node \a child a child of the node \a parent.
1749 *
1750 * The parent node then owns the child node, i.e., the child node gets
1751 * deleted together with its parent.
1752 *
1753 * \a child must have an id.
1754 *
1755 * \par Errors:
1756 * <dl>
1757 * <dt>-EINVAL<dd>\a child does not have an id.
1758 * <dt>-EINVAL<dd>\a child already has a parent.
1759 * <dt>-EEXIST<dd>\a parent already contains a child node with the same
1760 *                id as \a child.
1761 * </dl>
1762 *
1763 * \par Conforming to:
1764 * LSB 3.2
1765 */
1766int snd_config_add(snd_config_t *parent, snd_config_t *child)
1767{
1768	snd_config_iterator_t i, next;
1769	assert(parent && child);
1770	if (!child->id || child->parent)
1771		return -EINVAL;
1772	snd_config_for_each(i, next, parent) {
1773		snd_config_t *n = snd_config_iterator_entry(i);
1774		if (strcmp(child->id, n->id) == 0)
1775			return -EEXIST;
1776	}
1777	child->parent = parent;
1778	list_add_tail(&child->list, &parent->u.compound.fields);
1779	return 0;
1780}
1781
1782/**
1783 * \brief Removes a configuration node from its tree.
1784 * \param config Handle to the configuration node to be removed.
1785 * \return Zero if successful, otherwise a negative error code.
1786 *
1787 * This function makes \a config a top-level node, i.e., if \a config
1788 * has a parent, then \a config is removed from the list of the parent's
1789 * children.
1790 *
1791 * This functions does \e not free the removed node.
1792 *
1793 * \sa snd_config_delete
1794 */
1795int snd_config_remove(snd_config_t *config)
1796{
1797	assert(config);
1798	if (config->parent)
1799		list_del(&config->list);
1800	config->parent = NULL;
1801	return 0;
1802}
1803
1804/**
1805 * \brief Frees a configuration node.
1806 * \param config Handle to the configuration node to be deleted.
1807 * \return Zero if successful, otherwise a negative error code.
1808 *
1809 * This function frees a configuration node and all its resources.
1810 *
1811 * If the node is a child node, it is removed from the tree before being
1812 * deleted.
1813 *
1814 * If the node is a compound node, its descendants (the whole subtree)
1815 * are deleted recursively.
1816 *
1817 * \par Conforming to:
1818 * LSB 3.2
1819 *
1820 * \sa snd_config_remove
1821 */
1822int snd_config_delete(snd_config_t *config)
1823{
1824	assert(config);
1825	switch (config->type) {
1826	case SND_CONFIG_TYPE_COMPOUND:
1827	{
1828		int err;
1829		struct list_head *i;
1830		i = config->u.compound.fields.next;
1831		while (i != &config->u.compound.fields) {
1832			struct list_head *nexti = i->next;
1833			snd_config_t *child = snd_config_iterator_entry(i);
1834			err = snd_config_delete(child);
1835			if (err < 0)
1836				return err;
1837			i = nexti;
1838		}
1839		break;
1840	}
1841	case SND_CONFIG_TYPE_STRING:
1842		free(config->u.string);
1843		break;
1844	default:
1845		break;
1846	}
1847	if (config->parent)
1848		list_del(&config->list);
1849	free(config->id);
1850	free(config);
1851	return 0;
1852}
1853
1854/**
1855 * \brief Deletes the children of a node.
1856 * \param config Handle to the compound configuration node.
1857 * \return Zero if successful, otherwise a negative error code.
1858 *
1859 * This function removes and frees all children of a configuration node.
1860 *
1861 * Any compound nodes among the children of \a config are deleted
1862 * recursively.
1863 *
1864 * After a successful call to this function, \a config is an empty
1865 * compound node.
1866 *
1867 * \par Errors:
1868 * <dl>
1869 * <dt>-EINVAL<dd>\a config is not a compound node.
1870 * </dl>
1871 */
1872int snd_config_delete_compound_members(const snd_config_t *config)
1873{
1874	int err;
1875	struct list_head *i;
1876
1877	assert(config);
1878	if (config->type != SND_CONFIG_TYPE_COMPOUND)
1879		return -EINVAL;
1880	i = config->u.compound.fields.next;
1881	while (i != &config->u.compound.fields) {
1882		struct list_head *nexti = i->next;
1883		snd_config_t *child = snd_config_iterator_entry(i);
1884		err = snd_config_delete(child);
1885		if (err < 0)
1886			return err;
1887		i = nexti;
1888	}
1889	return 0;
1890}
1891
1892/**
1893 * \brief Creates a configuration node.
1894 * \param[out] config The function puts the handle to the new node at
1895 *                    the address specified by \a config.
1896 * \param[in] id The id of the new node.
1897 * \param[in] type The type of the new node.
1898 * \return Zero if successful, otherwise a negative error code.
1899 *
1900 * This functions creates a new node of the specified type.
1901 * The new node has id \a id, which may be \c NULL.
1902 *
1903 * The value of the new node is zero (for numbers), or \c NULL (for
1904 * strings and pointers), or empty (for compound nodes).
1905 *
1906 * \par Errors:
1907 * <dl>
1908 * <dt>-ENOMEM<dd>Out of memory.
1909 * </dl>
1910 */
1911int snd_config_make(snd_config_t **config, const char *id,
1912		    snd_config_type_t type)
1913{
1914	char *id1;
1915	assert(config);
1916	if (id) {
1917		id1 = strdup(id);
1918		if (!id1)
1919			return -ENOMEM;
1920	} else
1921		id1 = NULL;
1922	return _snd_config_make(config, &id1, type);
1923}
1924
1925/**
1926 * \brief Creates an integer configuration node.
1927 * \param[out] config The function puts the handle to the new node at
1928 *                    the address specified by \a config.
1929 * \param[in] id The id of the new node.
1930 * \return Zero if successful, otherwise a negative error code.
1931 *
1932 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
1933 * with value \c 0.
1934 *
1935 * \par Errors:
1936 * <dl>
1937 * <dt>-ENOMEM<dd>Out of memory.
1938 * </dl>
1939 *
1940 * \par Conforming to:
1941 * LSB 3.2
1942 *
1943 * \sa snd_config_imake_integer
1944 */
1945int snd_config_make_integer(snd_config_t **config, const char *id)
1946{
1947	return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
1948}
1949
1950/**
1951 * \brief Creates a 64-bit-integer configuration node.
1952 * \param[out] config The function puts the handle to the new node at
1953 *                    the address specified by \a config.
1954 * \param[in] id The id of the new node.
1955 * \return Zero if successful, otherwise a negative error code.
1956 *
1957 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
1958 * and with value \c 0.
1959 *
1960 * \par Errors:
1961 * <dl>
1962 * <dt>-ENOMEM<dd>Out of memory.
1963 * </dl>
1964 *
1965 * \par Conforming to:
1966 * LSB 3.2
1967 *
1968 * \sa snd_config_imake_integer64
1969 */
1970int snd_config_make_integer64(snd_config_t **config, const char *id)
1971{
1972	return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
1973}
1974
1975/**
1976 * \brief Creates a real number configuration node.
1977 * \param[out] config The function puts the handle to the new node at
1978 *                    the address specified by \a config.
1979 * \param[in] id The id of the new node.
1980 * \return Zero if successful, otherwise a negative error code.
1981 *
1982 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
1983 * with value \c 0.0.
1984 *
1985 * \par Errors:
1986 * <dl>
1987 * <dt>-ENOMEM<dd>Out of memory.
1988 * </dl>
1989 *
1990 * \sa snd_config_imake_real
1991 */
1992int snd_config_make_real(snd_config_t **config, const char *id)
1993{
1994	return snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
1995}
1996
1997/**
1998 * \brief Creates a string configuration node.
1999 * \param[out] config The function puts the handle to the new node at
2000 *                    the address specified by \a config.
2001 * \param[in] id The id of the new node.
2002 * \return Zero if successful, otherwise a negative error code.
2003 *
2004 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2005 * with value \c NULL.
2006 *
2007 * \par Errors:
2008 * <dl>
2009 * <dt>-ENOMEM<dd>Out of memory.
2010 * </dl>
2011 *
2012 * \par Conforming to:
2013 * LSB 3.2
2014 *
2015 * \sa snd_config_imake_string
2016 */
2017int snd_config_make_string(snd_config_t **config, const char *id)
2018{
2019	return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
2020}
2021
2022/**
2023 * \brief Creates a pointer configuration node.
2024 * \param[out] config The function puts the handle to the new node at
2025 *                    the address specified by \a config.
2026 * \param[in] id The id of the new node.
2027 * \return Zero if successful, otherwise a negative error code.
2028 *
2029 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2030 * with value \c NULL.
2031 *
2032 * \par Errors:
2033 * <dl>
2034 * <dt>-ENOMEM<dd>Out of memory.
2035 * </dl>
2036 *
2037 * \sa snd_config_imake_pointer
2038 */
2039int snd_config_make_pointer(snd_config_t **config, const char *id)
2040{
2041	return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2042}
2043
2044/**
2045 * \brief Creates an empty compound configuration node.
2046 * \param[out] config The function puts the handle to the new node at
2047 *                    the address specified by \a config.
2048 * \param[in] id The id of the new node.
2049 * \param[in] join Join flag.
2050 * \return Zero if successful, otherwise a negative error code.
2051 *
2052 * This function creates a new empty node of type
2053 * #SND_CONFIG_TYPE_COMPOUND.
2054 *
2055 * \a join determines how the compound node's id is printed when the
2056 * configuration is saved to a text file.  For example, if the join flag
2057 * of compound node \c a is zero, the output will look as follows:
2058 * \code
2059 * a {
2060 *     b "hello"
2061 *     c 42
2062 * }
2063 * \endcode
2064 * If, however, the join flag of \c a is nonzero, its id will be joined
2065 * with its children's ids, like this:
2066 * \code
2067 * a.b "hello"
2068 * a.c 42
2069 * \endcode
2070 * An \e empty compound node with its join flag set would result in no
2071 * output, i.e., after saving and reloading the configuration file, that
2072 * compound node would be lost.
2073 *
2074 * \par Errors:
2075 * <dl>
2076 * <dt>-ENOMEM<dd>Out of memory.
2077 * </dl>
2078 *
2079 * \par Conforming to:
2080 * LSB 3.2
2081 */
2082int snd_config_make_compound(snd_config_t **config, const char *id,
2083			     int join)
2084{
2085	int err;
2086	err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND);
2087	if (err < 0)
2088		return err;
2089	(*config)->u.compound.join = join;
2090	return 0;
2091}
2092
2093/**
2094 * \brief Creates an integer configuration node with the given initial value.
2095 * \param[out] config The function puts the handle to the new node at
2096 *                    the address specified by \a config.
2097 * \param[in] id The id of the new node.
2098 * \param[in] value The initial value of the new node.
2099 * \return Zero if successful, otherwise a negative error code.
2100 *
2101 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
2102 * with value \a value.
2103 *
2104 * \par Errors:
2105 * <dl>
2106 * <dt>-ENOMEM<dd>Out of memory.
2107 * </dl>
2108 *
2109 * \par Conforming to:
2110 * LSB 3.2
2111 */
2112int snd_config_imake_integer(snd_config_t **config, const char *id, const long value)
2113{
2114	int err;
2115
2116	err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
2117	if (err < 0)
2118		return err;
2119	(*config)->u.integer = value;
2120	return 0;
2121}
2122
2123/**
2124 * \brief Creates a 64-bit-integer configuration node with the given initial value.
2125 * \param[out] config The function puts the handle to the new node at
2126 *                    the address specified by \a config.
2127 * \param[in] id The id of the new node.
2128 * \param[in] value The initial value of the new node.
2129 * \return Zero if successful, otherwise a negative error code.
2130 *
2131 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
2132 * and with value \a value.
2133 *
2134 * \par Errors:
2135 * <dl>
2136 * <dt>-ENOMEM<dd>Out of memory.
2137 * </dl>
2138 *
2139 * \par Conforming to:
2140 * LSB 3.2
2141 */
2142int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value)
2143{
2144	int err;
2145
2146	err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
2147	if (err < 0)
2148		return err;
2149	(*config)->u.integer64 = value;
2150	return 0;
2151}
2152
2153/**
2154 * \brief Creates a real number configuration node with the given initial value.
2155 * \param[out] config The function puts the handle to the new node at
2156 *                    the address specified by \a config.
2157 * \param[in] id The id of the new node.
2158 * \param[in] value The initial value of the new node.
2159 * \return Zero if successful, otherwise a negative error code.
2160 *
2161 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
2162 * with value \a value.
2163 *
2164 * \par Errors:
2165 * <dl>
2166 * <dt>-ENOMEM<dd>Out of memory.
2167 * </dl>
2168 */
2169int snd_config_imake_real(snd_config_t **config, const char *id, const double value)
2170{
2171	int err;
2172
2173	err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
2174	if (err < 0)
2175		return err;
2176	(*config)->u.real = value;
2177	return 0;
2178}
2179
2180/**
2181 * \brief Creates a string configuration node with the given initial value.
2182 * \param[out] config The function puts the handle to the new node at
2183 *                    the address specified by \a config.
2184 * \param[in] id The id of the new node.
2185 * \param[in] value The initial value of the new node.  May be \c NULL.
2186 * \return Zero if successful, otherwise a negative error code.
2187 *
2188 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2189 * with a copy of the string \c value.
2190 *
2191 * \par Errors:
2192 * <dl>
2193 * <dt>-ENOMEM<dd>Out of memory.
2194 * </dl>
2195 *
2196 * \par Conforming to:
2197 * LSB 3.2
2198 */
2199int snd_config_imake_string(snd_config_t **config, const char *id, const char *value)
2200{
2201	int err;
2202	snd_config_t *tmp;
2203
2204	err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
2205	if (err < 0)
2206		return err;
2207	if (value) {
2208		tmp->u.string = strdup(value);
2209		if (!tmp->u.string) {
2210			snd_config_delete(tmp);
2211			return -ENOMEM;
2212		}
2213	} else {
2214		tmp->u.string = NULL;
2215	}
2216	*config = tmp;
2217	return 0;
2218}
2219
2220/**
2221 * \brief Creates a pointer configuration node with the given initial value.
2222 * \param[out] config The function puts the handle to the new node at
2223 *                    the address specified by \a config.
2224 * \param[in] id The id of the new node.
2225 * \param[in] value The initial value of the new node.
2226 * \return Zero if successful, otherwise a negative error code.
2227 *
2228 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2229 * with value \c value.
2230 *
2231 * \par Errors:
2232 * <dl>
2233 * <dt>-ENOMEM<dd>Out of memory.
2234 * </dl>
2235 */
2236int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value)
2237{
2238	int err;
2239
2240	err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2241	if (err < 0)
2242		return err;
2243	(*config)->u.ptr = value;
2244	return 0;
2245}
2246
2247/**
2248 * \brief Changes the value of an integer configuration node.
2249 * \param config Handle to the configuration node.
2250 * \param value The new value for the node.
2251 * \return Zero if successful, otherwise a negative error code.
2252 *
2253 * \par Errors:
2254 * <dl>
2255 * <dt>-EINVAL<dd>\a config is not an integer node.
2256 * </dl>
2257 *
2258 * \par Conforming to:
2259 * LSB 3.2
2260 */
2261int snd_config_set_integer(snd_config_t *config, long value)
2262{
2263	assert(config);
2264	if (config->type != SND_CONFIG_TYPE_INTEGER)
2265		return -EINVAL;
2266	config->u.integer = value;
2267	return 0;
2268}
2269
2270/**
2271 * \brief Changes the value of a 64-bit-integer configuration node.
2272 * \param config Handle to the configuration node.
2273 * \param value The new value for the node.
2274 * \return Zero if successful, otherwise a negative error code.
2275 *
2276 * \par Errors:
2277 * <dl>
2278 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2279 * </dl>
2280 *
2281 * \par Conforming to:
2282 * LSB 3.2
2283 */
2284int snd_config_set_integer64(snd_config_t *config, long long value)
2285{
2286	assert(config);
2287	if (config->type != SND_CONFIG_TYPE_INTEGER64)
2288		return -EINVAL;
2289	config->u.integer64 = value;
2290	return 0;
2291}
2292
2293/**
2294 * \brief Changes the value of a real-number configuration node.
2295 * \param config Handle to the configuration node.
2296 * \param value The new value for the node.
2297 * \return Zero if successful, otherwise a negative error code.
2298 *
2299 * \par Errors:
2300 * <dl>
2301 * <dt>-EINVAL<dd>\a config is not a real-number node.
2302 * </dl>
2303 */
2304int snd_config_set_real(snd_config_t *config, double value)
2305{
2306	assert(config);
2307	if (config->type != SND_CONFIG_TYPE_REAL)
2308		return -EINVAL;
2309	config->u.real = value;
2310	return 0;
2311}
2312
2313/**
2314 * \brief Changes the value of a string configuration node.
2315 * \param config Handle to the configuration node.
2316 * \param value The new value for the node.  May be \c NULL.
2317 * \return Zero if successful, otherwise a negative error code.
2318 *
2319 * This function deletes the old string in the node and stores a copy of
2320 * \a value string in the node.
2321 *
2322 * \par Errors:
2323 * <dl>
2324 * <dt>-EINVAL<dd>\a config is not a string node.
2325 * </dl>
2326 *
2327 * \par Conforming to:
2328 * LSB 3.2
2329 */
2330int snd_config_set_string(snd_config_t *config, const char *value)
2331{
2332	char *new_string;
2333	assert(config);
2334	if (config->type != SND_CONFIG_TYPE_STRING)
2335		return -EINVAL;
2336	if (value) {
2337		new_string = strdup(value);
2338		if (!new_string)
2339			return -ENOMEM;
2340	} else {
2341		new_string = NULL;
2342	}
2343	free(config->u.string);
2344	config->u.string = new_string;
2345	return 0;
2346}
2347
2348/**
2349 * \brief Changes the value of a pointer configuration node.
2350 * \param config Handle to the configuration node.
2351 * \param value The new value for the node.  May be \c NULL.
2352 * \return Zero if successful, otherwise a negative error code.
2353 *
2354 * This function does not free the old pointer in the node.
2355 *
2356 * \par Errors:
2357 * <dl>
2358 * <dt>-EINVAL<dd>\a config is not a pointer node.
2359 * </dl>
2360 */
2361int snd_config_set_pointer(snd_config_t *config, const void *value)
2362{
2363	assert(config);
2364	if (config->type != SND_CONFIG_TYPE_POINTER)
2365		return -EINVAL;
2366	config->u.ptr = value;
2367	return 0;
2368}
2369
2370/**
2371 * \brief Changes the value of a configuration node.
2372 * \param config Handle to the configuration node.
2373 * \param ascii The new value for the node, as an ASCII string.
2374 * \return Zero if successful, otherwise a negative error code.
2375 *
2376 * This function changes the node's value to a new value that is parsed
2377 * from the string \a ascii.  \a ascii must not be \c NULL, not even for
2378 * a string node.
2379 *
2380 * The node's type does not change, i.e., the string must contain a
2381 * valid value with the same type as the node's type.  For a string
2382 * node, the node's new value is a copy of \a ascii.
2383 *
2384 * \par Errors:
2385 * <dl>
2386 * <dt>-EINVAL<dd>\a config is not a number or string node.
2387 * <dt>-EINVAL<dd>The value in \a ascii cannot be parsed.
2388 * <dt>-ERANGE<dd>The value in \a ascii is too big for the node's type.
2389 * <dt>-ENOMEM<dd>Out of memory.
2390 * </dl>
2391 *
2392 * \par Conforming to:
2393 * LSB 3.2
2394 */
2395int snd_config_set_ascii(snd_config_t *config, const char *ascii)
2396{
2397	assert(config && ascii);
2398	switch (config->type) {
2399	case SND_CONFIG_TYPE_INTEGER:
2400		{
2401			long i;
2402			int err = safe_strtol(ascii, &i);
2403			if (err < 0)
2404				return err;
2405			config->u.integer = i;
2406		}
2407		break;
2408	case SND_CONFIG_TYPE_INTEGER64:
2409		{
2410			long long i;
2411			int err = safe_strtoll(ascii, &i);
2412			if (err < 0)
2413				return err;
2414			config->u.integer64 = i;
2415		}
2416		break;
2417	case SND_CONFIG_TYPE_REAL:
2418		{
2419			double d;
2420			int err = safe_strtod(ascii, &d);
2421			if (err < 0)
2422				return err;
2423			config->u.real = d;
2424			break;
2425		}
2426	case SND_CONFIG_TYPE_STRING:
2427		{
2428			char *ptr = strdup(ascii);
2429			if (ptr == NULL)
2430				return -ENOMEM;
2431			free(config->u.string);
2432			config->u.string = ptr;
2433		}
2434		break;
2435	default:
2436		return -EINVAL;
2437	}
2438	return 0;
2439}
2440
2441/**
2442 * \brief Returns the value of an integer configuration node.
2443 * \param[in] config Handle to the configuration node.
2444 * \param[out] ptr The node's value.
2445 * \return Zero if successful, otherwise a negative error code.
2446 *
2447 * \par Errors:
2448 * <dl>
2449 * <dt>-EINVAL<dd>\a config is not an integer node.
2450 * </dl>
2451 *
2452 * \par Conforming to:
2453 * LSB 3.2
2454 */
2455int snd_config_get_integer(const snd_config_t *config, long *ptr)
2456{
2457	assert(config && ptr);
2458	if (config->type != SND_CONFIG_TYPE_INTEGER)
2459		return -EINVAL;
2460	*ptr = config->u.integer;
2461	return 0;
2462}
2463
2464/**
2465 * \brief Returns the value of a 64-bit-integer configuration node.
2466 * \param[in] config Handle to the configuration node.
2467 * \param[out] ptr The node's value.
2468 * \return Zero if successful, otherwise a negative error code.
2469 *
2470 * \par Errors:
2471 * <dl>
2472 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2473 * </dl>
2474 *
2475 * \par Conforming to:
2476 * LSB 3.2
2477 */
2478int snd_config_get_integer64(const snd_config_t *config, long long *ptr)
2479{
2480	assert(config && ptr);
2481	if (config->type != SND_CONFIG_TYPE_INTEGER64)
2482		return -EINVAL;
2483	*ptr = config->u.integer64;
2484	return 0;
2485}
2486
2487/**
2488 * \brief Returns the value of a real-number configuration node.
2489 * \param[in] config Handle to the configuration node.
2490 * \param[out] ptr The node's value.
2491 * \return Zero if successful, otherwise a negative error code.
2492 *
2493 * \par Errors:
2494 * <dl>
2495 * <dt>-EINVAL<dd>\a config is not a real-number node.
2496 * </dl>
2497 */
2498int snd_config_get_real(const snd_config_t *config, double *ptr)
2499{
2500	assert(config && ptr);
2501	if (config->type != SND_CONFIG_TYPE_REAL)
2502		return -EINVAL;
2503	*ptr = config->u.real;
2504	return 0;
2505}
2506
2507/**
2508 * \brief Returns the value of a real or integer configuration node.
2509 * \param[in] config Handle to the configuration node.
2510 * \param[out] ptr The node's value.
2511 * \return Zero if successful, otherwise a negative error code.
2512 *
2513 * If the node's type is integer or integer64, the value is converted
2514 * to the \c double type on the fly.
2515 *
2516 * \par Errors:
2517 * <dl>
2518 * <dt>-EINVAL<dd>\a config is not a number node.
2519 * </dl>
2520 */
2521int snd_config_get_ireal(const snd_config_t *config, double *ptr)
2522{
2523	assert(config && ptr);
2524	if (config->type == SND_CONFIG_TYPE_REAL)
2525		*ptr = config->u.real;
2526	else if (config->type == SND_CONFIG_TYPE_INTEGER)
2527		*ptr = config->u.integer;
2528	else if (config->type == SND_CONFIG_TYPE_INTEGER64)
2529		*ptr = config->u.integer64;
2530	else
2531		return -EINVAL;
2532	return 0;
2533}
2534
2535/**
2536 * \brief Returns the value of a string configuration node.
2537 * \param[in] config Handle to the configuration node.
2538 * \param[out] ptr The function puts the node's value at the address
2539 *                 specified by \a ptr.
2540 * \return Zero if successful, otherwise a negative error code.
2541 *
2542 * The returned string is owned by the configuration node; the
2543 * application must not modify or delete it, and the string becomes
2544 * invalid when the node's value changes or when the node is freed.
2545 *
2546 * The string may be \c NULL.
2547 *
2548 * \par Errors:
2549 * <dl>
2550 * <dt>-EINVAL<dd>\a config is not a string node.
2551 * </dl>
2552 *
2553 * \par Conforming to:
2554 * LSB 3.2
2555 */
2556int snd_config_get_string(const snd_config_t *config, const char **ptr)
2557{
2558	assert(config && ptr);
2559	if (config->type != SND_CONFIG_TYPE_STRING)
2560		return -EINVAL;
2561	*ptr = config->u.string;
2562	return 0;
2563}
2564
2565/**
2566 * \brief Returns the value of a pointer configuration node.
2567 * \param[in] config Handle to the configuration node.
2568 * \param[out] ptr The function puts the node's value at the address
2569 *                 specified by \a ptr.
2570 * \return Zero if successful, otherwise a negative error code.
2571 *
2572 * \par Errors:
2573 * <dl>
2574 * <dt>-EINVAL<dd>\a config is not a string node.
2575 * </dl>
2576 */
2577int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
2578{
2579	assert(config && ptr);
2580	if (config->type != SND_CONFIG_TYPE_POINTER)
2581		return -EINVAL;
2582	*ptr = config->u.ptr;
2583	return 0;
2584}
2585
2586/**
2587 * \brief Returns the value of a configuration node as a string.
2588 * \param[in] config Handle to the configuration node.
2589 * \param[out] ascii The function puts the pointer to the returned
2590 *                   string at the address specified by \a ascii.
2591 * \return Zero if successful, otherwise a negative error code.
2592 *
2593 * This function dynamically allocates the returned string.  The
2594 * application is responsible for deleting it with \c free() when it is
2595 * no longer used.
2596 *
2597 * For a string node with \c NULL value, the returned string is \c NULL.
2598 *
2599 * Supported node types are #SND_CONFIG_TYPE_INTEGER,
2600 * #SND_CONFIG_TYPE_INTEGER64, #SND_CONFIG_TYPE_REAL, and
2601 * #SND_CONFIG_TYPE_STRING.
2602 *
2603 * \par Errors:
2604 * <dl>
2605 * <dt>-EINVAL<dd>\a config is not a (64-bit) integer or real number or
2606 *                string node.
2607 * <dt>-ENOMEM<dd>Out of memory.
2608 * </dl>
2609 *
2610 * \par Conforming to:
2611 * LSB 3.2
2612 */
2613int snd_config_get_ascii(const snd_config_t *config, char **ascii)
2614{
2615	assert(config && ascii);
2616	switch (config->type) {
2617	case SND_CONFIG_TYPE_INTEGER:
2618		{
2619			char res[12];
2620			int err;
2621			err = snprintf(res, sizeof(res), "%li", config->u.integer);
2622			if (err < 0 || err == sizeof(res)) {
2623				assert(0);
2624				return -ENOMEM;
2625			}
2626			*ascii = strdup(res);
2627		}
2628		break;
2629	case SND_CONFIG_TYPE_INTEGER64:
2630		{
2631			char res[32];
2632			int err;
2633			err = snprintf(res, sizeof(res), "%lli", config->u.integer64);
2634			if (err < 0 || err == sizeof(res)) {
2635				assert(0);
2636				return -ENOMEM;
2637			}
2638			*ascii = strdup(res);
2639		}
2640		break;
2641	case SND_CONFIG_TYPE_REAL:
2642		{
2643			char res[32];
2644			int err;
2645			err = snprintf(res, sizeof(res), "%-16g", config->u.real);
2646			if (err < 0 || err == sizeof(res)) {
2647				assert(0);
2648				return -ENOMEM;
2649			}
2650			if (res[0]) {		/* trim the string */
2651				char *ptr;
2652				ptr = res + strlen(res) - 1;
2653				while (ptr != res && *ptr == ' ')
2654					ptr--;
2655				if (*ptr != ' ')
2656					ptr++;
2657				*ptr = '\0';
2658			}
2659			*ascii = strdup(res);
2660		}
2661		break;
2662	case SND_CONFIG_TYPE_STRING:
2663		if (config->u.string)
2664			*ascii = strdup(config->u.string);
2665		else {
2666			*ascii = NULL;
2667			return 0;
2668		}
2669		break;
2670	default:
2671		return -EINVAL;
2672	}
2673	if (*ascii == NULL)
2674		return -ENOMEM;
2675	return 0;
2676}
2677
2678/**
2679 * \brief Compares the id of a configuration node to a given string.
2680 * \param config Handle to the configuration node.
2681 * \param id ASCII id.
2682 * \return The same value as the result of the \c strcmp function, i.e.,
2683 *         less than zero if \a config's id is lexicographically less
2684 *         than \a id, zero if \a config's id is equal to id, greater
2685 *         than zero otherwise.
2686 */
2687int snd_config_test_id(const snd_config_t *config, const char *id)
2688{
2689	assert(config && id);
2690	if (config->id)
2691		return strcmp(config->id, id);
2692	else
2693		return -1;
2694}
2695
2696/**
2697 * \brief Dumps the contents of a configuration node or tree.
2698 * \param config Handle to the (root) configuration node.
2699 * \param out Output handle.
2700 * \return Zero if successful, otherwise a negative error code.
2701 *
2702 * This function writes a textual representation of \a config's value to
2703 * the output \a out.
2704 *
2705 * \par Errors:
2706 * <dl>
2707 * <dt>-EINVAL<dd>A node in the tree has a type that cannot be printed,
2708 *                i.e., #SND_CONFIG_TYPE_POINTER.
2709 * </dl>
2710 *
2711 * \par Conforming to:
2712 * LSB 3.2
2713 */
2714int snd_config_save(snd_config_t *config, snd_output_t *out)
2715{
2716	assert(config && out);
2717	if (config->type == SND_CONFIG_TYPE_COMPOUND)
2718		return _snd_config_save_children(config, out, 0, 0);
2719	else
2720		return _snd_config_save_node_value(config, out, 0);
2721}
2722
2723/*
2724 *  *** search macros ***
2725 */
2726
2727#ifndef DOC_HIDDEN
2728
2729#define SND_CONFIG_SEARCH(config, key, result, extra_code) \
2730{ \
2731	snd_config_t *n; \
2732	int err; \
2733	const char *p; \
2734	assert(config && key); \
2735	while (1) { \
2736		if (config->type != SND_CONFIG_TYPE_COMPOUND) \
2737			return -ENOENT; \
2738		{ extra_code ; } \
2739		p = strchr(key, '.'); \
2740		if (p) { \
2741			err = _snd_config_search(config, key, p - key, &n); \
2742			if (err < 0) \
2743				return err; \
2744			config = n; \
2745			key = p + 1; \
2746		} else \
2747			return _snd_config_search(config, key, -1, result); \
2748	} \
2749}
2750
2751#define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \
2752{ \
2753	snd_config_t *n; \
2754	int err; \
2755	const char *p; \
2756	assert(config && key); \
2757	while (1) { \
2758		if (config->type != SND_CONFIG_TYPE_COMPOUND) { \
2759			if (snd_config_get_string(config, &p) < 0) \
2760				return -ENOENT; \
2761			err = fcn(root, root, p, &config); \
2762			if (err < 0) \
2763				return err; \
2764		} \
2765		{ extra_code ; } \
2766		p = strchr(key, '.'); \
2767		if (p) { \
2768			err = _snd_config_search(config, key, p - key, &n); \
2769			if (err < 0) \
2770				return err; \
2771			config = n; \
2772			key = p + 1; \
2773		} else \
2774			return _snd_config_search(config, key, -1, result); \
2775	} \
2776}
2777
2778#define SND_CONFIG_SEARCHV(config, result, fcn) \
2779{ \
2780	snd_config_t *n; \
2781	va_list arg; \
2782	assert(config); \
2783	va_start(arg, result); \
2784	while (1) { \
2785		const char *k = va_arg(arg, const char *); \
2786		int err; \
2787		if (!k) \
2788			break; \
2789		err = fcn(config, k, &n); \
2790		if (err < 0) \
2791			return err; \
2792		config = n; \
2793	} \
2794	va_end(arg); \
2795	if (result) \
2796		*result = n; \
2797	return 0; \
2798}
2799
2800#define SND_CONFIG_SEARCHVA(root, config, result, fcn) \
2801{ \
2802	snd_config_t *n; \
2803	va_list arg; \
2804	assert(config); \
2805	va_start(arg, result); \
2806	while (1) { \
2807		const char *k = va_arg(arg, const char *); \
2808		int err; \
2809		if (!k) \
2810			break; \
2811		err = fcn(root, config, k, &n); \
2812		if (err < 0) \
2813			return err; \
2814		config = n; \
2815	} \
2816	va_end(arg); \
2817	if (result) \
2818		*result = n; \
2819	return 0; \
2820}
2821
2822#define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
2823{ \
2824	snd_config_t *res = NULL; \
2825	char *old_key; \
2826	int err, first = 1, maxloop = 1000; \
2827	assert(config && key); \
2828	while (1) { \
2829		old_key = strdup(key); \
2830		if (old_key == NULL) { \
2831			err = -ENOMEM; \
2832			res = NULL; \
2833			break; \
2834		} \
2835		err = first && base ? -EIO : fcn1(config, config, key, &res); \
2836		if (err < 0) { \
2837			if (!base) \
2838				break; \
2839			err = fcn2(config, config, &res, base, key, NULL); \
2840			if (err < 0) \
2841				break; \
2842		} \
2843		if (snd_config_get_string(res, &key) < 0) \
2844			break; \
2845		assert(key); \
2846		if (!first && (strcmp(key, old_key) == 0 || maxloop <= 0)) { \
2847			if (maxloop == 0) \
2848				SNDERR("maximum loop count reached (circular configuration?)"); \
2849			else \
2850				SNDERR("key %s refers to itself", key); \
2851			err = -EINVAL; \
2852			res = NULL; \
2853			break; \
2854		} \
2855		free(old_key); \
2856		first = 0; \
2857		maxloop--; \
2858	} \
2859	free(old_key); \
2860	if (!res) \
2861		return err; \
2862	if (result) \
2863		*result = res; \
2864	return 0; \
2865}
2866
2867#endif /* DOC_HIDDEN */
2868
2869/**
2870 * \brief Searches for a node in a configuration tree.
2871 * \param[in] config Handle to the root of the configuration (sub)tree to search.
2872 * \param[in] key Search key: one or more node ids, separated with dots.
2873 * \param[out] result When \a result != \c NULL, the function puts the
2874 *                    handle to the node found at the address specified
2875 *                    by \a result.
2876 * \return Zero if successful, otherwise a negative error code.
2877 *
2878 * This function searches for a child node of \a config that is
2879 * identified by \a key, which contains either the id of a direct child
2880 * node of \a config, or a series of ids, separated with dots, where
2881 * each id specifies a node that is contained in the previous compound
2882 * node.
2883 *
2884 * In the following example, the comment after each node shows the
2885 * search key to find that node, assuming that \a config is a handle to
2886 * the compound node with id \c config:
2887 * \code
2888 * config {
2889 *     a 42               # "a"
2890 *     b {                # "b"
2891 *         c "cee"        # "b.c"
2892 *         d {            # "b.d"
2893 *             e 2.71828  # "b.d.e"
2894 *         }
2895 *     }
2896 * }
2897 * \endcode
2898 *
2899 * \par Errors:
2900 * <dl>
2901 * <dt>-ENOENT<dd>An id in \a key does not exist.
2902 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
2903 *                not a compound node.
2904 * </dl>
2905 *
2906 * \par Conforming to:
2907 * LSB 3.2
2908 */
2909int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
2910{
2911	SND_CONFIG_SEARCH(config, key, result, );
2912}
2913
2914/**
2915 * \brief Searches for a node in a configuration tree, expanding aliases.
2916 * \param[in] root Handle to the root configuration node containing
2917 *                 alias definitions.
2918 * \param[in] config Handle to the root of the configuration (sub)tree to search.
2919 * \param[in] key Search key: one or more node keys, separated with dots.
2920 * \param[out] result When \a result != \c NULL, the function puts the
2921 *                    handle to the node found at the address specified
2922 *                    by \a result.
2923 * \return Zero if successful, otherwise a negative error code.
2924 *
2925 * This functions searches for a child node of \a config like
2926 * #snd_config_search.  However, any compound node can also be
2927 * identified by an alias, which is a string node whose value is taken
2928 * as the id of a compound node below \a root.
2929 *
2930 * \a root must be a compound node.
2931 * \a root and \a config may be the same node.
2932 *
2933 * For example, with the following configuration, the call
2934 * \code
2935 * snd_config_searcha(root, config, "a.b.c.d", &result);
2936 * \endcode
2937 * would return the node with id \c d:
2938 * \code
2939 * config {
2940 *     a {
2941 *         b bb
2942 *     }
2943 * }
2944 * root {
2945 *     bb {
2946 *         c cc
2947 *     }
2948 *     cc ccc
2949 *     ccc {
2950 *         d {
2951 *             x "icks"
2952 *         }
2953 *     }
2954 * }
2955 * \endcode
2956 *
2957 * \par Errors:
2958 * <dl>
2959 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
2960 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
2961 *                not a compound or string node.
2962 * </dl>
2963 */
2964int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
2965{
2966	SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, );
2967}
2968
2969/**
2970 * \brief Searches for a node in a configuration tree.
2971 * \param[in] config Handle to the root of the configuration (sub)tree to search.
2972 * \param[out] result When \a result != \c NULL, the function puts the
2973 *                    handle to the node found at the address specified
2974 *                    by \a result.
2975 * \param[in] ... One or more concatenated dot-separated search keys,
2976 *                terminated with \c NULL.
2977 * \return Zero if successful, otherwise a negative error code.
2978 *
2979 * This functions searches for a child node of \a config like
2980 * #snd_config_search, but the search key is the concatenation of all
2981 * passed search key strings.  For example, the call
2982 * \code
2983 * snd_config_searchv(cfg, &res, "a", "b.c", "d.e", NULL);
2984 * \endcode
2985 * is equivalent to the call
2986 * \code
2987 * snd_config_search(cfg, "a.b.c.d.e", &res);
2988 * \endcode
2989 *
2990 * \par Errors:
2991 * <dl>
2992 * <dt>-ENOENT<dd>An id in a search key does not exist.
2993 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
2994 *                not a compound node.
2995 * </dl>
2996 *
2997 * \par Conforming to:
2998 * LSB 3.2
2999 */
3000int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...)
3001{
3002	SND_CONFIG_SEARCHV(config, result, snd_config_search);
3003}
3004
3005/**
3006 * \brief Searches for a node in a configuration tree, expanding aliases.
3007 * \param[in] root Handle to the root configuration node containing
3008 *                 alias definitions.
3009 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3010 * \param[out] result When \a result != \c NULL, the function puts the
3011 *                    handle to the node found at the address specified
3012 *                    by \a result.
3013 * \param[in] ... One or more concatenated dot separated search keys,
3014 *                terminated with \c NULL.
3015 * \return Zero if successful, otherwise a negative error code.
3016 *
3017 * This function searches for a child node of \a config, allowing
3018 * aliases, like #snd_config_searcha, but the search key is the
3019 * concatenation of all passed seach key strings, like with
3020 * #snd_config_searchv.
3021 *
3022 * \par Errors:
3023 * <dl>
3024 * <dt>-ENOENT<dd>An id in a search key does not exist.
3025 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3026 *                not a compound or string node.
3027 * </dl>
3028 */
3029int snd_config_searchva(snd_config_t *root, snd_config_t *config, snd_config_t **result, ...)
3030{
3031	SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha);
3032}
3033
3034/**
3035 * \brief Searches for a node in a configuration tree, expanding aliases.
3036 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3037 * \param[in] base Search key base, or \c NULL.
3038 * \param[in] key Search key suffix.
3039 * \param[out] result When \a result != \c NULL, the function puts the
3040 *                    handle to the node found at the address specified
3041 *                    by \a result.
3042 * \return Zero if successful, otherwise a negative error code.
3043 *
3044 * This functions searches for a child node of \a config, allowing
3045 * aliases, like #snd_config_searcha.  However, alias definitions are
3046 * searched below \a config (there is no separate \a root parameter),
3047 * and \a base specifies a seach key that identifies a compound node
3048 * that is used to search for an alias definitions that is not found
3049 * directly below \a config and that does not contain a period.  In
3050 * other words, when \c "id" is not found in \a config, this function
3051 * also tries \c "base.id".
3052 *
3053 * \par Errors:
3054 * <dl>
3055 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3056 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3057 *                not a compound or string node.
3058 * </dl>
3059 */
3060int snd_config_search_alias(snd_config_t *config,
3061			    const char *base, const char *key,
3062			    snd_config_t **result)
3063{
3064	SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3065				snd_config_searcha, snd_config_searchva);
3066}
3067
3068static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
3069
3070/**
3071 * \brief Searches for a node in a configuration tree and expands hooks.
3072 * \param[in,out] config Handle to the root of the configuration
3073 *                       (sub)tree to search.
3074 * \param[in] key Search key: one or more node keys, separated with dots.
3075 * \param[out] result The function puts the handle to the node found at
3076 *                    the address specified by \a result.
3077 * \return Zero if successful, otherwise a negative error code.
3078 *
3079 * This functions searches for a child node of \a config like
3080 * #snd_config_search, but any compound nodes to be searched that
3081 * contain hooks are modified by the respective hook functions.
3082 *
3083 * \par Errors:
3084 * <dl>
3085 * <dt>-ENOENT<dd>An id in \a key does not exist.
3086 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3087 *                not a compound node.
3088 * </dl>
3089 * Additionally, any errors encountered when parsing the hook
3090 * definitions or returned by the hook functions.
3091 */
3092int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
3093{
3094	SND_CONFIG_SEARCH(config, key, result, \
3095					err = snd_config_hooks(config, NULL); \
3096					if (err < 0) \
3097						return err; \
3098			 );
3099}
3100
3101/**
3102 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
3103 * \param[in] root Handle to the root configuration node containing
3104 *                 alias definitions.
3105 * \param[in,out] config Handle to the root of the configuration
3106 *                       (sub)tree to search.
3107 * \param[in] key Search key: one or more node keys, separated with dots.
3108 * \param[out] result The function puts the handle to the node found at
3109 *                    the address specified by \a result.
3110 * \return Zero if successful, otherwise a negative error code.
3111 *
3112 * This function searches for a child node of \a config, allowing
3113 * aliases, like #snd_config_searcha, and expanding hooks, like
3114 * #snd_config_search_hooks.
3115 *
3116 * \par Errors:
3117 * <dl>
3118 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3119 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3120 *                not a compound node.
3121 * </dl>
3122 * Additionally, any errors encountered when parsing the hook
3123 * definitions or returned by the hook functions.
3124 */
3125int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
3126{
3127	SND_CONFIG_SEARCHA(root, config, key, result,
3128					snd_config_searcha_hooks,
3129					err = snd_config_hooks(config, NULL); \
3130					if (err < 0) \
3131						return err; \
3132			 );
3133}
3134
3135/**
3136 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
3137 * \param[in] root Handle to the root configuration node containing
3138 *                 alias definitions.
3139 * \param[in,out] config Handle to the root of the configuration
3140 *                       (sub)tree to search.
3141 * \param[out] result The function puts the handle to the node found at
3142 *                    the address specified by \a result.
3143 * \param[in] ... One or more concatenated dot separated search keys,
3144 *                terminated with \c NULL.
3145 * \return Zero if successful, otherwise a negative error code.
3146 *
3147 * This function searches for a child node of \a config, allowing
3148 * aliases and expanding hooks like #snd_config_searcha_hooks, but the
3149 * search key is the concatenation of all passed seach key strings, like
3150 * with #snd_config_searchv.
3151 *
3152 * \par Errors:
3153 * <dl>
3154 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3155 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3156 *                not a compound node.
3157 * </dl>
3158 * Additionally, any errors encountered when parsing the hook
3159 * definitions or returned by the hook functions.
3160 */
3161int snd_config_searchva_hooks(snd_config_t *root, snd_config_t *config,
3162			      snd_config_t **result, ...)
3163{
3164	SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha_hooks);
3165}
3166
3167/**
3168 * \brief Searches for a node in a configuration tree, using an alias and expanding hooks.
3169 * \param[in] config Handle to the root of the configuration (sub)tree
3170 *                   to search.
3171 * \param[in] base Search key base, or \c NULL.
3172 * \param[in] key Search key suffix.
3173 * \param[out] result The function puts the handle to the node found at
3174 *                    the address specified by \a result.
3175 * \return Zero if successful, otherwise a negative error code.
3176 *
3177 * This functions searches for a child node of \a config, allowing
3178 * aliases, like #snd_config_search_alias, and expanding hooks, like
3179 * #snd_config_search_hooks.
3180 *
3181 * \par Errors:
3182 * <dl>
3183 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3184 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3185 *                not a compound node.
3186 * </dl>
3187 * Additionally, any errors encountered when parsing the hook
3188 * definitions or returned by the hook functions.
3189 */
3190int snd_config_search_alias_hooks(snd_config_t *config,
3191				  const char *base, const char *key,
3192				  snd_config_t **result)
3193{
3194	SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3195				snd_config_searcha_hooks,
3196				snd_config_searchva_hooks);
3197}
3198
3199/** The name of the environment variable containing the files list for #snd_config_update. */
3200#define ALSA_CONFIG_PATH_VAR "ALSA_CONFIG_PATH"
3201
3202/** The name of the default files used by #snd_config_update. */
3203#define ALSA_CONFIG_PATH_DEFAULT ALSA_CONFIG_DIR "/alsa.conf"
3204
3205/**
3206 * \ingroup Config
3207 * \brief Configuration top-level node (the global configuration).
3208 *
3209 * This variable contains a handle to the top-level configuration node,
3210 * as loaded from global configuration file.
3211 *
3212 * This variable is initialized or updated by #snd_config_update.
3213 * Functions like #snd_pcm_open (that use a device name from the global
3214 * configuration) automatically call #snd_config_update.  Before the
3215 * first call to #snd_config_update, this variable is \c NULL.
3216 *
3217 * The global configuration files are specified in the environment
3218 * variable \c ALSA_CONFIG_PATH.  If this is not set, the default value
3219 * is "/usr/share/alsa/alsa.conf".
3220 *
3221 * \warning Whenever the configuration tree is updated, all string
3222 * pointers and configuration node handles previously obtained from this
3223 * variable may become invalid.
3224 *
3225 * \par Conforming to:
3226 * LSB 3.2
3227 */
3228snd_config_t *snd_config = NULL;
3229
3230#ifndef DOC_HIDDEN
3231struct finfo {
3232	char *name;
3233	dev_t dev;
3234	ino_t ino;
3235	time_t mtime;
3236};
3237
3238struct _snd_config_update {
3239	unsigned int count;
3240	struct finfo *finfo;
3241};
3242#endif /* DOC_HIDDEN */
3243
3244static snd_config_update_t *snd_config_global_update = NULL;
3245
3246static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
3247{
3248	void *h = NULL;
3249	snd_config_t *c, *func_conf = NULL;
3250	char *buf = NULL;
3251	const char *lib = NULL, *func_name = NULL;
3252	const char *str;
3253	int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL;
3254	int err;
3255
3256	err = snd_config_search(config, "func", &c);
3257	if (err < 0) {
3258		SNDERR("Field func is missing");
3259		return err;
3260	}
3261	err = snd_config_get_string(c, &str);
3262	if (err < 0) {
3263		SNDERR("Invalid type for field func");
3264		return err;
3265	}
3266	assert(str);
3267	err = snd_config_search_definition(root, "hook_func", str, &func_conf);
3268	if (err >= 0) {
3269		snd_config_iterator_t i, next;
3270		if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
3271			SNDERR("Invalid type for func %s definition", str);
3272			err = -EINVAL;
3273			goto _err;
3274		}
3275		snd_config_for_each(i, next, func_conf) {
3276			snd_config_t *n = snd_config_iterator_entry(i);
3277			const char *id = n->id;
3278			if (strcmp(id, "comment") == 0)
3279				continue;
3280			if (strcmp(id, "lib") == 0) {
3281				err = snd_config_get_string(n, &lib);
3282				if (err < 0) {
3283					SNDERR("Invalid type for %s", id);
3284					goto _err;
3285				}
3286				continue;
3287			}
3288			if (strcmp(id, "func") == 0) {
3289				err = snd_config_get_string(n, &func_name);
3290				if (err < 0) {
3291					SNDERR("Invalid type for %s", id);
3292					goto _err;
3293				}
3294				continue;
3295			}
3296			SNDERR("Unknown field %s", id);
3297		}
3298	}
3299	if (!func_name) {
3300		int len = 16 + strlen(str) + 1;
3301		buf = malloc(len);
3302		if (! buf) {
3303			err = -ENOMEM;
3304			goto _err;
3305		}
3306		snprintf(buf, len, "snd_config_hook_%s", str);
3307		buf[len-1] = '\0';
3308		func_name = buf;
3309	}
3310	h = snd_dlopen(lib, RTLD_NOW);
3311	func = h ? snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_HOOK)) : NULL;
3312	err = 0;
3313	if (!h) {
3314		SNDERR("Cannot open shared library %s", lib);
3315		err = -ENOENT;
3316	} else if (!func) {
3317		SNDERR("symbol %s is not defined inside %s", func_name, lib);
3318		snd_dlclose(h);
3319		err = -ENXIO;
3320	}
3321	_err:
3322	if (func_conf)
3323		snd_config_delete(func_conf);
3324	if (err >= 0) {
3325		snd_config_t *nroot;
3326		err = func(root, config, &nroot, private_data);
3327		if (err < 0)
3328			SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
3329		snd_dlclose(h);
3330		if (err >= 0 && nroot)
3331			err = snd_config_substitute(root, nroot);
3332	}
3333	free(buf);
3334	if (err < 0)
3335		return err;
3336	return 0;
3337}
3338
3339static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
3340{
3341	snd_config_t *n;
3342	snd_config_iterator_t i, next;
3343	int err, hit, idx = 0;
3344
3345	if ((err = snd_config_search(config, "@hooks", &n)) < 0)
3346		return 0;
3347	snd_config_lock();
3348	snd_config_remove(n);
3349	do {
3350		hit = 0;
3351		snd_config_for_each(i, next, n) {
3352			snd_config_t *n = snd_config_iterator_entry(i);
3353			const char *id = n->id;
3354			long i;
3355			err = safe_strtol(id, &i);
3356			if (err < 0) {
3357				SNDERR("id of field %s is not and integer", id);
3358				err = -EINVAL;
3359				goto _err;
3360			}
3361			if (i == idx) {
3362				err = snd_config_hooks_call(config, n, private_data);
3363				if (err < 0)
3364					goto _err;
3365				idx++;
3366				hit = 1;
3367			}
3368		}
3369	} while (hit);
3370	err = 0;
3371       _err:
3372	snd_config_delete(n);
3373	snd_config_unlock();
3374	return err;
3375}
3376
3377static int config_filename_filter(const struct dirent *dirent)
3378{
3379	size_t flen;
3380
3381	if (dirent == NULL)
3382		return 0;
3383	if (dirent->d_type == DT_DIR)
3384		return 0;
3385
3386	flen = strlen(dirent->d_name);
3387	if (flen <= 5)
3388		return 0;
3389
3390	if (strncmp(&dirent->d_name[flen-5], ".conf", 5) == 0)
3391		return 1;
3392
3393	return 0;
3394}
3395
3396static int config_file_open(snd_config_t *root, const char *filename)
3397{
3398	snd_input_t *in;
3399	int err;
3400
3401	err = snd_input_stdio_open(&in, filename, "r");
3402	if (err >= 0) {
3403		err = snd_config_load(root, in);
3404		snd_input_close(in);
3405		if (err < 0)
3406			SNDERR("%s may be old or corrupted: consider to remove or fix it", filename);
3407	} else
3408		SNDERR("cannot access file %s", filename);
3409
3410	return err;
3411}
3412
3413/**
3414 * \brief Loads and parses the given configurations files.
3415 * \param[in] root Handle to the root configuration node.
3416 * \param[in] config Handle to the configuration node for this hook.
3417 * \param[out] dst The function puts the handle to the configuration
3418 *                 node loaded from the file(s) at the address specified
3419 *                 by \a dst.
3420 * \param[in] private_data Handle to the private data configuration node.
3421 * \return Zero if successful, otherwise a negative error code.
3422 *
3423 * See \ref confhooks for an example.
3424 */
3425int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
3426{
3427	snd_config_t *n;
3428	snd_config_iterator_t i, next;
3429	struct finfo *fi = NULL;
3430	int err, idx = 0, fi_count = 0, errors = 1, hit;
3431
3432	assert(root && dst);
3433	if ((err = snd_config_search(config, "errors", &n)) >= 0) {
3434		char *tmp;
3435		err = snd_config_get_ascii(n, &tmp);
3436		if (err < 0)
3437			return err;
3438		errors = snd_config_get_bool_ascii(tmp);
3439		free(tmp);
3440		if (errors < 0) {
3441			SNDERR("Invalid bool value in field errors");
3442			return errors;
3443		}
3444	}
3445	if ((err = snd_config_search(config, "files", &n)) < 0) {
3446		SNDERR("Unable to find field files in the pre-load section");
3447		return -EINVAL;
3448	}
3449	if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) {
3450		SNDERR("Unable to expand filenames in the pre-load section");
3451		return err;
3452	}
3453	if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
3454		SNDERR("Invalid type for field filenames");
3455		goto _err;
3456	}
3457	snd_config_for_each(i, next, n) {
3458		snd_config_t *c = snd_config_iterator_entry(i);
3459		const char *str;
3460		if ((err = snd_config_get_string(c, &str)) < 0) {
3461			SNDERR("Field %s is not a string", c->id);
3462			goto _err;
3463		}
3464		fi_count++;
3465	}
3466	fi = calloc(fi_count, sizeof(*fi));
3467	if (fi == NULL) {
3468		err = -ENOMEM;
3469		goto _err;
3470	}
3471	do {
3472		hit = 0;
3473		snd_config_for_each(i, next, n) {
3474			snd_config_t *n = snd_config_iterator_entry(i);
3475			const char *id = n->id;
3476			long i;
3477			err = safe_strtol(id, &i);
3478			if (err < 0) {
3479				SNDERR("id of field %s is not and integer", id);
3480				err = -EINVAL;
3481				goto _err;
3482			}
3483			if (i == idx) {
3484				char *name;
3485				if ((err = snd_config_get_ascii(n, &name)) < 0)
3486					goto _err;
3487				if ((err = snd_user_file(name, &fi[idx].name)) < 0)
3488					fi[idx].name = name;
3489				else
3490					free(name);
3491				idx++;
3492				hit = 1;
3493			}
3494		}
3495	} while (hit);
3496	for (idx = 0; idx < fi_count; idx++) {
3497		struct stat st;
3498		if (!errors && access(fi[idx].name, R_OK) < 0)
3499			continue;
3500		if (stat(fi[idx].name, &st) < 0) {
3501			SNDERR("cannot stat file/directory %s", fi[idx].name);
3502			continue;
3503		}
3504		if (S_ISDIR(st.st_mode)) {
3505			struct dirent **namelist;
3506			int n;
3507
3508#ifdef _GNU_SOURCE
3509#define SORTFUNC	versionsort
3510#else
3511#define SORTFUNC	alphasort
3512#endif
3513			n = scandir(fi[idx].name, &namelist, config_filename_filter, SORTFUNC);
3514			if (n > 0) {
3515				int j;
3516				err = 0;
3517				for (j = 0; j < n; ++j) {
3518					if (err >= 0) {
3519						int sl = strlen(fi[idx].name) + strlen(namelist[j]->d_name) + 2;
3520						char *filename = malloc(sl);
3521						snprintf(filename, sl, "%s/%s", fi[idx].name, namelist[j]->d_name);
3522						filename[sl-1] = '\0';
3523
3524						err = config_file_open(root, filename);
3525						free(filename);
3526					}
3527					free(namelist[j]);
3528				}
3529				free(namelist);
3530				if (err < 0)
3531					goto _err;
3532			}
3533		} else if (config_file_open(root, fi[idx].name) < 0)
3534			goto _err;
3535	}
3536	*dst = NULL;
3537	err = 0;
3538       _err:
3539	if (fi)
3540		for (idx = 0; idx < fi_count; idx++)
3541			free(fi[idx].name);
3542	free(fi);
3543	snd_config_delete(n);
3544	return err;
3545}
3546#ifndef DOC_HIDDEN
3547SND_DLSYM_BUILD_VERSION(snd_config_hook_load, SND_CONFIG_DLSYM_VERSION_HOOK);
3548#endif
3549
3550#ifndef DOC_HIDDEN
3551int snd_determine_driver(int card, char **driver);
3552#endif
3553
3554/**
3555 * \brief Loads and parses the given configurations files for each
3556 *        installed sound card.
3557 * \param[in] root Handle to the root configuration node.
3558 * \param[in] config Handle to the configuration node for this hook.
3559 * \param[out] dst The function puts the handle to the configuration
3560 *                 node loaded from the file(s) at the address specified
3561 *                 by \a dst.
3562 * \param[in] private_data Handle to the private data configuration node.
3563 * \return Zero if successful, otherwise a negative error code.
3564 *
3565 * This function works like #snd_config_hook_load, but the files are
3566 * loaded once for each sound card.  The driver name is available with
3567 * the \c private_string function to customize the file name.
3568 */
3569int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data ATTRIBUTE_UNUSED)
3570{
3571	int card = -1, err;
3572
3573	do {
3574		err = snd_card_next(&card);
3575		if (err < 0)
3576			return err;
3577		if (card >= 0) {
3578			snd_config_t *n, *private_data = NULL;
3579			const char *driver;
3580			char *fdriver = NULL;
3581			err = snd_determine_driver(card, &fdriver);
3582			if (err < 0)
3583				return err;
3584			if (snd_config_search(root, fdriver, &n) >= 0) {
3585				if (snd_config_get_string(n, &driver) < 0)
3586					goto __err;
3587				assert(driver);
3588				while (1) {
3589					char *s = strchr(driver, '.');
3590					if (s == NULL)
3591						break;
3592					driver = s + 1;
3593				}
3594				if (snd_config_search(root, driver, &n) >= 0)
3595					goto __err;
3596			} else {
3597				driver = fdriver;
3598			}
3599			err = snd_config_imake_string(&private_data, "string", driver);
3600			if (err < 0)
3601				goto __err;
3602			err = snd_config_hook_load(root, config, &n, private_data);
3603		      __err:
3604			if (private_data)
3605				snd_config_delete(private_data);
3606			free(fdriver);
3607			if (err < 0)
3608				return err;
3609		}
3610	} while (card >= 0);
3611	*dst = NULL;
3612	return 0;
3613}
3614#ifndef DOC_HIDDEN
3615SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK);
3616#endif
3617
3618/**
3619 * \brief Updates a configuration tree by rereading the configuration files (if needed).
3620 * \param[in,out] _top Address of the handle to the top-level node.
3621 * \param[in,out] _update Address of a pointer to private update information.
3622 * \param[in] cfgs A list of configuration file names, delimited with ':'.
3623 *                 If \p cfgs is \c NULL, the default global
3624 *                 configuration file is used.
3625 * \return 0 if \a _top was up to date, 1 if the configuration files
3626 *         have been reread, otherwise a negative error code.
3627 *
3628 * The variables pointed to by \a _top and \a _update can be initialized
3629 * to \c NULL before the first call to this function.  The private
3630 * update information holds information about all used configuration
3631 * files that allows this function to detects changes to them; this data
3632 * can be freed with #snd_config_update_free.
3633 *
3634 * The global configuration files are specified in the environment variable
3635 * \c ALSA_CONFIG_PATH.
3636 *
3637 * \warning If the configuration tree is reread, all string pointers and
3638 * configuration node handles previously obtained from this tree become
3639 * invalid.
3640 *
3641 * \par Errors:
3642 * Any errors encountered when parsing the input or returned by hooks or
3643 * functions.
3644 */
3645int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs)
3646{
3647	int err;
3648	const char *configs, *c;
3649	unsigned int k;
3650	size_t l;
3651	snd_config_update_t *local;
3652	snd_config_update_t *update;
3653	snd_config_t *top;
3654
3655	assert(_top && _update);
3656	top = *_top;
3657	update = *_update;
3658	configs = cfgs;
3659	if (!configs) {
3660		configs = getenv(ALSA_CONFIG_PATH_VAR);
3661		if (!configs || !*configs)
3662			configs = ALSA_CONFIG_PATH_DEFAULT;
3663	}
3664	for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
3665		c += l;
3666		k++;
3667		if (!*c)
3668			break;
3669		c++;
3670	}
3671	if (k == 0) {
3672		local = NULL;
3673		goto _reread;
3674	}
3675	local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t));
3676	if (!local)
3677		return -ENOMEM;
3678	local->count = k;
3679	local->finfo = calloc(local->count, sizeof(struct finfo));
3680	if (!local->finfo) {
3681		free(local);
3682		return -ENOMEM;
3683	}
3684	for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
3685		char name[l + 1];
3686		memcpy(name, c, l);
3687		name[l] = 0;
3688		err = snd_user_file(name, &local->finfo[k].name);
3689		if (err < 0)
3690			goto _end;
3691		c += l;
3692		k++;
3693		if (!*c)
3694			break;
3695		c++;
3696	}
3697	for (k = 0; k < local->count; ++k) {
3698		struct stat st;
3699		struct finfo *lf = &local->finfo[k];
3700		if (stat(lf->name, &st) >= 0) {
3701			lf->dev = st.st_dev;
3702			lf->ino = st.st_ino;
3703			lf->mtime = st.st_mtime;
3704		} else {
3705			SNDERR("Cannot access file %s", lf->name);
3706			free(lf->name);
3707			memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1));
3708			k--;
3709			local->count--;
3710		}
3711	}
3712	if (!update)
3713		goto _reread;
3714	if (local->count != update->count)
3715		goto _reread;
3716	for (k = 0; k < local->count; ++k) {
3717		struct finfo *lf = &local->finfo[k];
3718		struct finfo *uf = &update->finfo[k];
3719		if (strcmp(lf->name, uf->name) != 0 ||
3720		    lf->dev != uf->dev ||
3721		    lf->ino != uf->ino ||
3722		    lf->mtime != uf->mtime)
3723			goto _reread;
3724	}
3725	err = 0;
3726
3727 _end:
3728	if (err < 0) {
3729		if (top) {
3730			snd_config_delete(top);
3731			*_top = NULL;
3732		}
3733		if (update) {
3734			snd_config_update_free(update);
3735			*_update = NULL;
3736		}
3737	}
3738	if (local)
3739		snd_config_update_free(local);
3740	return err;
3741
3742 _reread:
3743 	*_top = NULL;
3744 	*_update = NULL;
3745 	if (update) {
3746 		snd_config_update_free(update);
3747 		update = NULL;
3748 	}
3749	if (top) {
3750		snd_config_delete(top);
3751		top = NULL;
3752	}
3753	err = snd_config_top(&top);
3754	if (err < 0)
3755		goto _end;
3756	if (!local)
3757		goto _skip;
3758	for (k = 0; k < local->count; ++k) {
3759		snd_input_t *in;
3760		err = snd_input_stdio_open(&in, local->finfo[k].name, "r");
3761		if (err >= 0) {
3762			err = snd_config_load(top, in);
3763			snd_input_close(in);
3764			if (err < 0) {
3765				SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name);
3766				goto _end;
3767			}
3768		} else {
3769			SNDERR("cannot access file %s", local->finfo[k].name);
3770		}
3771	}
3772 _skip:
3773	err = snd_config_hooks(top, NULL);
3774	if (err < 0) {
3775		SNDERR("hooks failed, removing configuration");
3776		goto _end;
3777	}
3778	*_top = top;
3779	*_update = local;
3780	return 1;
3781}
3782
3783/**
3784 * \brief Updates #snd_config by rereading the global configuration files (if needed).
3785 * \return 0 if #snd_config was up to date, 1 if #snd_config was
3786 *         updated, otherwise a negative error code.
3787 *
3788 * \warning Whenever #snd_config is updated, all string pointers and
3789 * configuration node handles previously obtained from it may become
3790 * invalid.
3791 *
3792 * \par Errors:
3793 * Any errors encountered when parsing the input or returned by hooks or
3794 * functions.
3795 *
3796 * \par Conforming to:
3797 * LSB 3.2
3798 */
3799int snd_config_update(void)
3800{
3801	int err;
3802
3803	snd_config_lock();
3804	err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
3805	snd_config_unlock();
3806	return err;
3807}
3808
3809/**
3810 * \brief Frees a private update structure.
3811 * \param[in] update The private update structure to free.
3812 * \return Zero if successful, otherwise a negative error code.
3813 */
3814int snd_config_update_free(snd_config_update_t *update)
3815{
3816	unsigned int k;
3817
3818	assert(update);
3819	for (k = 0; k < update->count; k++)
3820		free(update->finfo[k].name);
3821	free(update->finfo);
3822	free(update);
3823	return 0;
3824}
3825
3826/**
3827 * \brief Frees the global configuration tree in #snd_config.
3828 * \return Zero if successful, otherwise a negative error code.
3829 *
3830 * This functions releases all resources of the global configuration
3831 * tree, and sets #snd_config to \c NULL.
3832 *
3833 * \par Conforming to:
3834 * LSB 3.2
3835 */
3836int snd_config_update_free_global(void)
3837{
3838	snd_config_lock();
3839	if (snd_config)
3840		snd_config_delete(snd_config);
3841	snd_config = NULL;
3842	if (snd_config_global_update)
3843		snd_config_update_free(snd_config_global_update);
3844	snd_config_global_update = NULL;
3845	snd_config_unlock();
3846	/* FIXME: better to place this in another place... */
3847	snd_dlobj_cache_cleanup();
3848
3849	return 0;
3850}
3851
3852/**
3853 * \brief Returns an iterator pointing to a node's first child.
3854 * \param[in] config Handle to a configuration node.
3855 * \return An iterator pointing to \a config's first child.
3856 *
3857 * \a config must be a compound node.
3858 *
3859 * The returned iterator is valid if it is not equal to the return value
3860 * of #snd_config_iterator_end on \a config.
3861 *
3862 * Use #snd_config_iterator_entry to get the handle of the node pointed
3863 * to.
3864 *
3865 * \par Conforming to:
3866 * LSB 3.2
3867 */
3868snd_config_iterator_t snd_config_iterator_first(const snd_config_t *config)
3869{
3870	assert(config->type == SND_CONFIG_TYPE_COMPOUND);
3871	return config->u.compound.fields.next;
3872}
3873
3874/**
3875 * \brief Returns an iterator pointing to the next sibling.
3876 * \param[in] iterator An iterator pointing to a child configuration node.
3877 * \return An iterator pointing to the next sibling of \a iterator.
3878 *
3879 * The returned iterator is valid if it is not equal to the return value
3880 * of #snd_config_iterator_end on the node's parent.
3881 *
3882 * Use #snd_config_iterator_entry to get the handle of the node pointed
3883 * to.
3884 *
3885 * \par Conforming to:
3886 * LSB 3.2
3887 */
3888snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator)
3889{
3890	return iterator->next;
3891}
3892
3893/**
3894 * \brief Returns an iterator that ends a node's children list.
3895 * \param[in] config Handle to a configuration node.
3896 * \return An iterator that indicates the end of \a config's children list.
3897 *
3898 * \a config must be a compound node.
3899 *
3900 * The return value can be understood as pointing past the last child of
3901 * \a config.
3902 *
3903 * \par Conforming to:
3904 * LSB 3.2
3905 */
3906snd_config_iterator_t snd_config_iterator_end(const snd_config_t *config)
3907{
3908	assert(config->type == SND_CONFIG_TYPE_COMPOUND);
3909	return (const snd_config_iterator_t)&config->u.compound.fields;
3910}
3911
3912/**
3913 * \brief Returns the configuration node handle pointed to by an iterator.
3914 * \param[in] iterator A configuration node iterator.
3915 * \return The configuration node handle pointed to by \a iterator.
3916 *
3917 * \par Conforming to:
3918 * LSB 3.2
3919 */
3920snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator)
3921{
3922	return list_entry(iterator, snd_config_t, list);
3923}
3924
3925#ifndef DOC_HIDDEN
3926typedef enum _snd_config_walk_pass {
3927	SND_CONFIG_WALK_PASS_PRE,
3928	SND_CONFIG_WALK_PASS_POST,
3929	SND_CONFIG_WALK_PASS_LEAF,
3930} snd_config_walk_pass_t;
3931#endif
3932
3933/* Return 1 if node needs to be attached to parent */
3934/* Return 2 if compound is replaced with standard node */
3935#ifndef DOC_HIDDEN
3936typedef int (*snd_config_walk_callback_t)(snd_config_t *src,
3937					  snd_config_t *root,
3938					  snd_config_t **dst,
3939					  snd_config_walk_pass_t pass,
3940					  snd_config_t *private_data);
3941#endif
3942
3943static int snd_config_walk(snd_config_t *src,
3944			   snd_config_t *root,
3945			   snd_config_t **dst,
3946			   snd_config_walk_callback_t callback,
3947			   snd_config_t *private_data)
3948{
3949	int err;
3950	snd_config_iterator_t i, next;
3951
3952	switch (snd_config_get_type(src)) {
3953	case SND_CONFIG_TYPE_COMPOUND:
3954		err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, private_data);
3955		if (err <= 0)
3956			return err;
3957		snd_config_for_each(i, next, src) {
3958			snd_config_t *s = snd_config_iterator_entry(i);
3959			snd_config_t *d = NULL;
3960
3961			err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL,
3962					      callback, private_data);
3963			if (err < 0)
3964				goto _error;
3965			if (err && d) {
3966				err = snd_config_add(*dst, d);
3967				if (err < 0)
3968					goto _error;
3969			}
3970		}
3971		err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, private_data);
3972		if (err <= 0) {
3973		_error:
3974			if (dst && *dst)
3975				snd_config_delete(*dst);
3976		}
3977		break;
3978	default:
3979		err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, private_data);
3980		break;
3981	}
3982	return err;
3983}
3984
3985static int _snd_config_copy(snd_config_t *src,
3986			    snd_config_t *root ATTRIBUTE_UNUSED,
3987			    snd_config_t **dst,
3988			    snd_config_walk_pass_t pass,
3989			    snd_config_t *private_data ATTRIBUTE_UNUSED)
3990{
3991	int err;
3992	const char *id = src->id;
3993	snd_config_type_t type = snd_config_get_type(src);
3994	switch (pass) {
3995	case SND_CONFIG_WALK_PASS_PRE:
3996		err = snd_config_make_compound(dst, id, src->u.compound.join);
3997		if (err < 0)
3998			return err;
3999		break;
4000	case SND_CONFIG_WALK_PASS_LEAF:
4001		err = snd_config_make(dst, id, type);
4002		if (err < 0)
4003			return err;
4004		switch (type) {
4005		case SND_CONFIG_TYPE_INTEGER:
4006		{
4007			long v;
4008			err = snd_config_get_integer(src, &v);
4009			assert(err >= 0);
4010			snd_config_set_integer(*dst, v);
4011			break;
4012		}
4013		case SND_CONFIG_TYPE_INTEGER64:
4014		{
4015			long long v;
4016			err = snd_config_get_integer64(src, &v);
4017			assert(err >= 0);
4018			snd_config_set_integer64(*dst, v);
4019			break;
4020		}
4021		case SND_CONFIG_TYPE_REAL:
4022		{
4023			double v;
4024			err = snd_config_get_real(src, &v);
4025			assert(err >= 0);
4026			snd_config_set_real(*dst, v);
4027			break;
4028		}
4029		case SND_CONFIG_TYPE_STRING:
4030		{
4031			const char *s;
4032			err = snd_config_get_string(src, &s);
4033			assert(err >= 0);
4034			err = snd_config_set_string(*dst, s);
4035			if (err < 0)
4036				return err;
4037			break;
4038		}
4039		default:
4040			assert(0);
4041		}
4042		break;
4043	default:
4044		break;
4045	}
4046	return 1;
4047}
4048
4049/**
4050 * \brief Creates a copy of a configuration node.
4051 * \param[out] dst The function puts the handle to the new configuration
4052 *                 node at the address specified by \a dst.
4053 * \param[in] src Handle to the source configuration node.
4054 * \return A non-negative value if successful, otherwise a negative error code.
4055 *
4056 * This function creates a deep copy, i.e., if \a src is a compound
4057 * node, all children are copied recursively.
4058 *
4059 * \par Errors:
4060 * <dl>
4061 * <dt>-ENOMEM<dd>Out of memory.
4062 * </dl>
4063 *
4064 * \par Conforming to:
4065 * LSB 3.2
4066 */
4067int snd_config_copy(snd_config_t **dst,
4068		    snd_config_t *src)
4069{
4070	return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL);
4071}
4072
4073static int _snd_config_expand(snd_config_t *src,
4074			      snd_config_t *root ATTRIBUTE_UNUSED,
4075			      snd_config_t **dst,
4076			      snd_config_walk_pass_t pass,
4077			      snd_config_t *private_data)
4078{
4079	int err;
4080	const char *id = src->id;
4081	snd_config_type_t type = snd_config_get_type(src);
4082	switch (pass) {
4083	case SND_CONFIG_WALK_PASS_PRE:
4084	{
4085		if (id && strcmp(id, "@args") == 0)
4086			return 0;
4087		err = snd_config_make_compound(dst, id, src->u.compound.join);
4088		if (err < 0)
4089			return err;
4090		break;
4091	}
4092	case SND_CONFIG_WALK_PASS_LEAF:
4093		switch (type) {
4094		case SND_CONFIG_TYPE_INTEGER:
4095		{
4096			long v;
4097			err = snd_config_get_integer(src, &v);
4098			assert(err >= 0);
4099			err = snd_config_imake_integer(dst, id, v);
4100			if (err < 0)
4101				return err;
4102			break;
4103		}
4104		case SND_CONFIG_TYPE_INTEGER64:
4105		{
4106			long long v;
4107			err = snd_config_get_integer64(src, &v);
4108			assert(err >= 0);
4109			err = snd_config_imake_integer64(dst, id, v);
4110			if (err < 0)
4111				return err;
4112			break;
4113		}
4114		case SND_CONFIG_TYPE_REAL:
4115		{
4116			double v;
4117			err = snd_config_get_real(src, &v);
4118			assert(err >= 0);
4119			err = snd_config_imake_real(dst, id, v);
4120			if (err < 0)
4121				return err;
4122			break;
4123		}
4124		case SND_CONFIG_TYPE_STRING:
4125		{
4126			const char *s;
4127			snd_config_t *val;
4128			snd_config_t *vars = private_data;
4129			snd_config_get_string(src, &s);
4130			if (s && *s == '$') {
4131				s++;
4132				if (snd_config_search(vars, s, &val) < 0)
4133					return 0;
4134				err = snd_config_copy(dst, val);
4135				if (err < 0)
4136					return err;
4137				err = snd_config_set_id(*dst, id);
4138				if (err < 0) {
4139					snd_config_delete(*dst);
4140					return err;
4141				}
4142			} else {
4143				err = snd_config_imake_string(dst, id, s);
4144				if (err < 0)
4145					return err;
4146			}
4147			break;
4148		}
4149		default:
4150			assert(0);
4151		}
4152		break;
4153	default:
4154		break;
4155	}
4156	return 1;
4157}
4158
4159static int _snd_config_evaluate(snd_config_t *src,
4160				snd_config_t *root,
4161				snd_config_t **dst ATTRIBUTE_UNUSED,
4162				snd_config_walk_pass_t pass,
4163				snd_config_t *private_data)
4164{
4165	int err;
4166	if (pass == SND_CONFIG_WALK_PASS_PRE) {
4167		char *buf = NULL;
4168		const char *lib = NULL, *func_name = NULL;
4169		const char *str;
4170		int (*func)(snd_config_t **dst, snd_config_t *root,
4171			    snd_config_t *src, snd_config_t *private_data) = NULL;
4172		void *h = NULL;
4173		snd_config_t *c, *func_conf = NULL;
4174		err = snd_config_search(src, "@func", &c);
4175		if (err < 0)
4176			return 1;
4177		err = snd_config_get_string(c, &str);
4178		if (err < 0) {
4179			SNDERR("Invalid type for @func");
4180			return err;
4181		}
4182		assert(str);
4183		err = snd_config_search_definition(root, "func", str, &func_conf);
4184		if (err >= 0) {
4185			snd_config_iterator_t i, next;
4186			if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
4187				SNDERR("Invalid type for func %s definition", str);
4188				goto _err;
4189			}
4190			snd_config_for_each(i, next, func_conf) {
4191				snd_config_t *n = snd_config_iterator_entry(i);
4192				const char *id = n->id;
4193				if (strcmp(id, "comment") == 0)
4194					continue;
4195				if (strcmp(id, "lib") == 0) {
4196					err = snd_config_get_string(n, &lib);
4197					if (err < 0) {
4198						SNDERR("Invalid type for %s", id);
4199						goto _err;
4200					}
4201					continue;
4202				}
4203				if (strcmp(id, "func") == 0) {
4204					err = snd_config_get_string(n, &func_name);
4205					if (err < 0) {
4206						SNDERR("Invalid type for %s", id);
4207						goto _err;
4208					}
4209					continue;
4210				}
4211				SNDERR("Unknown field %s", id);
4212			}
4213		}
4214		if (!func_name) {
4215			int len = 9 + strlen(str) + 1;
4216			buf = malloc(len);
4217			if (! buf) {
4218				err = -ENOMEM;
4219				goto _err;
4220			}
4221			snprintf(buf, len, "snd_func_%s", str);
4222			buf[len-1] = '\0';
4223			func_name = buf;
4224		}
4225		h = snd_dlopen(lib, RTLD_NOW);
4226		if (h)
4227			func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE));
4228		err = 0;
4229		if (!h) {
4230			SNDERR("Cannot open shared library %s", lib);
4231			err = -ENOENT;
4232			goto _errbuf;
4233		} else if (!func) {
4234			SNDERR("symbol %s is not defined inside %s", func_name, lib);
4235			snd_dlclose(h);
4236			err = -ENXIO;
4237			goto _errbuf;
4238		}
4239	       _err:
4240		if (func_conf)
4241			snd_config_delete(func_conf);
4242		if (err >= 0) {
4243			snd_config_t *eval;
4244			err = func(&eval, root, src, private_data);
4245			if (err < 0)
4246				SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
4247			snd_dlclose(h);
4248			if (err >= 0 && eval) {
4249				/* substitute merges compound members */
4250				/* we don't want merging at all */
4251				err = snd_config_delete_compound_members(src);
4252				if (err >= 0)
4253					err = snd_config_substitute(src, eval);
4254			}
4255		}
4256	       _errbuf:
4257		free(buf);
4258		if (err < 0)
4259			return err;
4260		return 0;
4261	}
4262	return 1;
4263}
4264
4265/**
4266 * \brief Evaluates a configuration node at runtime.
4267 * \param[in,out] config Handle to the source configuration node.
4268 * \param[in] root Handle to the root of the source configuration.
4269 * \param[in] private_data Handle to the private data node for runtime evaluation.
4270 * \param result Must be \c NULL.
4271 * \return A non-negative value if successful, otherwise a negative error code.
4272 *
4273 * This function evaluates any functions (\c \@func) in \a config and
4274 * replaces those nodes with the respective function results.
4275 */
4276int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
4277		        snd_config_t *private_data, snd_config_t **result)
4278{
4279	/* FIXME: Only in place evaluation is currently implemented */
4280	assert(result == NULL);
4281	return snd_config_walk(config, root, result, _snd_config_evaluate, private_data);
4282}
4283
4284static int load_defaults(snd_config_t *subs, snd_config_t *defs)
4285{
4286	snd_config_iterator_t d, dnext;
4287	snd_config_for_each(d, dnext, defs) {
4288		snd_config_t *def = snd_config_iterator_entry(d);
4289		snd_config_iterator_t f, fnext;
4290		if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND)
4291			continue;
4292		snd_config_for_each(f, fnext, def) {
4293			snd_config_t *fld = snd_config_iterator_entry(f);
4294			const char *id = fld->id;
4295			if (strcmp(id, "type") == 0)
4296				continue;
4297			if (strcmp(id, "default") == 0) {
4298				snd_config_t *deflt;
4299				int err;
4300				err = snd_config_copy(&deflt, fld);
4301				if (err < 0)
4302					return err;
4303				err = snd_config_set_id(deflt, def->id);
4304				if (err < 0) {
4305					snd_config_delete(deflt);
4306					return err;
4307				}
4308				err = snd_config_add(subs, deflt);
4309				if (err < 0) {
4310					snd_config_delete(deflt);
4311					return err;
4312				}
4313				continue;
4314			}
4315			SNDERR("Unknown field %s", id);
4316			return -EINVAL;
4317		}
4318	}
4319	return 0;
4320}
4321
4322static void skip_blank(const char **ptr)
4323{
4324	while (1) {
4325		switch (**ptr) {
4326		case ' ':
4327		case '\f':
4328		case '\t':
4329		case '\n':
4330		case '\r':
4331			break;
4332		default:
4333			return;
4334		}
4335		(*ptr)++;
4336	}
4337}
4338
4339static int parse_char(const char **ptr)
4340{
4341	int c;
4342	assert(**ptr == '\\');
4343	(*ptr)++;
4344	c = **ptr;
4345	switch (c) {
4346	case 'n':
4347		c = '\n';
4348		break;
4349	case 't':
4350		c = '\t';
4351		break;
4352	case 'v':
4353		c = '\v';
4354		break;
4355	case 'b':
4356		c = '\b';
4357		break;
4358	case 'r':
4359		c = '\r';
4360		break;
4361	case 'f':
4362		c = '\f';
4363		break;
4364	case '0' ... '7':
4365	{
4366		int num = c - '0';
4367		int i = 1;
4368		(*ptr)++;
4369		do {
4370			c = **ptr;
4371			if (c < '0' || c > '7')
4372				break;
4373			num = num * 8 + c - '0';
4374			i++;
4375			(*ptr)++;
4376		} while (i < 3);
4377		return num;
4378	}
4379	default:
4380		break;
4381	}
4382	(*ptr)++;
4383	return c;
4384}
4385
4386static int parse_id(const char **ptr)
4387{
4388	if (!**ptr)
4389		return -EINVAL;
4390	while (1) {
4391		switch (**ptr) {
4392		case '\f':
4393		case '\t':
4394		case '\n':
4395		case '\r':
4396		case ',':
4397		case '=':
4398		case '\0':
4399			return 0;
4400		default:
4401			break;
4402		}
4403		(*ptr)++;
4404	}
4405}
4406
4407static int parse_string(const char **ptr, char **val)
4408{
4409	const size_t bufsize = 256;
4410	char _buf[bufsize];
4411	char *buf = _buf;
4412	size_t alloc = bufsize;
4413	char delim = **ptr;
4414	size_t idx = 0;
4415	(*ptr)++;
4416	while (1) {
4417		int c = **ptr;
4418		switch (c) {
4419		case '\0':
4420			SNDERR("Unterminated string");
4421			return -EINVAL;
4422		case '\\':
4423			c = parse_char(ptr);
4424			if (c < 0)
4425				return c;
4426			break;
4427		default:
4428			(*ptr)++;
4429			if (c == delim) {
4430				*val = malloc(idx + 1);
4431				if (!*val)
4432					return -ENOMEM;
4433				memcpy(*val, buf, idx);
4434				(*val)[idx] = 0;
4435				if (alloc > bufsize)
4436					free(buf);
4437				return 0;
4438			}
4439		}
4440		if (idx >= alloc) {
4441			size_t old_alloc = alloc;
4442			alloc *= 2;
4443			if (old_alloc == bufsize) {
4444				buf = malloc(alloc);
4445				memcpy(buf, _buf, old_alloc);
4446			} else {
4447				buf = realloc(buf, alloc);
4448			}
4449			if (!buf)
4450				return -ENOMEM;
4451		}
4452		buf[idx++] = c;
4453	}
4454}
4455
4456
4457/* Parse var=val or val */
4458static int parse_arg(const char **ptr, unsigned int *varlen, char **val)
4459{
4460	const char *str;
4461	int err, vallen;
4462	skip_blank(ptr);
4463	str = *ptr;
4464	if (*str == '"' || *str == '\'') {
4465		err = parse_string(ptr, val);
4466		if (err < 0)
4467			return err;
4468		*varlen = 0;
4469		return 0;
4470	}
4471	err = parse_id(ptr);
4472	if (err < 0)
4473		return err;
4474	vallen = *ptr - str;
4475	skip_blank(ptr);
4476	if (**ptr != '=') {
4477		*varlen = 0;
4478		goto _value;
4479	}
4480	*varlen = vallen;
4481	(*ptr)++;
4482	skip_blank(ptr);
4483	str = *ptr;
4484	if (*str == '"' || *str == '\'') {
4485		err = parse_string(ptr, val);
4486		if (err < 0)
4487			return err;
4488		return 0;
4489	}
4490	err = parse_id(ptr);
4491	if (err < 0)
4492		return err;
4493	vallen = *ptr - str;
4494 _value:
4495	*val = malloc(vallen + 1);
4496	if (!*val)
4497		return -ENOMEM;
4498	memcpy(*val, str, vallen);
4499	(*val)[vallen] = 0;
4500	return 0;
4501}
4502
4503
4504/* val1, val2, ...
4505 * var1=val1,var2=val2,...
4506 * { conf syntax }
4507 */
4508static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
4509{
4510	int err;
4511	int arg = 0;
4512	if (str == NULL)
4513		return 0;
4514	skip_blank(&str);
4515	if (!*str)
4516		return 0;
4517	if (*str == '{') {
4518		int len = strlen(str);
4519		snd_input_t *input;
4520		snd_config_iterator_t i, next;
4521		while (1) {
4522			switch (str[--len]) {
4523			case ' ':
4524			case '\f':
4525			case '\t':
4526			case '\n':
4527			case '\r':
4528				continue;
4529			default:
4530				break;
4531			}
4532			break;
4533		}
4534		if (str[len] != '}')
4535			return -EINVAL;
4536		err = snd_input_buffer_open(&input, str + 1, len - 1);
4537		if (err < 0)
4538			return err;
4539		err = snd_config_load_override(subs, input);
4540		snd_input_close(input);
4541		if (err < 0)
4542			return err;
4543		snd_config_for_each(i, next, subs) {
4544			snd_config_t *n = snd_config_iterator_entry(i);
4545			snd_config_t *d;
4546			const char *id = n->id;
4547			err = snd_config_search(defs, id, &d);
4548			if (err < 0) {
4549				SNDERR("Unknown parameter %s", id);
4550				return err;
4551			}
4552		}
4553		return 0;
4554	}
4555
4556	while (1) {
4557		char buf[256];
4558		const char *var = buf;
4559		unsigned int varlen;
4560		snd_config_t *def, *sub, *typ;
4561		const char *new = str;
4562		const char *tmp;
4563		char *val = NULL;
4564		err = parse_arg(&new, &varlen, &val);
4565		if (err < 0)
4566			goto _err;
4567		if (varlen > 0) {
4568			assert(varlen < sizeof(buf));
4569			memcpy(buf, str, varlen);
4570			buf[varlen] = 0;
4571		} else {
4572			sprintf(buf, "%d", arg);
4573		}
4574		err = snd_config_search_alias(defs, NULL, var, &def);
4575		if (err < 0) {
4576			SNDERR("Unknown parameter %s", var);
4577			goto _err;
4578		}
4579		if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) {
4580			SNDERR("Parameter %s definition is not correct", var);
4581			err = -EINVAL;
4582			goto _err;
4583		}
4584		var = def->id;
4585		err = snd_config_search(subs, var, &sub);
4586		if (err >= 0)
4587			snd_config_delete(sub);
4588		err = snd_config_search(def, "type", &typ);
4589		if (err < 0) {
4590		_invalid_type:
4591			SNDERR("Parameter %s definition is missing a valid type info", var);
4592			goto _err;
4593		}
4594		err = snd_config_get_string(typ, &tmp);
4595		if (err < 0 || !tmp)
4596			goto _invalid_type;
4597		if (strcmp(tmp, "integer") == 0) {
4598			long v;
4599			err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER);
4600			if (err < 0)
4601				goto _err;
4602			err = safe_strtol(val, &v);
4603			if (err < 0) {
4604				SNDERR("Parameter %s must be an integer", var);
4605				goto _err;
4606			}
4607			err = snd_config_set_integer(sub, v);
4608			if (err < 0)
4609				goto _err;
4610		} else if (strcmp(tmp, "integer64") == 0) {
4611			long long v;
4612			err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER64);
4613			if (err < 0)
4614				goto _err;
4615			err = safe_strtoll(val, &v);
4616			if (err < 0) {
4617				SNDERR("Parameter %s must be an integer", var);
4618				goto _err;
4619			}
4620			err = snd_config_set_integer64(sub, v);
4621			if (err < 0)
4622				goto _err;
4623		} else if (strcmp(tmp, "real") == 0) {
4624			double v;
4625			err = snd_config_make(&sub, var, SND_CONFIG_TYPE_REAL);
4626			if (err < 0)
4627				goto _err;
4628			err = safe_strtod(val, &v);
4629			if (err < 0) {
4630				SNDERR("Parameter %s must be a real", var);
4631				goto _err;
4632			}
4633			err = snd_config_set_real(sub, v);
4634			if (err < 0)
4635				goto _err;
4636		} else if (strcmp(tmp, "string") == 0) {
4637			err = snd_config_make(&sub, var, SND_CONFIG_TYPE_STRING);
4638			if (err < 0)
4639				goto _err;
4640			err = snd_config_set_string(sub, val);
4641			if (err < 0)
4642				goto _err;
4643		} else {
4644			err = -EINVAL;
4645			goto _invalid_type;
4646		}
4647		err = snd_config_set_id(sub, var);
4648		if (err < 0)
4649			goto _err;
4650		err = snd_config_add(subs, sub);
4651		if (err < 0) {
4652		_err:
4653			free(val);
4654			return err;
4655		}
4656		free(val);
4657		if (!*new)
4658			break;
4659		if (*new != ',')
4660			return -EINVAL;
4661		str = new + 1;
4662		arg++;
4663	}
4664	return 0;
4665}
4666
4667/**
4668 * \brief Expands a configuration node, applying arguments and functions.
4669 * \param[in] config Handle to the configuration node.
4670 * \param[in] root Handle to the root configuration node.
4671 * \param[in] args Arguments string, can be \c NULL.
4672 * \param[in] private_data Handle to the private data node for functions.
4673 * \param[out] result The function puts the handle to the result
4674 *                    configuration node at the address specified by
4675 *                    \a result.
4676 * \return A non-negative value if successful, otherwise a negative error code.
4677 *
4678 * If \a config has arguments (defined by a child with id \c \@args),
4679 * this function replaces any string node beginning with $ with the
4680 * respective argument value, or the default argument value, or nothing.
4681 * Furthermore, any functions are evaluated (see #snd_config_evaluate).
4682 * The resulting copy of \a config is returned in \a result.
4683 */
4684int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args,
4685		      snd_config_t *private_data, snd_config_t **result)
4686{
4687	int err;
4688	snd_config_t *defs, *subs = NULL, *res;
4689	err = snd_config_search(config, "@args", &defs);
4690	if (err < 0) {
4691		if (args != NULL) {
4692			SNDERR("Unknown parameters %s", args);
4693			return -EINVAL;
4694		}
4695		err = snd_config_copy(&res, config);
4696		if (err < 0)
4697			return err;
4698	} else {
4699		err = snd_config_top(&subs);
4700		if (err < 0)
4701			return err;
4702		err = load_defaults(subs, defs);
4703		if (err < 0) {
4704			SNDERR("Load defaults error: %s", snd_strerror(err));
4705			goto _end;
4706		}
4707		err = parse_args(subs, args, defs);
4708		if (err < 0) {
4709			SNDERR("Parse arguments error: %s", snd_strerror(err));
4710			goto _end;
4711		}
4712		err = snd_config_evaluate(subs, root, private_data, NULL);
4713		if (err < 0) {
4714			SNDERR("Args evaluate error: %s", snd_strerror(err));
4715			goto _end;
4716		}
4717		err = snd_config_walk(config, root, &res, _snd_config_expand, subs);
4718		if (err < 0) {
4719			SNDERR("Expand error (walk): %s", snd_strerror(err));
4720			goto _end;
4721		}
4722	}
4723	err = snd_config_evaluate(res, root, private_data, NULL);
4724	if (err < 0) {
4725		SNDERR("Evaluate error: %s", snd_strerror(err));
4726		snd_config_delete(res);
4727		goto _end;
4728	}
4729	*result = res;
4730	err = 1;
4731 _end:
4732 	if (subs)
4733		snd_config_delete(subs);
4734	return err;
4735}
4736
4737/**
4738 * \brief Searches for a definition in a configuration tree, using
4739 *        aliases and expanding hooks and arguments.
4740 * \param[in] config Handle to the configuration (sub)tree to search.
4741 * \param[in] base Implicit key base, or \c NULL for none.
4742 * \param[in] name Key suffix, optionally with arguments.
4743 * \param[out] result The function puts the handle to the expanded found
4744 *                    node at the address specified by \a result.
4745 * \return A non-negative value if successful, otherwise a negative error code.
4746 *
4747 * This functions searches for a child node of \a config, allowing
4748 * aliases and expanding hooks, like #snd_config_search_alias_hooks.
4749 *
4750 * If \a name contains a colon (:), the rest of the string after the
4751 * colon contains arguments that are expanded as with
4752 * #snd_config_expand.
4753 *
4754 * In any case, \a result is a new node that must be freed by the
4755 * caller.
4756 *
4757 * \par Errors:
4758 * <dl>
4759 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
4760 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
4761 *                not a compound node.
4762 * </dl>
4763 * Additionally, any errors encountered when parsing the hook
4764 * definitions or arguments, or returned by (hook) functions.
4765 */
4766int snd_config_search_definition(snd_config_t *config,
4767				 const char *base, const char *name,
4768				 snd_config_t **result)
4769{
4770	snd_config_t *conf;
4771	char *key;
4772	const char *args = strchr(name, ':');
4773	int err;
4774	if (args) {
4775		args++;
4776		key = alloca(args - name);
4777		memcpy(key, name, args - name - 1);
4778		key[args - name - 1] = '\0';
4779	} else {
4780		key = (char *) name;
4781	}
4782	/*
4783	 *  if key contains dot (.), the implicit base is ignored
4784	 *  and the key starts from root given by the 'config' parameter
4785	 */
4786	snd_config_lock();
4787	err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf);
4788	if (err < 0) {
4789		snd_config_unlock();
4790		return err;
4791	}
4792	err = snd_config_expand(conf, config, args, NULL, result);
4793	snd_config_unlock();
4794	return err;
4795}
4796
4797#ifndef DOC_HIDDEN
4798void snd_config_set_hop(snd_config_t *conf, int hop)
4799{
4800	conf->hop = hop;
4801}
4802
4803int snd_config_check_hop(snd_config_t *conf)
4804{
4805	if (conf) {
4806		if (conf->hop >= SND_CONF_MAX_HOPS) {
4807			SYSERR("Too many definition levels (looped?)\n");
4808			return -EINVAL;
4809		}
4810		return conf->hop;
4811	}
4812	return 0;
4813}
4814#endif
4815
4816#if 0
4817/* Not strictly needed, but useful to check for memory leaks */
4818void _snd_config_end(void) __attribute__ ((destructor));
4819
4820static void _snd_config_end(void)
4821{
4822	int k;
4823	if (snd_config)
4824		snd_config_delete(snd_config);
4825	snd_config = 0;
4826	for (k = 0; k < files_info_count; ++k)
4827		free(files_info[k].name);
4828	free(files_info);
4829	files_info = NULL;
4830	files_info_count = 0;
4831}
4832#endif
4833