OSDN Git Service

Maik Broemme <mbroemme@plusserver.de>
[android-x86/external-alsa-lib.git] / src / conf.c
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@suse.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@suse.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
38 data description like nesting and array assignments.</P>
39
40 \section conf_whitespace Whitespace
41
42 Whitespace is the collective name given to spaces (blanks), horizontal and
43 vertical tabs, newline characters, and comments. Whitespace can
44 indicate where configuration tokens start and end, but beyond this function,
45 any surplus whitespace is discarded. For example, the two sequences
46
47 \code
48   a 1 b 2
49 \endcode
50
51 and
52
53 \code
54   a 1 
55      b 2
56 \endcode
57
58 are lexically equivalent and parse identically to give the four tokens:
59
60 \code
61 a
62 1
63 b
64 2
65 \endcode
66
67 The ASCII characters representing whitespace can occur within literal
68 strings, 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
75 parses to two tokens, including the single literal-string token "John
76 Smith".
77
78 \section conf_linesplicing Line continuation with \
79
80 A special case occurs if a newline character in a string is preceded
81 by a backslash (\). The backslash and the new line are both discarded,
82 allowing two physical lines of text to be treated as one unit.
83
84 \code
85 "John \
86 Smith"
87 \endcode
88
89 is parsed as "John Smith".
90
91 \section conf_comments Comments
92
93 A single-line comment begins with the character #. The comment can start
94 at 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
102 To include another configuration file, write the file name in angle brackets.
103 The 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
112 The 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
120 Opening and closing braces { } indicate the start and end of a compound
121 statement:
122
123 \code
124 a {
125   b 1
126 }
127 \endcode
128
129 \subsection conf_brackets Brackets
130
131 Opening and closing brackets indicate a single array definition. The
132 identifiers are automatically generated starting with zero.
133
134 \code
135 a [
136   "first"
137   "second"
138 ]
139 \endcode
140
141 The above code is equal to
142
143 \code
144 a.0 "first"
145 a.1 "second"
146 \endcode
147
148 \subsection conf_comma_semicolon Comma and semicolon
149
150 The comma (,) or semicolon (;) can separate value assignments. It is not
151 strictly required to use these separators because whitespace suffices to
152 separate tokens.
153
154 \code
155 a 1;
156 b 1,
157 \endcode
158
159 \subsection conf_equal Equal sign
160
161 The equal sign (=) can separate variable declarations from
162 initialization lists:
163
164 \code
165 a=1
166 b=2
167 \endcode
168
169 Using equal signs is not required because whitespace suffices to separate
170 tokens.
171
172 \section conf_assigns Assignments
173
174 The configuration file defines id (key) and value pairs. The id (key) can be
175 composed from ASCII digits, characters from a to z and A to Z, and the
176 underscore (_). The value can be either a string, an integer, a real number,
177 or a compound statement.
178
179 \subsection conf_single Single assignments
180
181 \code
182 a 1     # is equal to
183 a=1     # is equal to
184 a=1;    # is equal to
185 a 1,
186 \endcode
187
188 \subsection conf_compound Compound assignments (definitions using braces)
189
190 \code
191 a {
192   b = 1
193 }
194 a={
195   b 1,
196 }
197 \endcode
198
199 \section conf_compound1 Compound assignments (one key definitions)
200
201 \code
202 a.b 1
203 a.b=1
204 \endcode
205
206 \subsection conf_array Array assignments (definitions using brackets)
207
208 \code
209 a [
210   "first"
211   "second"
212 ]
213 \endcode
214
215 \subsection conf_array1 Array assignments (one key definitions)
216
217 \code
218 a.0 "first"
219 a.1 "second"
220 \endcode
221
222 \section conf_mode Operation modes for parsing nodes
223
224 By default, the node operation mode is 'merge+create', i.e., if
225 a configuration node is not present a new one is created, otherwise
226 the latest assignment is merged (if possible - type checking). The
227 'merge+create' operation mode is specified with the prefix character plus (+).
228
229 The operation mode 'merge' merges the node with the old one (which must
230 exist). Type checking is done, so strings cannot be assigned to integers
231 and so on. This mode is specified with the prefix character minus (-).
232
233 The operation mode 'do not override' ignores a new configuration node
234 if a configuration node with the same name exists. This mode is specified with
235 the prefix character question mark (?).
236
237 The operation mode 'override' always overrides the old configuration node
238 with new contents. This mode is specified with the prefix character
239 exclamation mark (!).
240
241 \code
242 defaults.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
254 name [=] value [,|;]
255
256 # Compound assignment (first style)
257 name [=] {
258         name1 [=] value [,|;]
259         ...
260 }
261
262 # Compound assignment (second style)
263 name.name1 [=] value [,|;]
264
265 # Array assignment (first style)
266 name [
267         value0 [,|;]
268         value1 [,|;]
269         ...
270 ]
271
272 # Array assignment (second style)
273 name.0 [=] value0 [,|;]
274 name.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
288 blocks. This extension is built on top of the basic configuration file
289 syntax.<P>
290
291 \section confarg_define Defining arguments
292
293 Arguments are defined using the id (key) \c @args and array values containing
294 the 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
303 An argument's type is specified with the id (key) \c @args and the argument
304 name. 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
315 Arguments 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
323 To use a block with arguments, write the argument values after the key,
324 separated with a colon (:). For example, all these names for PCM interfaces
325 give the same result:
326
327 \code
328 hw:0,1
329 hw:CARD=0,DEV=1
330 hw:{CARD 0 DEV 1}
331 plug:"hw:0,1"
332 plug:{SLAVE="hw:{CARD 0 DEV 1}"}
333 \endcode
334
335 As you see, arguments can be specified in their proper order or by name.
336 Note that arguments enclosed in braces are parsed in the same way as in
337 configuration files, but using the override method by default.
338
339 \section confarg_example Example
340
341 \code
342 pcm.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.
363 Several built-in functions are available.</P>
364
365 <P>A function is defined with the id \c @func and the function name. All other
366 values in the current compound are used as configuration for the function.
367 If the compound func.<function_name> is defined in the root node, then the
368 library 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.
370 The definition of a function looks like:</P> 
371
372 \code
373 func.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
384 nodes at run-time. The existence of a hook is determined by the
385 presence of a @hooks compound node.</P>
386
387 <P>This example defines a hook which loads two configuration files at the
388 beginning:</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 <wordexp.h>
419 #include <dlfcn.h>
420 #include <limits.h>
421 #include <sys/stat.h>
422 #include <pthread.h>
423 #include "local.h"
424
425 #ifndef DOC_HIDDEN
426
427 struct _snd_config {
428         char *id;
429         snd_config_type_t type;
430         union {
431                 long integer;
432                 long long integer64;
433                 char *string;
434                 double real;
435                 const void *ptr;
436                 struct {
437                         struct list_head fields;
438                         int join;
439                 } compound;
440         } u;
441         struct list_head list;
442         snd_config_t *father;
443 };
444
445 struct filedesc {
446         char *name;
447         snd_input_t *in;
448         unsigned int line, column;
449         struct filedesc *next;
450 };
451
452 #define LOCAL_ERROR                     (-0x68000000)
453
454 #define LOCAL_UNTERMINATED_STRING       (LOCAL_ERROR - 0)
455 #define LOCAL_UNTERMINATED_QUOTE        (LOCAL_ERROR - 1)
456 #define LOCAL_UNEXPECTED_CHAR           (LOCAL_ERROR - 2)
457 #define LOCAL_UNEXPECTED_EOF            (LOCAL_ERROR - 3)
458
459 typedef struct {
460         struct filedesc *current;
461         int unget;
462         int ch;
463 } input_t;
464
465 static int safe_strtoll(const char *str, long long *val)
466 {
467         long long v;
468         int endidx;
469         if (!*str)
470                 return -EINVAL;
471         errno = 0;
472         if (sscanf(str, "%Ld%n", &v, &endidx) < 1)
473                 return -EINVAL;
474         if (str[endidx])
475                 return -EINVAL;
476         *val = v;
477         return 0;
478 }
479
480 int safe_strtol(const char *str, long *val)
481 {
482         char *end;
483         long v;
484         if (!*str)
485                 return -EINVAL;
486         errno = 0;
487         v = strtol(str, &end, 0);
488         if (errno)
489                 return -errno;
490         if (*end)
491                 return -EINVAL;
492         *val = v;
493         return 0;
494 }
495
496 static int safe_strtod(const char *str, double *val)
497 {
498         char *end;
499         double v;
500         if (!*str)
501                 return -EINVAL;
502         errno = 0;
503         v = strtod(str, &end);
504         if (errno)
505                 return -errno;
506         if (*end)
507                 return -EINVAL;
508         *val = v;
509         return 0;
510 }
511
512 static int get_char(input_t *input)
513 {
514         int c;
515         struct filedesc *fd;
516         if (input->unget) {
517                 input->unget = 0;
518                 return input->ch;
519         }
520  again:
521         fd = input->current;
522         c = snd_input_getc(fd->in);
523         switch (c) {
524         case '\n':
525                 fd->column = 0;
526                 fd->line++;
527                 break;
528         case '\t':
529                 fd->column += 8 - fd->column % 8;
530                 break;
531         case EOF:
532                 if (fd->next) {
533                         snd_input_close(fd->in);
534                         free(fd->name);
535                         input->current = fd->next;
536                         free(fd);
537                         goto again;
538                 }
539                 return LOCAL_UNEXPECTED_EOF;
540         default:
541                 fd->column++;
542                 break;
543         }
544         return (unsigned char)c;
545 }
546
547 static void unget_char(int c, input_t *input)
548 {
549         assert(!input->unget);
550         input->ch = c;
551         input->unget = 1;
552 }
553
554 static int get_delimstring(char **string, int delim, input_t *input);
555
556 static int get_char_skip_comments(input_t *input)
557 {
558         int c;
559         while (1) {
560                 c = get_char(input);
561                 if (c == '<') {
562                         char *str;
563                         snd_input_t *in;
564                         struct filedesc *fd;
565                         int err = get_delimstring(&str, '>', input);
566                         if (err < 0)
567                                 return err;
568                         if (!strncmp(str, "confdir:", 8)) {
569                                 char *tmp = malloc(strlen(DATADIR "/alsa") + 1 + strlen(str + 8) + 1);
570                                 if (tmp == NULL) {
571                                         free(str);
572                                         return -ENOMEM;
573                                 }
574                                 sprintf(tmp, DATADIR "/alsa/%s", str + 8);
575                                 free(str);
576                                 str = tmp;
577                         }
578                         err = snd_input_stdio_open(&in, str, "r");
579                         if (err < 0) {
580                                 free(str);
581                                 return err;
582                         }
583                         fd = malloc(sizeof(*fd));
584                         if (!fd) {
585                                 free(str);
586                                 return -ENOMEM;
587                         }
588                         fd->name = str;
589                         fd->in = in;
590                         fd->next = input->current;
591                         fd->line = 1;
592                         fd->column = 0;
593                         input->current = fd;
594                         continue;
595                 }
596                 if (c != '#')
597                         break;
598                 while (1) {
599                         c = get_char(input);
600                         if (c < 0)
601                                 return c;
602                         if (c == '\n')
603                                 break;
604                 }
605         }
606                 
607         return c;
608 }
609                         
610
611 static int get_nonwhite(input_t *input)
612 {
613         int c;
614         while (1) {
615                 c = get_char_skip_comments(input);
616                 switch (c) {
617                 case ' ':
618                 case '\f':
619                 case '\t':
620                 case '\n':
621                 case '\r':
622                         break;
623                 default:
624                         return c;
625                 }
626         }
627 }
628
629 static int get_quotedchar(input_t *input)
630 {
631         int c;
632         c = get_char(input);
633         switch (c) {
634         case 'n':
635                 return '\n';
636         case 't':
637                 return '\t';
638         case 'v':
639                 return '\v';
640         case 'b':
641                 return '\b';
642         case 'r':
643                 return '\r';
644         case 'f':
645                 return '\f';
646         case '0' ... '7':
647         {
648                 int num = c - '0';
649                 int i = 1;
650                 do {
651                         c = get_char(input);
652                         if (c < '0' || c > '7') {
653                                 unget_char(c, input);
654                                 break;
655                         }
656                         num = num * 8 + c - '0';
657                         i++;
658                 } while (i < 3);
659                 return num;
660         }
661         default:
662                 return c;
663         }
664 }
665
666 static int get_freestring(char **string, int id, input_t *input)
667 {
668         const size_t bufsize = 64;
669         char _buf[bufsize];
670         char *buf = _buf;
671         size_t alloc = bufsize;
672         size_t idx = 0;
673         int c;
674         while (1) {
675                 c = get_char(input);
676                 if (c < 0) {
677                         if (c == LOCAL_UNEXPECTED_EOF) {
678                                 char *s = malloc(idx + 1);
679                                 if (!s)
680                                         return -ENOMEM;
681                                 memcpy(s, buf, idx);
682                                 s[idx] = '\0';
683                                 *string = s;
684                                 c = 0;
685                         }
686                         if (alloc > bufsize)
687                                 free(buf);
688                         return c;
689                 }
690                 switch (c) {
691                 case '.':
692                         if (!id)
693                                 break;
694                 case ' ':
695                 case '\f':
696                 case '\t':
697                 case '\n':
698                 case '\r':
699                 case '=':
700                 case ',':
701                 case ';':
702                 case '{':
703                 case '}':
704                 case '[':
705                 case ']':
706                 case '\'':
707                 case '"':
708                 case '\\':
709                 case '#':
710                 {
711                         char *s = malloc(idx + 1);
712                         if (!s)
713                                 return -ENOMEM;
714                         unget_char(c, input);
715                         memcpy(s, buf, idx);
716                         s[idx] = '\0';
717                         *string = s;
718                         if (alloc > bufsize)
719                                 free(buf);
720                         return 0;
721                 }
722                 default:
723                         break;
724                 }
725                 if (idx >= alloc) {
726                         size_t old_alloc = alloc;
727                         alloc *= 2;
728                         if (old_alloc == bufsize) {
729                                 buf = malloc(alloc);
730                                 if (buf == NULL)
731                                         return -ENOMEM;
732                                 memcpy(buf, _buf, old_alloc);
733                         } else {
734                                 char *ptr = realloc(buf, alloc);
735                                 if (ptr == NULL) {
736                                         free(buf);
737                                         return -ENOMEM;
738                                 }
739                                 buf = ptr;
740                         }
741                 }
742                 buf[idx++] = c;
743         }
744         return 0;
745 }
746                         
747 static int get_delimstring(char **string, int delim, input_t *input)
748 {
749         const size_t bufsize = 64;
750         char _buf[bufsize];
751         char *buf = _buf;
752         size_t alloc = bufsize;
753         size_t idx = 0;
754         int c;
755         while (1) {
756                 c = get_char(input);
757                 if (c < 0)
758                         return c;
759                 switch (c) {
760                 case '\\':
761                         c = get_quotedchar(input);
762                         if (c < 0)
763                                 return c;
764                         if (c == '\n')
765                                 continue;
766                         break;
767                 default:
768                         if (c == delim) {
769                                 char *s = malloc(idx + 1);
770                                 if (!s)
771                                         return -ENOMEM;
772                                 memcpy(s, buf, idx);
773                                 s[idx] = '\0';
774                                 *string = s;
775                                 if (alloc > bufsize)
776                                         free(buf);
777                                 return 0;
778                         }
779                 }
780                 if (idx >= alloc) {
781                         size_t old_alloc = alloc;
782                         alloc *= 2;
783                         if (old_alloc == bufsize) {
784                                 buf = malloc(alloc);
785                                 if (buf == NULL)
786                                         return -ENOMEM;
787                                 memcpy(buf, _buf, old_alloc);
788                         } else {
789                                 char *ptr = realloc(buf, alloc);
790                                 if (ptr == NULL) {
791                                         free(buf);
792                                         return -ENOMEM;
793                                 }
794                                 buf = ptr;
795                         }
796                 }
797                 buf[idx++] = c;
798         }
799 }
800
801 /* Return 0 for free string, 1 for delimited string */
802 static int get_string(char **string, int id, input_t *input)
803 {
804         int c = get_nonwhite(input), err;
805         if (c < 0)
806                 return c;
807         switch (c) {
808         case '=':
809         case ',':
810         case ';':
811         case '.':
812         case '{':
813         case '}':
814         case '[':
815         case ']':
816                 return LOCAL_UNEXPECTED_CHAR;
817         case '\'':
818         case '"':
819                 err = get_delimstring(string, c, input);
820                 if (err < 0)
821                         return err;
822                 return 1;
823         default:
824                 unget_char(c, input);
825                 err = get_freestring(string, id, input);
826                 if (err < 0)
827                         return err;
828                 return 0;
829         }
830 }
831
832 static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
833 {
834         snd_config_t *n;
835         assert(config);
836         n = calloc(1, sizeof(*n));
837         if (n == NULL) {
838                 if (*id) {
839                         free(*id);
840                         *id = NULL;
841                 }
842                 return -ENOMEM;
843         }
844         if (id) {
845                 n->id = *id;
846                 *id = NULL;
847         }
848         n->type = type;
849         if (type == SND_CONFIG_TYPE_COMPOUND)
850                 INIT_LIST_HEAD(&n->u.compound.fields);
851         *config = n;
852         return 0;
853 }
854         
855
856 static int _snd_config_make_add(snd_config_t **config, char **id,
857                                 snd_config_type_t type, snd_config_t *father)
858 {
859         snd_config_t *n;
860         int err;
861         assert(father->type == SND_CONFIG_TYPE_COMPOUND);
862         err = _snd_config_make(&n, id, type);
863         if (err < 0)
864                 return err;
865         n->father = father;
866         list_add_tail(&n->list, &father->u.compound.fields);
867         *config = n;
868         return 0;
869 }
870
871 static int _snd_config_search(snd_config_t *config, 
872                               const char *id, int len, snd_config_t **result)
873 {
874         snd_config_iterator_t i, next;
875         snd_config_for_each(i, next, config) {
876                 snd_config_t *n = snd_config_iterator_entry(i);
877                 if (len < 0) {
878                         if (strcmp(n->id, id) != 0)
879                                 continue;
880                 } else if (strlen(n->id) != (size_t) len ||
881                            memcmp(n->id, id, (size_t) len) != 0)
882                                 continue;
883                 if (result)
884                         *result = n;
885                 return 0;
886         }
887         return -ENOENT;
888 }
889
890 static int parse_value(snd_config_t **_n, snd_config_t *father, input_t *input, char **id, int skip)
891 {
892         snd_config_t *n = *_n;
893         char *s;
894         int err;
895
896         err = get_string(&s, 0, input);
897         if (err < 0)
898                 return err;
899         if (skip) {
900                 free(s);
901                 return 0;
902         }
903         if (err == 0 && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) {
904                 long long i;
905                 errno = 0;
906                 err = safe_strtoll(s, &i);
907                 if (err < 0) {
908                         double r;
909                         err = safe_strtod(s, &r);
910                         if (err >= 0) {
911                                 free(s);
912                                 if (n) {
913                                         if (n->type != SND_CONFIG_TYPE_REAL) {
914                                                 SNDERR("%s is not a real", *id);
915                                                 return -EINVAL;
916                                         }
917                                 } else {
918                                         err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, father);
919                                         if (err < 0)
920                                                 return err;
921                                 }
922                                 n->u.real = r;
923                                 *_n = n;
924                                 return 0;
925                         }
926                 } else {
927                         free(s);
928                         if (n) {
929                                 if (n->type != SND_CONFIG_TYPE_INTEGER && n->type != SND_CONFIG_TYPE_INTEGER64) {
930                                         SNDERR("%s is not an integer", *id);
931                                         return -EINVAL;
932                                 }
933                         } else {
934                                 if (i <= INT_MAX) 
935                                         err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, father);
936                                 else
937                                         err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER64, father);
938                                 if (err < 0)
939                                         return err;
940                         }
941                         if (n->type == SND_CONFIG_TYPE_INTEGER) 
942                                 n->u.integer = (long) i;
943                         else 
944                                 n->u.integer64 = i;
945                         *_n = n;
946                         return 0;
947                 }
948         }
949         if (n) {
950                 if (n->type != SND_CONFIG_TYPE_STRING) {
951                         SNDERR("%s is not a string", *id);
952                         free(s);
953                         return -EINVAL;
954                 }
955         } else {
956                 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, father);
957                 if (err < 0)
958                         return err;
959         }
960         if (n->u.string)
961                 free(n->u.string);
962         n->u.string = s;
963         *_n = n;
964         return 0;
965 }
966
967 static int parse_defs(snd_config_t *father, input_t *input, int skip, int override);
968 static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override);
969
970 static int parse_array_def(snd_config_t *father, input_t *input, int idx, int skip, int override)
971 {
972         char static_id[12], *id = NULL;
973         int c;
974         int err;
975         snd_config_t *n = NULL;
976
977         if (!skip) {
978                 snprintf(static_id, sizeof(static_id), "%i", idx);
979                 static_id[sizeof(static_id)-1] = '\0';
980                 id = strdup(static_id);
981                 if (id == NULL)
982                         return -ENOMEM;
983         }
984         c = get_nonwhite(input);
985         if (c < 0) {
986                 err = c;
987                 goto __end;
988         }
989         switch (c) {
990         case '{':
991         case '[':
992         {
993                 char endchr;
994                 if (!skip) {
995                         if (n) {
996                                 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
997                                         SNDERR("%s is not a compound", id);
998                                         err = -EINVAL;
999                                         goto __end;
1000                                 }
1001                         } else {
1002                                 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, father);
1003                                 if (err < 0)
1004                                         goto __end;
1005                         }
1006                 }
1007                 if (c == '{') {
1008                         err = parse_defs(n, input, skip, override);
1009                         endchr = '}';
1010                 } else {
1011                         err = parse_array_defs(n, input, skip, override);
1012                         endchr = ']';
1013                 }
1014                 c = get_nonwhite(input);
1015                 if (c < 0) {
1016                         err = c;
1017                         goto __end;
1018                 }
1019                 if (c != endchr) {
1020                         if (n)
1021                                 snd_config_delete(n);
1022                         err = LOCAL_UNEXPECTED_CHAR;
1023                         goto __end;
1024                 }
1025                 break;
1026         }
1027         default:
1028                 unget_char(c, input);
1029                 err = parse_value(&n, father, input, &id, skip);
1030                 if (err < 0)
1031                         goto __end;
1032                 break;
1033         }
1034         err = 0;
1035       __end:
1036         if (id)
1037                 free(id);
1038         return err;
1039 }
1040
1041 static int parse_array_defs(snd_config_t *father, input_t *input, int skip, int override)
1042 {
1043         int idx = 0;
1044         while (1) {
1045                 int c = get_nonwhite(input), err;
1046                 if (c < 0)
1047                         return c;
1048                 unget_char(c, input);
1049                 if (c == ']')
1050                         return 0;
1051                 err = parse_array_def(father, input, idx++, skip, override);
1052                 if (err < 0)
1053                         return err;
1054         }
1055         return 0;
1056 }
1057
1058 static int parse_def(snd_config_t *father, input_t *input, int skip, int override)
1059 {
1060         char *id = NULL;
1061         int c;
1062         int err;
1063         snd_config_t *n;
1064         enum {MERGE_CREATE, MERGE, OVERRIDE, DONT_OVERRIDE} mode;
1065         while (1) {
1066                 c = get_nonwhite(input);
1067                 if (c < 0)
1068                         return c;
1069                 switch (c) {
1070                 case '+':
1071                         mode = MERGE_CREATE;
1072                         break;
1073                 case '-':
1074                         mode = MERGE;
1075                         break;
1076                 case '?':
1077                         mode = DONT_OVERRIDE;
1078                         break;
1079                 case '!':
1080                         mode = OVERRIDE;
1081                         break;
1082                 default:
1083                         mode = !override ? MERGE_CREATE : OVERRIDE;
1084                         unget_char(c, input);
1085                 }
1086                 err = get_string(&id, 1, input);
1087                 if (err < 0)
1088                         return err;
1089                 c = get_nonwhite(input);
1090                 if (c != '.')
1091                         break;
1092                 if (skip) {
1093                         free(id);
1094                         continue;
1095                 }
1096                 if (_snd_config_search(father, id, -1, &n) == 0) {
1097                         if (mode == DONT_OVERRIDE) {
1098                                 skip = 1;
1099                                 free(id);
1100                                 continue;
1101                         }
1102                         if (mode != OVERRIDE) {
1103                                 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1104                                         SNDERR("%s is not a compound", id);
1105                                         return -EINVAL;
1106                                 }
1107                                 n->u.compound.join = 1;
1108                                 father = n;
1109                                 free(id);
1110                                 continue;
1111                         }
1112                         snd_config_delete(n);
1113                 }
1114                 if (mode == MERGE) {
1115                         SNDERR("%s does not exists", id);
1116                         err = -ENOENT;
1117                         goto __end;
1118                 }
1119                 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, father);
1120                 if (err < 0)
1121                         goto __end;
1122                 n->u.compound.join = 1;
1123                 father = n;
1124         }
1125         if (c == '=') {
1126                 c = get_nonwhite(input);
1127                 if (c < 0)
1128                         return c;
1129         }
1130         if (!skip) {
1131                 if (_snd_config_search(father, id, -1, &n) == 0) {
1132                         if (mode == DONT_OVERRIDE) {
1133                                 skip = 1;
1134                                 n = NULL;
1135                         } else if (mode == OVERRIDE) {
1136                                 snd_config_delete(n);
1137                                 n = NULL;
1138                         }
1139                 } else {
1140                         n = NULL;
1141                         if (mode == MERGE) {
1142                                 SNDERR("%s does not exists", id);
1143                                 err = -ENOENT;
1144                                 goto __end;
1145                         }
1146                 }
1147         }
1148         switch (c) {
1149         case '{':
1150         case '[':
1151         {
1152                 char endchr;
1153                 if (!skip) {
1154                         if (n) {
1155                                 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1156                                         SNDERR("%s is not a compound", id);
1157                                         err = -EINVAL;
1158                                         goto __end;
1159                                 }
1160                         } else {
1161                                 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, father);
1162                                 if (err < 0)
1163                                         goto __end;
1164                         }
1165                 }
1166                 if (c == '{') {
1167                         err = parse_defs(n, input, skip, override);
1168                         endchr = '}';
1169                 } else {
1170                         err = parse_array_defs(n, input, skip, override);
1171                         endchr = ']';
1172                 }
1173                 c = get_nonwhite(input);
1174                 if (c != endchr) {
1175                         if (n)
1176                                 snd_config_delete(n);
1177                         err = LOCAL_UNEXPECTED_CHAR;
1178                         goto __end;
1179                 }
1180                 break;
1181         }
1182         default:
1183                 unget_char(c, input);
1184                 err = parse_value(&n, father, input, &id, skip);
1185                 if (err < 0)
1186                         goto __end;
1187                 break;
1188         }
1189         c = get_nonwhite(input);
1190         switch (c) {
1191         case ';':
1192         case ',':
1193                 break;
1194         default:
1195                 unget_char(c, input);
1196         }
1197       __end:
1198         if (id)
1199                 free(id);
1200         return err;
1201 }
1202                 
1203 static int parse_defs(snd_config_t *father, input_t *input, int skip, int override)
1204 {
1205         int c, err;
1206         while (1) {
1207                 c = get_nonwhite(input);
1208                 if (c < 0)
1209                         return c == LOCAL_UNEXPECTED_EOF ? 0 : c;
1210                 unget_char(c, input);
1211                 if (c == '}')
1212                         return 0;
1213                 err = parse_def(father, input, skip, override);
1214                 if (err < 0)
1215                         return err;
1216         }
1217         return 0;
1218 }
1219
1220 static void string_print(char *str, int id, snd_output_t *out)
1221 {
1222         unsigned char *p = str;
1223         if (!id) {
1224                 switch (*p) {
1225                 case 0:
1226                         assert(0);
1227                         break;
1228                 case '0' ... '9':
1229                 case '-':
1230                         goto quoted;
1231                 }
1232         }
1233         if (!*p) {
1234                 snd_output_puts(out, "''");
1235                 return;
1236         }
1237  loop:
1238         switch (*p) {
1239         case 0:
1240                 goto nonquoted;
1241         case 1 ... 31:
1242         case 127 ... 255:
1243         case ' ':
1244         case '=':
1245         case ';':
1246         case ',':
1247         case '.':
1248         case '{':
1249         case '}':
1250         case '\'':
1251         case '"':
1252                 goto quoted;
1253         default:
1254                 p++;
1255                 goto loop;
1256         }
1257  nonquoted:
1258         snd_output_puts(out, str);
1259         return;
1260  quoted:
1261         snd_output_putc(out, '\'');
1262         p = str;
1263         while (*p) {
1264                 int c;
1265                 c = *p;
1266                 switch (c) {
1267                 case '\n':
1268                         snd_output_putc(out, '\\');
1269                         snd_output_putc(out, 'n');
1270                         break;
1271                 case '\t':
1272                         snd_output_putc(out, '\\');
1273                         snd_output_putc(out, 't');
1274                         break;
1275                 case '\v':
1276                         snd_output_putc(out, '\\');
1277                         snd_output_putc(out, 'v');
1278                         break;
1279                 case '\b':
1280                         snd_output_putc(out, '\\');
1281                         snd_output_putc(out, 'b');
1282                         break;
1283                 case '\r':
1284                         snd_output_putc(out, '\\');
1285                         snd_output_putc(out, 'r');
1286                         break;
1287                 case '\f':
1288                         snd_output_putc(out, '\\');
1289                         snd_output_putc(out, 'f');
1290                         break;
1291                 case '\'':
1292                         snd_output_putc(out, '\\');
1293                         snd_output_putc(out, c);
1294                         break;
1295                 case 32 ... '\'' - 1:
1296                 case '\'' + 1 ... 126:
1297                         snd_output_putc(out, c);
1298                         break;
1299                 default:
1300                         snd_output_printf(out, "\\%04o", c);
1301                         break;
1302                 }
1303                 p++;
1304         }
1305         snd_output_putc(out, '\'');
1306 }
1307
1308 static int _snd_config_save_leaves(snd_config_t *config, snd_output_t *out, unsigned int level, unsigned int joins);
1309
1310 static int _snd_config_save_leaf(snd_config_t *n, snd_output_t *out, 
1311                                  unsigned int level)
1312 {
1313         int err;
1314         unsigned int k;
1315         switch (n->type) {
1316         case SND_CONFIG_TYPE_INTEGER:
1317                 snd_output_printf(out, "%ld", n->u.integer);
1318                 break;
1319         case SND_CONFIG_TYPE_INTEGER64:
1320                 snd_output_printf(out, "%Ld", n->u.integer64);
1321                 break;
1322         case SND_CONFIG_TYPE_REAL:
1323                 snd_output_printf(out, "%-16g", n->u.real);
1324                 break;
1325         case SND_CONFIG_TYPE_STRING:
1326                 string_print(n->u.string, 0, out);
1327                 break;
1328         case SND_CONFIG_TYPE_POINTER:
1329                 SNDERR("cannot save runtime pointer type");
1330                 return -EINVAL;
1331         case SND_CONFIG_TYPE_COMPOUND:
1332                 snd_output_putc(out, '{');
1333                 snd_output_putc(out, '\n');
1334                 err = _snd_config_save_leaves(n, out, level + 1, 0);
1335                 if (err < 0)
1336                         return err;
1337                 for (k = 0; k < level; ++k) {
1338                         snd_output_putc(out, '\t');
1339                 }
1340                 snd_output_putc(out, '}');
1341                 break;
1342         }
1343         return 0;
1344 }
1345
1346 static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins)
1347 {
1348         if (joins > 0) {
1349                 assert(n->father);
1350                 id_print(n->father, out, joins - 1);
1351                 snd_output_putc(out, '.');
1352         }
1353         string_print(n->id, 1, out);
1354 }
1355
1356 static int _snd_config_save_leaves(snd_config_t *config, snd_output_t *out, unsigned int level, unsigned int joins)
1357 {
1358         unsigned int k;
1359         int err;
1360         snd_config_iterator_t i, next;
1361         assert(config && out);
1362         snd_config_for_each(i, next, config) {
1363                 snd_config_t *n = snd_config_iterator_entry(i);
1364                 if (n->type == SND_CONFIG_TYPE_COMPOUND &&
1365                     n->u.compound.join) {
1366                         err = _snd_config_save_leaves(n, out, level, joins + 1);
1367                         if (err < 0)
1368                                 return err;
1369                         continue;
1370                 }
1371                 for (k = 0; k < level; ++k) {
1372                         snd_output_putc(out, '\t');
1373                 }
1374                 id_print(n, out, joins);
1375 #if 0
1376                 snd_output_putc(out, ' ');
1377                 snd_output_putc(out, '=');
1378 #endif
1379                 snd_output_putc(out, ' ');
1380                 err = _snd_config_save_leaf(n, out, level);
1381                 if (err < 0)
1382                         return err;
1383 #if 0
1384                 snd_output_putc(out, ';');
1385 #endif
1386                 snd_output_putc(out, '\n');
1387         }
1388         return 0;
1389 }
1390 #endif
1391
1392
1393 /**
1394  * \brief Substitutes one configuration node to another.
1395  * \param dst Handle to the destination node.
1396  * \param src Handle to the source node. Must not be the same as \p dst.
1397  * \return Zero if successful, otherwise a negative error code.
1398  *
1399  * If both nodes are compounds, the source compound node members are
1400  * appended to the destination compound node.
1401  *
1402  * If the destination node is a compound and the source node is
1403  * an ordinary type, the compound members are deleted (including
1404  * their contents).
1405  *
1406  * A successful call to this function invalidates the source node.
1407  */
1408 int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
1409 {
1410         assert(dst && src);
1411         if (dst->type == SND_CONFIG_TYPE_COMPOUND &&
1412             src->type == SND_CONFIG_TYPE_COMPOUND) {    /* append */
1413                 snd_config_iterator_t i, next;
1414                 snd_config_for_each(i, next, src) {
1415                         snd_config_t *n = snd_config_iterator_entry(i);
1416                         n->father = dst;
1417                 }
1418                 src->u.compound.fields.next->prev = &dst->u.compound.fields;
1419                 src->u.compound.fields.prev->next = &dst->u.compound.fields;
1420         } else if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
1421                 int err;
1422                 err = snd_config_delete_compound_members(dst);
1423                 if (err < 0)
1424                         return err;
1425         }
1426         if (dst->id)
1427                 free(dst->id);
1428         dst->id = src->id;
1429         dst->type = src->type;
1430         dst->u = src->u;
1431         free(src);
1432         return 0;
1433 }
1434
1435 /**
1436  * \brief Converts an ASCII string to a configuration node type.
1437  * \param ascii A string containing a configuration node type.
1438  * \param type The function puts the node type at the address specified
1439  *             by \p type.
1440  * \return Zero if successgul, otherwise a negative error code.
1441  */
1442 int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
1443 {
1444         assert(ascii && type);
1445         if (!strcmp(ascii, "integer")) {
1446                 *type = SND_CONFIG_TYPE_INTEGER;
1447                 return 0;
1448         }
1449         if (!strcmp(ascii, "integer64")) {
1450                 *type = SND_CONFIG_TYPE_INTEGER64;
1451                 return 0;
1452         }
1453         if (!strcmp(ascii, "real")) {
1454                 *type = SND_CONFIG_TYPE_REAL;
1455                 return 0;
1456         }
1457         if (!strcmp(ascii, "string")) {
1458                 *type = SND_CONFIG_TYPE_STRING;
1459                 return 0;
1460         }
1461         if (!strcmp(ascii, "compound")) {
1462                 *type = SND_CONFIG_TYPE_COMPOUND;
1463                 return 0;
1464         }
1465         return -EINVAL;
1466 }
1467
1468 /**
1469  * \brief Returns the type of a configuration node.
1470  * \param config Handle to the configuration node.
1471  * \return The node's type.
1472  */
1473 snd_config_type_t snd_config_get_type(const snd_config_t *config)
1474 {
1475         return config->type;
1476 }
1477
1478 /**
1479  * \brief Returns the id of a configuration node.
1480  * \param config Handle to the configuration node.
1481  * \param id The function puts the pointer to the id string at the address
1482  *           specified by \p id.
1483  * \return Zero if successful, otherwise a negative error code.
1484  *
1485  * The returned string is owned by the configuration node; the application
1486  * must not modify or delete it.
1487  */
1488 int snd_config_get_id(const snd_config_t *config, const char **id)
1489 {
1490         assert(config && id);
1491         *id = config->id;
1492         return 0;
1493 }
1494
1495 /**
1496  * \brief Sets the id of a configuration node.
1497  * \param config Handle to the configuration node.
1498  * \param id The new node id.
1499  * \return Zero if successful, otherwise a negative error code.
1500  */
1501 int snd_config_set_id(snd_config_t *config, const char *id)
1502 {
1503         char *new_id;
1504         assert(config && id);
1505         new_id = strdup(id);
1506         if (!new_id)
1507                 return -ENOMEM;
1508         if (config->id)
1509                 free(config->id);
1510         config->id = new_id;
1511         return 0;
1512 }
1513
1514 /**
1515  * \brief Creates a top level configuration node.
1516  * \param config The function puts the handle to the new node at the address
1517  *               specified by \p config.
1518  * \return Zero if successful, otherwise a negative error code.
1519  *
1520  * The returned node is a compound node.
1521  */
1522 int snd_config_top(snd_config_t **config)
1523 {
1524         assert(config);
1525         return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
1526 }
1527
1528 static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override)
1529 {
1530         int err;
1531         input_t input;
1532         struct filedesc *fd, *fd_next;
1533         assert(config && in);
1534         fd = malloc(sizeof(*fd));
1535         if (!fd)
1536                 return -ENOMEM;
1537         fd->name = NULL;
1538         fd->in = in;
1539         fd->line = 1;
1540         fd->column = 0;
1541         fd->next = NULL;
1542         input.current = fd;
1543         input.unget = 0;
1544         err = parse_defs(config, &input, 0, override);
1545         fd = input.current;
1546         if (err < 0) {
1547                 const char *str;
1548                 switch (err) {
1549                 case LOCAL_UNTERMINATED_STRING:
1550                         str = "Unterminated string";
1551                         break;
1552                 case LOCAL_UNTERMINATED_QUOTE:
1553                         str = "Unterminated quote";
1554                         break;
1555                 case LOCAL_UNEXPECTED_CHAR:
1556                         str = "Unexpected char";
1557                         break;
1558                 case LOCAL_UNEXPECTED_EOF:
1559                         str = "Unexpected end of file";
1560                         break;
1561                 default:
1562                         str = strerror(-err);
1563                         break;
1564                 }
1565                 SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
1566                 goto _end;
1567         }
1568         if (get_char(&input) != LOCAL_UNEXPECTED_EOF) {
1569                 SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
1570                 err = -EINVAL;
1571                 goto _end;
1572         }
1573  _end:
1574         while (fd->next) {
1575                 fd_next = fd->next;
1576                 snd_input_close(fd->in);
1577                 free(fd->name);
1578                 free(fd);
1579                 fd = fd_next;
1580         }
1581         free(fd);
1582         return err;
1583 }
1584
1585 /**
1586  * \brief Loads a configuration tree.
1587  * \param config Handle to a top level configuration node.
1588  * \param in Input handle to read the configuration from.
1589  * \return Zero if successful, otherwise a negative error code.
1590  */
1591 int snd_config_load(snd_config_t *config, snd_input_t *in)
1592 {
1593         return snd_config_load1(config, in, 0);
1594 }
1595
1596 /**
1597  * \brief Loads a configuration tree and overrides existing configuration nodes.
1598  * \param config Handle to a top level configuration node.
1599  * \param in Input handle to read the configuration from.
1600  * \return Zero if successful, otherwise a negative error code.
1601  */
1602 int snd_config_load_override(snd_config_t *config, snd_input_t *in)
1603 {
1604         return snd_config_load1(config, in, 1);
1605 }
1606
1607 /**
1608  * \brief Adds a child to a compound configuration node.
1609  * \param father Handle to the compound configuration node.
1610  * \param leaf Handle to the configuration node to be added to \p father.
1611  * \return Zero if successful, otherwise a negative error code.
1612  */
1613 int snd_config_add(snd_config_t *father, snd_config_t *leaf)
1614 {
1615         snd_config_iterator_t i, next;
1616         assert(father && leaf);
1617         snd_config_for_each(i, next, father) {
1618                 snd_config_t *n = snd_config_iterator_entry(i);
1619                 if (strcmp(leaf->id, n->id) == 0)
1620                         return -EEXIST;
1621         }
1622         leaf->father = father;
1623         list_add_tail(&leaf->list, &father->u.compound.fields);
1624         return 0;
1625 }
1626
1627 /**
1628  * \brief Removes a configuration node from its tree.
1629  * \param config Handle to the configuration node to be removed.
1630  * \return Zero if successful, otherwise a negative error code.
1631  *
1632  * This functions does \e not delete the removed node.
1633  */
1634 int snd_config_remove(snd_config_t *config)
1635 {
1636         assert(config);
1637         if (config->father)
1638                 list_del(&config->list);
1639         config->father = NULL;
1640         return 0;
1641 }
1642
1643 /**
1644  * \brief Deletes a configuration node (freeing all its related resources).
1645  * \param config Handle to the configuration node to be deleted.
1646  * \return Zero if successful, otherwise a negative error code.
1647  *
1648  * If the node is a child node, it is removed from the tree before being
1649  * deleted. If the node is a compound node, all children are deleted
1650  * recursively.
1651  */
1652 int snd_config_delete(snd_config_t *config)
1653 {
1654         assert(config);
1655         switch (config->type) {
1656         case SND_CONFIG_TYPE_COMPOUND:
1657         {
1658                 int err;
1659                 struct list_head *i;
1660                 i = config->u.compound.fields.next;
1661                 while (i != &config->u.compound.fields) {
1662                         struct list_head *nexti = i->next;
1663                         snd_config_t *leaf = snd_config_iterator_entry(i);
1664                         err = snd_config_delete(leaf);
1665                         if (err < 0)
1666                                 return err;
1667                         i = nexti;
1668                 }
1669                 break;
1670         }
1671         case SND_CONFIG_TYPE_STRING:
1672                 if (config->u.string)
1673                         free(config->u.string);
1674                 break;
1675         default:
1676                 break;
1677         }
1678         if (config->father)
1679                 list_del(&config->list);
1680         if (config->id)
1681                 free(config->id);
1682         free(config);
1683         return 0;
1684 }
1685
1686 /**
1687  * \brief Deletes the children of a compound configuration node (freeing all its related resources)
1688  * \param config Handle to the compound configuration node.
1689  * \return Zero if successful, otherwise a negative error code.
1690  *
1691  * Any compound nodes among the children of \p config are deleted recursively.
1692  */
1693 int snd_config_delete_compound_members(const snd_config_t *config)
1694 {
1695         int err;
1696         struct list_head *i;
1697
1698         assert(config);
1699         if (config->type != SND_CONFIG_TYPE_COMPOUND)
1700                 return -EINVAL;
1701         i = config->u.compound.fields.next;
1702         while (i != &config->u.compound.fields) {
1703                 struct list_head *nexti = i->next;
1704                 snd_config_t *leaf = snd_config_iterator_entry(i);
1705                 err = snd_config_delete(leaf);
1706                 if (err < 0)
1707                         return err;
1708                 i = nexti;
1709         }
1710         return 0;
1711 }
1712
1713 /**
1714  * \brief Creates a configuration node.
1715  * \param config The function puts the handle to the new node at the address
1716  *               specified by \p config.
1717  * \param id The id of the new node.
1718  * \param type The type of the new node.
1719  * \return Zero if successful, otherwise a negative error code.
1720  */
1721 int snd_config_make(snd_config_t **config, const char *id,
1722                     snd_config_type_t type)
1723 {
1724         char *id1;
1725         assert(config);
1726         if (id) {
1727                 id1 = strdup(id);
1728                 if (!id1)
1729                         return -ENOMEM;
1730         } else
1731                 id1 = NULL;
1732         return _snd_config_make(config, &id1, type);
1733 }
1734
1735 /**
1736  * \brief Creates an integer configuration node.
1737  * \param config The function puts the handle to the new node at the address
1738  *               specified by \p config.
1739  * \param id The id of the new node.
1740  * \return Zero if successful, otherwise a negative error code.
1741  *
1742  * The value of the new node is 0.
1743  */
1744 int snd_config_make_integer(snd_config_t **config, const char *id)
1745 {
1746         return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
1747 }
1748
1749 /**
1750  * \brief Creates an integer64 configuration node.
1751  * \param config The function puts the handle to the new node at the address
1752  *               specified by \p config.
1753  * \param id The id of the new node.
1754  * \return Zero if successful, otherwise a negative error code.
1755  *
1756  * The value of the new node is 0.
1757  */
1758 int snd_config_make_integer64(snd_config_t **config, const char *id)
1759 {
1760         return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
1761 }
1762
1763 /**
1764  * \brief Creates a real configuration node.
1765  * \param config The function puts the handle to the new node at the address
1766  *               specified by \p config.
1767  * \param id The id of the new node.
1768  * \return Zero if successful, otherwise a negative error code.
1769  *
1770  * The value of the new node is 0.0.
1771  */
1772 int snd_config_make_real(snd_config_t **config, const char *id)
1773 {
1774         return snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
1775 }
1776
1777 /**
1778  * \brief Creates a string configuration node.
1779  * \param config The function puts the handle to the new node at the address
1780  *               specified by \p config.
1781  * \param id The id of the new node.
1782  * \return Zero if successful, otherwise a negative error code.
1783  *
1784  * The value of the new node is \c NULL.
1785  */
1786 int snd_config_make_string(snd_config_t **config, const char *id)
1787 {
1788         return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
1789 }
1790
1791 /**
1792  * \brief Creates a pointer configuration node.
1793  * \param config The function puts the handle to the new node at the address
1794  *               specified by \p config.
1795  * \param id The id of the new node.
1796  * \return Zero if successful, otherwise a negative error code.
1797  *
1798  * The value of the new node is \c NULL.
1799  */
1800 int snd_config_make_pointer(snd_config_t **config, const char *id)
1801 {
1802         return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
1803 }
1804
1805 /**
1806  * \brief Creates an empty compound configuration node.
1807  * \param config The function puts the handle to the new node at the address
1808  *               specified by \p config.
1809  * \param id The id of the new node.
1810  * \param join Join flag.
1811  *             This is checked in #snd_config_save to change look. (Huh?)
1812  * \return Zero if successful, otherwise a negative error code.
1813  */
1814 int snd_config_make_compound(snd_config_t **config, const char *id,
1815                              int join)
1816 {
1817         int err;
1818         err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND);
1819         if (err < 0)
1820                 return err;
1821         (*config)->u.compound.join = join;
1822         return 0;
1823 }
1824
1825 /**
1826  * \brief Creates an integer configuration node with the given initial value.
1827  * \param config The function puts the handle to the new node at the address
1828  *               specified by \p config.
1829  * \param id The id of the new node.
1830  * \param value The initial value of the new node.
1831  * \return Zero if successful, otherwise a negative error code.
1832  */
1833 int snd_config_imake_integer(snd_config_t **config, const char *id, const long value)
1834 {
1835         int err;
1836         
1837         err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
1838         if (err < 0)
1839                 return err;
1840         (*config)->u.integer = value;
1841         return 0;
1842 }
1843
1844 /**
1845  * \brief Creates an integer configuration node with the given initial value.
1846  * \param config The function puts the handle to the new node at the address
1847  *               specified by \p config.
1848  * \param id The id of the new node.
1849  * \param value The initial value of the new node.
1850  * \return Zero if successful, otherwise a negative error code.
1851  */
1852 int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value)
1853 {
1854         int err;
1855         
1856         err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
1857         if (err < 0)
1858                 return err;
1859         (*config)->u.integer64 = value;
1860         return 0;
1861 }
1862
1863 /**
1864  * \brief Creates a real configuration node with the given initial value.
1865  * \param config The function puts the handle to the new node at the address
1866  *               specified by \p config.
1867  * \param id The id of the new node.
1868  * \param value The initial value of the new node.
1869  * \return Zero if successful, otherwise a negative error code.
1870  */
1871 int snd_config_imake_real(snd_config_t **config, const char *id, const double value)
1872 {
1873         int err;
1874         
1875         err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
1876         if (err < 0)
1877                 return err;
1878         (*config)->u.real = value;
1879         return 0;
1880 }
1881
1882 /**
1883  * \brief Creates a string configuration node with the given initial value.
1884  * \param config The function puts the handle to the new node at the address
1885  *               specified by \p config.
1886  * \param id The id of the new node.
1887  * \param value The initial value of the new node. May be \c NULL.
1888  * \return Zero if successful, otherwise a negative error code.
1889  *
1890  * This function creates the new node with its own copy of the passed string.
1891  */
1892 int snd_config_imake_string(snd_config_t **config, const char *id, const char *value)
1893 {
1894         int err;
1895         snd_config_t *tmp;
1896         
1897         err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
1898         if (err < 0)
1899                 return err;
1900         if (value) {
1901                 tmp->u.string = strdup(value);
1902                 if (!tmp->u.string) {
1903                         snd_config_delete(tmp);
1904                         return -ENOMEM;
1905                 }
1906         } else {
1907                 tmp->u.string = NULL;
1908         }
1909         *config = tmp;
1910         return 0;
1911 }
1912
1913 /**
1914  * \brief Creates a pointer configuration node with the given initial value.
1915  * \param config The function puts the handle to the new node at the address
1916  *               specified by \p config.
1917  * \param id The id of the new node.
1918  * \param value The initial value of the new node. May be \c NULL.
1919  * \return Zero if successful, otherwise a negative error code.
1920  */
1921 int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value)
1922 {
1923         int err;
1924         
1925         err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
1926         if (err < 0)
1927                 return err;
1928         (*config)->u.ptr = value;
1929         return 0;
1930 }
1931
1932 /**
1933  * \brief Changes the value of an integer configuration node.
1934  * \param config Handle to the configuration node.
1935  * \param value The new value for the node.
1936  * \return Zero if successful, otherwise a negative error code.
1937  */
1938 int snd_config_set_integer(snd_config_t *config, long value)
1939 {
1940         assert(config);
1941         if (config->type != SND_CONFIG_TYPE_INTEGER)
1942                 return -EINVAL;
1943         config->u.integer = value;
1944         return 0;
1945 }
1946
1947 /**
1948  * \brief Changes the value of an integer64 configuration node.
1949  * \param config Handle to the configuration node.
1950  * \param value The new value for the node.
1951  * \return Zero if successful, otherwise a negative error code.
1952  */
1953 int snd_config_set_integer64(snd_config_t *config, long long value)
1954 {
1955         assert(config);
1956         if (config->type != SND_CONFIG_TYPE_INTEGER64)
1957                 return -EINVAL;
1958         config->u.integer64 = value;
1959         return 0;
1960 }
1961
1962 /**
1963  * \brief Changes the value of a real configuration node.
1964  * \param config Handle to the configuration node.
1965  * \param value The new value for the node.
1966  * \return Zero if successful, otherwise a negative error code.
1967  */
1968 int snd_config_set_real(snd_config_t *config, double value)
1969 {
1970         assert(config);
1971         if (config->type != SND_CONFIG_TYPE_REAL)
1972                 return -EINVAL;
1973         config->u.real = value;
1974         return 0;
1975 }
1976
1977 /**
1978  * \brief Changes the value of a string configuration node.
1979  * \param config Handle to the configuration node.
1980  * \param value The new value for the node. May be \c NULL.
1981  * \return Zero if successful, otherwise a negative error code.
1982  *
1983  * This function deletes the old string in the node and stores a copy of
1984  * the passed string in the node.
1985  */
1986 int snd_config_set_string(snd_config_t *config, const char *value)
1987 {
1988         char *new_string;
1989         assert(config);
1990         if (config->type != SND_CONFIG_TYPE_STRING)
1991                 return -EINVAL;
1992         if (value) {
1993                 new_string = strdup(value);
1994                 if (!new_string)
1995                         return -ENOMEM;
1996         } else {
1997                 new_string = NULL;
1998         }
1999         if (config->u.string)
2000                 free(config->u.string);
2001         config->u.string = new_string;
2002         return 0;
2003 }
2004
2005 /**
2006  * \brief Changes the value of a pointer configuration node.
2007  * \param config Handle to the configuration node.
2008  * \param value The new value for the node. May be \c NULL.
2009  * \return Zero if successful, otherwise a negative error code.
2010  *
2011  * This function does not free the old pointer in the node.
2012  */
2013 int snd_config_set_pointer(snd_config_t *config, const void *value)
2014 {
2015         assert(config);
2016         if (config->type != SND_CONFIG_TYPE_POINTER)
2017                 return -EINVAL;
2018         config->u.ptr = value;
2019         return 0;
2020 }
2021
2022 /**
2023  * \brief Changes the value of a configuration node.
2024  * \param config Handle to the configuration node.
2025  * \param ascii The new value for the node as an ASCII string. \p ascii must
2026  *              not be \c NULL, not even for a string node.
2027  * \return Zero if successful, otherwise a negative error code.
2028  *
2029  * The node must have a simple type, and the new value must have the same type.
2030  */
2031 int snd_config_set_ascii(snd_config_t *config, const char *ascii)
2032 {
2033         assert(config && ascii);
2034         switch (config->type) {
2035         case SND_CONFIG_TYPE_INTEGER:
2036                 {
2037                         long i;
2038                         int err = safe_strtol(ascii, &i);
2039                         if (err < 0)
2040                                 return err;
2041                         config->u.integer = i;
2042                 }
2043                 break;
2044         case SND_CONFIG_TYPE_INTEGER64:
2045                 {
2046                         long long i;
2047                         int err = safe_strtoll(ascii, &i);
2048                         if (err < 0)
2049                                 return err;
2050                         config->u.integer64 = i;
2051                 }
2052                 break;
2053         case SND_CONFIG_TYPE_REAL:
2054                 {
2055                         double d;
2056                         int err = safe_strtod(ascii, &d);
2057                         if (err < 0)
2058                                 return err;
2059                         config->u.real = d;
2060                         break;
2061                 }
2062         case SND_CONFIG_TYPE_STRING:
2063                 {
2064                         char *ptr = strdup(ascii);
2065                         if (ptr == NULL)
2066                                 return -ENOMEM;
2067                         if (config->u.string)
2068                                 free(config->u.string);
2069                         config->u.string = ptr;
2070                 }
2071                 break;
2072         default:
2073                 return -EINVAL;
2074         }
2075         return 0;
2076 }
2077
2078 /**
2079  * \brief Returns the value of an integer configuration node.
2080  * \param config Handle to the configuration node.
2081  * \param ptr The function puts the node's value at the address specified
2082  *            by \p ptr.
2083  * \return Zero if successful, otherwise a negative error code.
2084  */
2085 int snd_config_get_integer(const snd_config_t *config, long *ptr)
2086 {
2087         assert(config && ptr);
2088         if (config->type != SND_CONFIG_TYPE_INTEGER)
2089                 return -EINVAL;
2090         *ptr = config->u.integer;
2091         return 0;
2092 }
2093
2094 /**
2095  * \brief Returns the value of an integer64 configuration node.
2096  * \param config Handle to the configuration node.
2097  * \param ptr The function puts the node's value at the address specified
2098  *            by \p ptr.
2099  * \return Zero if successful, otherwise a negative error code.
2100  */
2101 int snd_config_get_integer64(const snd_config_t *config, long long *ptr)
2102 {
2103         assert(config && ptr);
2104         if (config->type != SND_CONFIG_TYPE_INTEGER64)
2105                 return -EINVAL;
2106         *ptr = config->u.integer64;
2107         return 0;
2108 }
2109
2110 /**
2111  * \brief Returns the value of a real configuration node.
2112  * \param config Handle to the configuration node.
2113  * \param ptr The function puts the node's value at the address specified
2114  *            by \p ptr.
2115  * \return Zero if successful, otherwise a negative error code.
2116  */
2117 int snd_config_get_real(const snd_config_t *config, double *ptr)
2118 {
2119         assert(config && ptr);
2120         if (config->type != SND_CONFIG_TYPE_REAL)
2121                 return -EINVAL;
2122         *ptr = config->u.real;
2123         return 0;
2124 }
2125
2126 /**
2127  * \brief Returns the value of a real or integer configuration node.
2128  * \param config Handle to the configuration node.
2129  * \param ptr The function puts the node's value at the address specified
2130  *            by \p ptr.
2131  * \return Zero if successful, otherwise a negative error code.
2132  *
2133  * If the node's type is integer or integer64, the value is converted
2134  * to the \c double type on the fly.
2135  */
2136 int snd_config_get_ireal(const snd_config_t *config, double *ptr)
2137 {
2138         assert(config && ptr);
2139         if (config->type == SND_CONFIG_TYPE_REAL)
2140                 *ptr = config->u.real;
2141         else if (config->type == SND_CONFIG_TYPE_INTEGER)
2142                 *ptr = config->u.integer;
2143         else if (config->type == SND_CONFIG_TYPE_INTEGER64)
2144                 *ptr = config->u.integer64;
2145         else
2146                 return -EINVAL;
2147         return 0;
2148 }
2149
2150 /**
2151  * \brief Returns the value of a string configuration node.
2152  * \param config Handle to the configuration node.
2153  * \param ptr The function puts the node's value at the address specified
2154  *            by \p ptr.
2155  * \return Zero if successful, otherwise a negative error code.
2156  *
2157  * The returned string is owned by the configuration node; the application
2158  * must not modify or delete it.
2159  */
2160 int snd_config_get_string(const snd_config_t *config, const char **ptr)
2161 {
2162         assert(config && ptr);
2163         if (config->type != SND_CONFIG_TYPE_STRING)
2164                 return -EINVAL;
2165         *ptr = config->u.string;
2166         return 0;
2167 }
2168
2169 /**
2170  * \brief Returns the value of a pointer configuration node.
2171  * \param config Handle to the configuration node.
2172  * \param ptr The function puts the node's value at the address specified
2173  *            by \p ptr.
2174  * \return Zero if successful, otherwise a negative error code.
2175  */
2176 int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
2177 {
2178         assert(config && ptr);
2179         if (config->type != SND_CONFIG_TYPE_POINTER)
2180                 return -EINVAL;
2181         *ptr = config->u.ptr;
2182         return 0;
2183 }
2184
2185 /**
2186  * \brief Returns the value of a configuration node as a string.
2187  * \param config Handle to the configuration node.
2188  * \param ascii The function puts the pointer to the returned string at the
2189  *              address specified by \p ascii.
2190  * \return Zero if successful, otherwise a negative error code.
2191  *
2192  * This function dynamically allocates the returned string. The application
2193  * is responsible for deleting it with \c free() when it is no longer used.
2194  */
2195 int snd_config_get_ascii(const snd_config_t *config, char **ascii)
2196 {
2197         assert(config && ascii);
2198         switch (config->type) {
2199         case SND_CONFIG_TYPE_INTEGER:
2200                 {
2201                         char res[12];
2202                         int err;
2203                         err = snprintf(res, sizeof(res), "%li", config->u.integer);
2204                         if (err < 0 || err == sizeof(res)) {
2205                                 assert(0);
2206                                 return -ENOMEM;
2207                         }
2208                         *ascii = strdup(res);
2209                 }
2210                 break;
2211         case SND_CONFIG_TYPE_INTEGER64:
2212                 {
2213                         char res[32];
2214                         int err;
2215                         err = snprintf(res, sizeof(res), "%Li", config->u.integer64);
2216                         if (err < 0 || err == sizeof(res)) {
2217                                 assert(0);
2218                                 return -ENOMEM;
2219                         }
2220                         *ascii = strdup(res);
2221                 }
2222                 break;
2223         case SND_CONFIG_TYPE_REAL:
2224                 {
2225                         char res[32];
2226                         int err;
2227                         err = snprintf(res, sizeof(res), "%-16g", config->u.real);
2228                         if (err < 0 || err == sizeof(res)) {
2229                                 assert(0);
2230                                 return -ENOMEM;
2231                         }
2232                         if (res[0]) {           /* trim the string */
2233                                 char *ptr;
2234                                 ptr = res + strlen(res) - 1;
2235                                 while (ptr != res && *ptr == ' ')
2236                                         ptr--;
2237                                 if (*ptr != ' ')
2238                                         ptr++;
2239                                 *ptr = '\0';
2240                         }
2241                         *ascii = strdup(res);
2242                 }
2243                 break;
2244         case SND_CONFIG_TYPE_STRING:
2245                 if (config->u.string)
2246                         *ascii = strdup(config->u.string);
2247                 else {
2248                         *ascii = NULL;
2249                         return 0;
2250                 }
2251                 break;
2252         default:
2253                 return -EINVAL;
2254         }
2255         if (*ascii == NULL)
2256                 return -ENOMEM;
2257         return 0;
2258 }
2259
2260 /**
2261  * \brief Compares the id of a configuration node to a given string.
2262  * \param config Handle to the configuration node.
2263  * \param id ASCII id.
2264  * \return The same value as the result of the \c strcmp function.
2265  */
2266 int snd_config_test_id(const snd_config_t *config, const char *id)
2267 {
2268         assert(config && id);
2269         return strcmp(config->id, id);
2270 }
2271
2272 /**
2273  * \brief Dumps the contents of a configuration node or tree.
2274  * \param config Handle to the (root) configuration node.
2275  * \param out Output handle.
2276  * \return Zero if successful, otherwise a negative error code.
2277  */
2278 int snd_config_save(snd_config_t *config, snd_output_t *out)
2279 {
2280         assert(config && out);
2281         if (config->type == SND_CONFIG_TYPE_COMPOUND)
2282                 return _snd_config_save_leaves(config, out, 0, 0);
2283         else
2284                 return _snd_config_save_leaf(config, out, 0);
2285 }
2286
2287 /*
2288  *  *** search macros ***
2289  */
2290
2291 #ifndef DOC_HIDDEN
2292
2293 #define SND_CONFIG_SEARCH(config, key, result, extra_code) \
2294 { \
2295         snd_config_t *n; \
2296         int err; \
2297         const char *p; \
2298         assert(config && key); \
2299         while (1) { \
2300                 if (config->type != SND_CONFIG_TYPE_COMPOUND) \
2301                         return -ENOENT; \
2302                 { extra_code ; } \
2303                 p = strchr(key, '.'); \
2304                 if (p) { \
2305                         err = _snd_config_search(config, key, p - key, &n); \
2306                         if (err < 0) \
2307                                 return err; \
2308                         config = n; \
2309                         key = p + 1; \
2310                 } else \
2311                         return _snd_config_search(config, key, -1, result); \
2312         } \
2313 }
2314
2315 #define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \
2316 { \
2317         snd_config_t *n; \
2318         int err; \
2319         const char *p; \
2320         assert(config && key); \
2321         while (1) { \
2322                 if (config->type != SND_CONFIG_TYPE_COMPOUND) { \
2323                         if (snd_config_get_string(config, &p) < 0) \
2324                                 return -ENOENT; \
2325                         err = fcn(root, root, p, &config); \
2326                         if (err < 0) \
2327                                 return err; \
2328                 } \
2329                 { extra_code ; } \
2330                 p = strchr(key, '.'); \
2331                 if (p) { \
2332                         err = _snd_config_search(config, key, p - key, &n); \
2333                         if (err < 0) \
2334                                 return err; \
2335                         config = n; \
2336                         key = p + 1; \
2337                 } else \
2338                         return _snd_config_search(config, key, -1, result); \
2339         } \
2340 }
2341
2342 #define SND_CONFIG_SEARCHV(config, result, fcn) \
2343 { \
2344         snd_config_t *n; \
2345         va_list arg; \
2346         assert(config); \
2347         va_start(arg, result); \
2348         while (1) { \
2349                 const char *k = va_arg(arg, const char *); \
2350                 int err; \
2351                 if (!k) \
2352                         break; \
2353                 err = fcn(config, k, &n); \
2354                 if (err < 0) \
2355                         return err; \
2356                 config = n; \
2357         } \
2358         va_end(arg); \
2359         if (result) \
2360                 *result = n; \
2361         return 0; \
2362 }
2363
2364 #define SND_CONFIG_SEARCHVA(root, config, result, fcn) \
2365 { \
2366         snd_config_t *n; \
2367         va_list arg; \
2368         assert(config); \
2369         va_start(arg, result); \
2370         while (1) { \
2371                 const char *k = va_arg(arg, const char *); \
2372                 int err; \
2373                 if (!k) \
2374                         break; \
2375                 err = fcn(root, config, k, &n); \
2376                 if (err < 0) \
2377                         return err; \
2378                 config = n; \
2379         } \
2380         va_end(arg); \
2381         if (result) \
2382                 *result = n; \
2383         return 0; \
2384 }
2385
2386 #define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
2387 { \
2388         snd_config_t *res = NULL; \
2389         int err, first = 1; \
2390         assert(config && key); \
2391         do { \
2392                 err = first && base ? -EIO : fcn1(config, config, key, &res); \
2393                 if (err < 0) { \
2394                         if (!base) \
2395                                 break; \
2396                         err = fcn2(config, config, &res, base, key, NULL); \
2397                         if (err < 0) \
2398                                 break; \
2399                 } \
2400                 first = 0; \
2401         } while (snd_config_get_string(res, &key) >= 0); \
2402         if (!res) \
2403                 return err; \
2404         if (result) \
2405                 *result = res; \
2406         return 0; \
2407 }
2408
2409 #endif /* DOC_HIDDEN */
2410
2411 /**
2412  * \brief Searches for a node in a configuration tree.
2413  * \param config Handle to the root of the configuration (sub)tree to search.
2414  * \param key Search key: one or more node keys, separated with dots.
2415  * \param result The function puts the handle to the node found at the address
2416  *               specified by \p result.
2417  * \return Zero if successful, otherwise a negative error code.
2418  */
2419 int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
2420 {
2421         SND_CONFIG_SEARCH(config, key, result, );
2422 }
2423
2424 /**
2425  * \brief Searches for a node in a configuration tree, expanding aliases.
2426  * \param root Handle to the root configuration node containing alias
2427  *             definitions.
2428  * \param config Handle to the root of the configuration (sub)tree to search.
2429  * \param key Search key: one or more node keys, separated with dots.
2430  * \param result The function puts the handle to the node found at the address
2431  *               specified by \p result.
2432  * \return Zero if successful, otherwise a negative error code.
2433  */
2434 int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
2435 {
2436         SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, );
2437 }
2438
2439 /**
2440  * \brief Searches for a node in a configuration tree.
2441  * \param config Handle to the root of the configuration (sub)tree to search.
2442  * \param result The function puts the handle to the node found at the address
2443  *               specified by \p result.
2444  * \param ... One or more concatenated dot separated search keys, terminated with \c NULL.
2445  * \return Zero if successful, otherwise a negative error code.
2446  */
2447 int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...)
2448 {
2449         SND_CONFIG_SEARCHV(config, result, snd_config_search);
2450 }
2451
2452 /**
2453  * \brief Searches for a node in a configuration tree, expanding aliases.
2454  * \param root Handle to the root configuration node containing alias
2455  *             definitions.
2456  * \param config Handle to the root of the configuration (sub)tree to search.
2457  * \param result The function puts the handle to the node found at the address
2458  *               specified by \p result.
2459  * \param ... One or more concatenated dot separated search keys, terminated with \c NULL.
2460  * \return Zero if successful, otherwise a negative error code.
2461  */
2462 int snd_config_searchva(snd_config_t *root, snd_config_t *config, snd_config_t **result, ...)
2463 {
2464         SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha);
2465 }
2466
2467 /**
2468  * \brief Searches for a node in a configuration tree, using an alias.
2469  * \param config Handle to the root of the configuration (sub)tree to search.
2470  * \param base Search key base, or \c NULL.
2471  * \param key Search key suffix.
2472  * \param result The function puts the handle to the node found at the address
2473  *               specified by \p result.
2474  * \return Zero if successful, otherwise a negative error code.
2475  *
2476  * First \c key is tried, then, if nothing is found, \c base.key is tried.
2477  * If the value found is a string, this is recursively tried in the
2478  * same way.
2479  */
2480 int snd_config_search_alias(snd_config_t *config,
2481                             const char *base, const char *key,
2482                             snd_config_t **result)
2483 {
2484         SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
2485                                 snd_config_searcha, snd_config_searchva);
2486 }
2487
2488 /**
2489  * \brief Searches for a node in a configuration tree and expands hooks.
2490  * \param config Handle to the root of the configuration (sub)tree to search.
2491  * \param key Search key: one or more node keys, separated with dots.
2492  * \param result The function puts the handle to the node found at the address
2493  *               specified by \p result.
2494  * \return Zero if successful, otherwise a negative error code.
2495  */
2496 int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
2497 {
2498         static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
2499         SND_CONFIG_SEARCH(config, key, result, \
2500                                         err = snd_config_hooks(config, NULL); \
2501                                         if (err < 0) \
2502                                                 return err; \
2503                          );
2504 }
2505
2506 /**
2507  * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
2508  * \param root Handle to the root configuration node containing alias
2509  *             definitions.
2510  * \param config Handle to the root of the configuration (sub)tree to search.
2511  * \param key Search key: one or more node keys, separated with dots.
2512  * \param result The function puts the handle to the node found at the address
2513  *               specified by \p result.
2514  * \return Zero if successful, otherwise a negative error code.
2515  */
2516 int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
2517 {
2518         static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
2519         SND_CONFIG_SEARCHA(root, config, key, result,
2520                                         snd_config_searcha_hooks,
2521                                         err = snd_config_hooks(config, NULL); \
2522                                         if (err < 0) \
2523                                                 return err; \
2524                          );
2525 }
2526
2527 /**
2528  * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
2529  * \param root Handle to the root configuration node containing alias
2530  *             definitions.
2531  * \param config Handle to the root of the configuration (sub)tree to search.
2532  * \param result The function puts the handle to the node found at the address
2533  *               specified by \p result.
2534  * \param ... One or more concatenated dot separated search keys, terminated with \c NULL.
2535  * \return Zero if successful, otherwise a negative error code.
2536  */
2537 int snd_config_searchva_hooks(snd_config_t *root, snd_config_t *config,
2538                               snd_config_t **result, ...)
2539 {
2540         SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha_hooks);
2541 }
2542
2543 /**
2544  * \brief Searches for a node in a configuration tree, using an alias and expanding hooks.
2545  * \param config Handle to the root of the configuration (sub)tree to search.
2546  * \param base Search key base, or \c NULL.
2547  * \param key Search key suffix.
2548  * \param result The function puts the handle to the node found at the address
2549  *               specified by \p result.
2550  * \return Zero if successful, otherwise a negative error code.
2551  *
2552  * First \c key is tried, then, if nothing is found, \c base.key is tried.
2553  * If the value found is a string, this is recursively tried in the
2554  * same way.
2555  */
2556 int snd_config_search_alias_hooks(snd_config_t *config,
2557                                   const char *base, const char *key,
2558                                   snd_config_t **result)
2559 {
2560         SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
2561                                 snd_config_searcha_hooks,
2562                                 snd_config_searchva_hooks);
2563 }
2564
2565 /** The name of the environment variable containing the files list for #snd_config_update. */
2566 #define ALSA_CONFIG_PATH_VAR "ALSA_CONFIG_PATH"
2567
2568 /** The name of the default files used by #snd_config_update. */
2569 #define ALSA_CONFIG_PATH_DEFAULT DATADIR "/alsa/alsa.conf"
2570
2571 /**
2572  * \ingroup Config
2573  * Configuration top level node (the global configuration).
2574  */
2575 snd_config_t *snd_config = NULL;
2576
2577 struct finfo {
2578         char *name;
2579         dev_t dev;
2580         ino_t ino;
2581         time_t mtime;
2582 };
2583
2584 struct _snd_config_update {
2585         unsigned int count;
2586         struct finfo *finfo;
2587 };
2588
2589 static snd_config_update_t *snd_config_global_update = NULL;
2590
2591 static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
2592 {
2593         void *h = NULL;
2594         snd_config_t *c, *func_conf = NULL;
2595         char *buf = NULL;
2596         const char *lib = NULL, *func_name = NULL;
2597         const char *str;
2598         int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL;
2599         int err;
2600
2601         err = snd_config_search(config, "func", &c);
2602         if (err < 0) {
2603                 SNDERR("Field func is missing");
2604                 return err;
2605         }
2606         err = snd_config_get_string(c, &str);
2607         if (err < 0) {
2608                 SNDERR("Invalid type for field func");
2609                 return err;
2610         }
2611         err = snd_config_search_definition(root, "hook_func", str, &func_conf);
2612         if (err >= 0) {
2613                 snd_config_iterator_t i, next;
2614                 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
2615                         SNDERR("Invalid type for func %s definition", str);
2616                         goto _err;
2617                 }
2618                 snd_config_for_each(i, next, func_conf) {
2619                         snd_config_t *n = snd_config_iterator_entry(i);
2620                         const char *id = n->id;
2621                         if (strcmp(id, "comment") == 0)
2622                                 continue;
2623                         if (strcmp(id, "lib") == 0) {
2624                                 err = snd_config_get_string(n, &lib);
2625                                 if (err < 0) {
2626                                         SNDERR("Invalid type for %s", id);
2627                                         goto _err;
2628                                 }
2629                                 continue;
2630                         }
2631                         if (strcmp(id, "func") == 0) {
2632                                 err = snd_config_get_string(n, &func_name);
2633                                 if (err < 0) {
2634                                         SNDERR("Invalid type for %s", id);
2635                                         goto _err;
2636                                 }
2637                                 continue;
2638                         }
2639                         SNDERR("Unknown field %s", id);
2640                 }
2641         }
2642         if (!func_name) {
2643                 int len = 16 + strlen(str) + 1;
2644                 buf = malloc(len);
2645                 snprintf(buf, len, "snd_config_hook_%s", str);
2646                 buf[len-1] = '\0';
2647                 func_name = buf;
2648         }
2649         h = snd_dlopen(lib, RTLD_NOW);
2650         func = h ? snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_HOOK)) : NULL;
2651         err = 0;
2652         if (!h) {
2653                 SNDERR("Cannot open shared library %s", lib);
2654                 err = -ENOENT;
2655         } else if (!func) {
2656                 SNDERR("symbol %s is not defined inside %s", func_name, lib);
2657                 snd_dlclose(h);
2658                 err = -ENXIO;
2659         }
2660         _err:
2661         if (func_conf)
2662                 snd_config_delete(func_conf);
2663         if (err >= 0) {
2664                 snd_config_t *nroot;
2665                 err = func(root, config, &nroot, private_data);
2666                 if (err < 0)
2667                         SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
2668                 snd_dlclose(h);
2669                 if (err >= 0 && nroot)
2670                         err = snd_config_substitute(root, nroot);
2671         }
2672         if (buf)
2673                 free(buf);
2674         if (err < 0)
2675                 return err;
2676         return 0;
2677 }
2678
2679 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
2680 {
2681         snd_config_t *n;
2682         snd_config_iterator_t i, next;
2683         int err, hit, idx = 0;
2684
2685         if ((err = snd_config_search(config, "@hooks", &n)) < 0)
2686                 return 0;
2687         snd_config_remove(n);
2688         do {
2689                 hit = 0;
2690                 snd_config_for_each(i, next, n) {
2691                         snd_config_t *n = snd_config_iterator_entry(i);
2692                         const char *id = n->id;
2693                         long i;
2694                         err = safe_strtol(id, &i);
2695                         if (err < 0) {
2696                                 SNDERR("id of field %s is not and integer", id);
2697                                 err = -EINVAL;
2698                                 goto _err;
2699                         }
2700                         if (i == idx) {
2701                                 err = snd_config_hooks_call(config, n, private_data);
2702                                 if (err < 0)
2703                                         return err;
2704                                 idx++;
2705                                 hit = 1;
2706                         }
2707                 }
2708         } while (hit);
2709         err = 0;
2710        _err:
2711         snd_config_delete(n);
2712         return err;
2713 }
2714
2715 /**
2716  * \brief Loads and parses the given configurations files.
2717  * \param root Handle to the root configuration node.
2718  * \param config Handle to the configuration node for this hook.
2719  * \param dst The function puts the handle to the configuration node loaded
2720  *            from the file(s) at the address specified by \p dst.
2721  * \param private_data Handle to the private data configuration node.
2722  * \return Zero if successful, otherwise a negative error code.
2723  */
2724 int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
2725 {
2726         snd_config_t *n;
2727         snd_config_iterator_t i, next;
2728         struct finfo *fi = NULL;
2729         int err, idx = 0, fi_count = 0, errors = 1, hit;
2730
2731         assert(root && dst);
2732         if ((err = snd_config_search(config, "errors", &n)) >= 0) {
2733                 char *tmp;
2734                 err = snd_config_get_ascii(n, &tmp);
2735                 if (err < 0)
2736                         return err;
2737                 errors = snd_config_get_bool_ascii(tmp);
2738                 free(tmp);
2739                 if (errors < 0) {
2740                         SNDERR("Invalid bool value in field errors");
2741                         return errors;
2742                 }
2743         }
2744         if ((err = snd_config_search(config, "files", &n)) < 0) {
2745                 SNDERR("Unable to find field files in the pre-load section");
2746                 return -EINVAL;
2747         }
2748         if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) {
2749                 SNDERR("Unable to expand filenames in the pre-load section");
2750                 return err;
2751         }
2752         if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
2753                 SNDERR("Invalid type for field filenames");
2754                 goto _err;
2755         }
2756         snd_config_for_each(i, next, n) {
2757                 snd_config_t *c = snd_config_iterator_entry(i);
2758                 const char *str;
2759                 if ((err = snd_config_get_string(c, &str)) < 0) {
2760                         SNDERR("Field %s is not a string", c->id);
2761                         goto _err;
2762                 }
2763                 fi_count++;
2764         }
2765         fi = calloc(fi_count, sizeof(*fi));
2766         if (fi == NULL) {
2767                 err = -ENOMEM;
2768                 goto _err;
2769         }
2770         do {
2771                 hit = 0;
2772                 snd_config_for_each(i, next, n) {
2773                         snd_config_t *n = snd_config_iterator_entry(i);
2774                         const char *id = n->id;
2775                         long i;
2776                         err = safe_strtol(id, &i);
2777                         if (err < 0) {
2778                                 SNDERR("id of field %s is not and integer", id);
2779                                 err = -EINVAL;
2780                                 goto _err;
2781                         }
2782                         if (i == idx) {
2783                                 char *name;
2784                                 if ((err = snd_config_get_ascii(n, &name)) < 0)
2785                                         goto _err;
2786                                 if ((err = snd_user_file(name, &fi[idx].name)) < 0)
2787                                         goto _err;
2788                                 free(name);
2789                                 idx++;
2790                                 hit = 1;
2791                         }
2792                 }
2793         } while (hit);
2794         for (idx = 0; idx < fi_count; idx++) {
2795                 snd_input_t *in;
2796                 if (!errors && access(fi[idx].name, R_OK) < 0)
2797                         continue;
2798                 err = snd_input_stdio_open(&in, fi[idx].name, "r");
2799                 if (err >= 0) {
2800                         err = snd_config_load(root, in);
2801                         snd_input_close(in);
2802                         if (err < 0) {
2803                                 SNDERR("%s may be old or corrupted: consider to remove or fix it", fi[idx].name);
2804                                 goto _err;
2805                         }
2806                 } else {
2807                         SNDERR("cannot access file %s", fi[idx].name);
2808                 }
2809         }
2810         *dst = NULL;
2811         err = 0;
2812        _err:
2813         for (idx = 0; idx < fi_count; idx++)
2814                 if (fi[idx].name)
2815                         free(fi[idx].name);
2816         if (fi)
2817                 free(fi);
2818         snd_config_delete(n);
2819         return err;
2820 }
2821 #ifndef DOC_HIDDEN
2822 SND_DLSYM_BUILD_VERSION(snd_config_hook_load, SND_CONFIG_DLSYM_VERSION_HOOK);
2823 #endif
2824
2825 #ifndef DOC_HIDDEN
2826 int snd_determine_driver(int card, char **driver);
2827 #endif
2828
2829 /**
2830  * \brief Loads and parses the given configurations files for each installed sound card.
2831  * \param root Handle to the root configuration node.
2832  * \param config Handle to the configuration node for this hook.
2833  * \param dst The function puts the handle to the configuration node loaded
2834  *            from the file(s) at the address specified by \p dst.
2835  * \param private_data Handle to the private data configuration node.
2836  * \return Zero if successful, otherwise a negative error code.
2837  */
2838 int 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)
2839 {
2840         int card = -1, err;
2841         
2842         do {
2843                 err = snd_card_next(&card);
2844                 if (err < 0)
2845                         return err;
2846                 if (card >= 0) {
2847                         snd_config_t *n, *private_data = NULL;
2848                         const char *driver;
2849                         char *fdriver = NULL;
2850                         err = snd_determine_driver(card, &fdriver);
2851                         if (err < 0)
2852                                 return err;
2853                         if (snd_config_search(root, fdriver, &n) >= 0) {
2854                                 if (snd_config_get_string(n, &driver) < 0)
2855                                         continue;
2856                                 while (1) {
2857                                         char *s = strchr(driver, '.');
2858                                         if (s == NULL)
2859                                                 break;
2860                                         driver = s + 1;
2861                                 }
2862                                 if (snd_config_search(root, driver, &n) >= 0)
2863                                         continue;
2864                         } else {
2865                                 driver = fdriver;
2866                         }
2867                         err = snd_config_imake_string(&private_data, "string", driver);
2868                         if (err < 0)
2869                                 goto __err;
2870                         err = snd_config_hook_load(root, config, &n, private_data);
2871                       __err:
2872                         if (private_data)
2873                                 snd_config_delete(private_data);
2874                         if (fdriver)
2875                                 free(fdriver);
2876                         if (err < 0)
2877                                 return err;
2878                 }
2879         } while (card >= 0);
2880         *dst = NULL;
2881         return 0;
2882 }
2883 #ifndef DOC_HIDDEN
2884 SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK);
2885 #endif
2886
2887 /** 
2888  * \brief Updates a configuration tree by rereading the configuration files (if needed).
2889  * \param top Address of the handle to the top level node.
2890  * \param update Address of a pointer to private update information.
2891  * \param cfgs A list of configuration file names, delimited with ':'.
2892  *             If \p cfgs is set to \c NULL, the default global configuration
2893  *             file is used ("/usr/share/alsa/alsa.conf").
2894  * \return A non-negative value if successful, otherwise a negative error code.
2895  * \retval 0 No action is needed.
2896  * \retval 1 The configuration tree has been rebuilt.
2897  *
2898  * The global configuration files are specified in the environment variable
2899  * \c ALSA_CONFIG_PATH.
2900  *
2901  * \warning If the configuration tree is reread, all string pointers and
2902  * configuration node handles previously obtained from this tree become invalid.
2903  */
2904 int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs)
2905 {
2906         int err;
2907         const char *configs, *c;
2908         unsigned int k;
2909         size_t l;
2910         snd_config_update_t *local;
2911         snd_config_update_t *update;
2912         snd_config_t *top;
2913         
2914         assert(_top && _update);
2915         top = *_top;
2916         update = *_update;
2917         configs = cfgs;
2918         if (!configs) {
2919                 configs = getenv(ALSA_CONFIG_PATH_VAR);
2920                 if (!configs)
2921                         configs = ALSA_CONFIG_PATH_DEFAULT;
2922         }
2923         for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
2924                 c += l;
2925                 k++;
2926                 if (!*c)
2927                         break;
2928                 c++;
2929         }
2930         if (k == 0) {
2931                 local = NULL;
2932                 goto _reread;
2933         }
2934         local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t));
2935         if (!local)
2936                 return -ENOMEM;
2937         local->count = k;
2938         local->finfo = calloc(local->count, sizeof(struct finfo));
2939         if (!local->finfo) {
2940                 free(local);
2941                 return -ENOMEM;
2942         }
2943         for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
2944                 char name[l + 1];
2945                 memcpy(name, c, l);
2946                 name[l] = 0;
2947                 err = snd_user_file(name, &local->finfo[k].name);
2948                 if (err < 0)
2949                         goto _end;
2950                 c += l;
2951                 k++;
2952                 if (!*c)
2953                         break;
2954                 c++;
2955         }
2956         for (k = 0; k < local->count; ++k) {
2957                 struct stat st;
2958                 struct finfo *lf = &local->finfo[k];
2959                 if (stat(lf->name, &st) >= 0) {
2960                         lf->dev = st.st_dev;
2961                         lf->ino = st.st_ino;
2962                         lf->mtime = st.st_mtime;
2963                 } else {
2964                         memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1));
2965                         k--;
2966                         local->count--;
2967                 }
2968         }
2969         if (!update)
2970                 goto _reread;
2971         if (local->count != update->count)
2972                 goto _reread;
2973         for (k = 0; k < local->count; ++k) {
2974                 struct finfo *lf = &local->finfo[k];
2975                 struct finfo *uf = &update->finfo[k];
2976                 if (strcmp(lf->name, uf->name) != 0 ||
2977                     lf->dev != uf->dev ||
2978                     lf->ino != uf->ino ||
2979                     lf->mtime != uf->mtime)
2980                         goto _reread;
2981         }
2982         err = 0;
2983
2984  _end:
2985         if (err < 0) {
2986                 if (top) {
2987                         snd_config_delete(top);
2988                         *_top = NULL;
2989                 }
2990                 if (update) {
2991                         snd_config_update_free(update);
2992                         *_update = NULL;
2993                 }
2994         }
2995         if (local)
2996                 snd_config_update_free(local);
2997         return err;
2998
2999  _reread:
3000         *_top = NULL;
3001         *_update = NULL;
3002         if (update) {
3003                 snd_config_update_free(update);
3004                 update = NULL;
3005         }
3006         if (top) {
3007                 snd_config_delete(top);
3008                 top = NULL;
3009         }
3010         err = snd_config_top(&top);
3011         if (err < 0)
3012                 goto _end;
3013         if (!local)
3014                 goto _skip;
3015         for (k = 0; k < local->count; ++k) {
3016                 snd_input_t *in;
3017                 err = snd_input_stdio_open(&in, local->finfo[k].name, "r");
3018                 if (err >= 0) {
3019                         err = snd_config_load(top, in);
3020                         snd_input_close(in);
3021                         if (err < 0) {
3022                                 SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name);
3023                                 goto _end;
3024                         }
3025                 } else {
3026                         SNDERR("cannot access file %s", local->finfo[k].name);
3027                 }
3028         }
3029  _skip:
3030         err = snd_config_hooks(top, NULL);
3031         if (err < 0) {
3032                 SNDERR("hooks failed, removing configuration");
3033                 goto _end;
3034         }
3035         *_top = top;
3036         *_update = local;
3037         return 1;
3038 }
3039
3040 static pthread_mutex_t snd_config_update_mutex = PTHREAD_MUTEX_INITIALIZER;
3041
3042 /** 
3043  * \brief Updates #snd_config by rereading the global configuration files (if needed).
3044  * \return A non-negative value if successful, otherwise a negative error code.
3045  * \retval 0 No action is needed.
3046  * \retval 1 The configuration tree has been rebuilt.
3047  *
3048  * The global configuration files are specified in the environment variable
3049  * \c ALSA_CONFIG_PATH. If this is not set, the default value is
3050  * "/usr/share/alsa/alsa.conf".
3051  *
3052  * \warning If the configuration tree is reread, all string pointers and
3053  * configuration node handles previously obtained from this tree become invalid.
3054  */
3055 int snd_config_update(void)
3056 {
3057         int err;
3058
3059         pthread_mutex_lock(&snd_config_update_mutex);
3060         err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
3061         pthread_mutex_unlock(&snd_config_update_mutex);
3062         return err;
3063 }
3064
3065 /** 
3066  * \brief Frees a private update structure.
3067  * \param update The private update structure to free.
3068  * \return Zero if successful, otherwise a negative error code.
3069  */
3070 int snd_config_update_free(snd_config_update_t *update)
3071 {
3072         unsigned int k;
3073
3074         assert(update);
3075         assert(update->count > 0 && update->finfo);
3076         for (k = 0; k < update->count; k++)
3077                 free(update->finfo[k].name);
3078         if (update->finfo)
3079                 free(update->finfo);
3080         free(update);
3081         return 0;
3082 }
3083
3084 /** 
3085  * \brief Frees the global configuration tree in #snd_config.
3086  * \return Zero if successful, otherwise a negative error code.
3087  */
3088 int snd_config_update_free_global(void)
3089 {
3090         pthread_mutex_lock(&snd_config_update_mutex);
3091         if (snd_config)
3092                 snd_config_delete(snd_config);
3093         snd_config = NULL;
3094         if (snd_config_global_update)
3095                 snd_config_update_free(snd_config_global_update);
3096         snd_config_global_update = NULL;
3097         pthread_mutex_unlock(&snd_config_update_mutex);
3098         return 0;
3099 }
3100
3101 /**
3102  * \brief Returns an iterator pointing to the first child of a compound configuration node.
3103  * \param node Handle to the compound configuration node.
3104  * \return An iterator pointing to the first child.
3105  */
3106 snd_config_iterator_t snd_config_iterator_first(const snd_config_t *node)
3107 {
3108         assert(node->type == SND_CONFIG_TYPE_COMPOUND);
3109         return node->u.compound.fields.next;
3110 }
3111
3112 /**
3113  * \brief Returns an iterator pointing to the next sibling.
3114  * \param iterator An iterator pointing to a child configuration node.
3115  * \return An iterator pointing to the next sibling of \p iterator.
3116  *         If \p iterator is the last sibling, the returned value is the same
3117  *         as the result of calling #snd_config_iterator_end on the father
3118  *         of the nodes.
3119  */
3120 snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator)
3121 {
3122         return iterator->next;
3123 }
3124
3125 /**
3126  * \brief Returns an iterator pointing past the last child of a compound configuration node.
3127  * \param node Handle to the compound configuration node.
3128  * \return An iterator pointing past the last child of \p node.
3129  */
3130 snd_config_iterator_t snd_config_iterator_end(const snd_config_t *node)
3131 {
3132         assert(node->type == SND_CONFIG_TYPE_COMPOUND);
3133         return (const snd_config_iterator_t)&node->u.compound.fields;
3134 }
3135
3136 /**
3137  * \brief Returns the configuration node handle pointed to by an iterator.
3138  * \param iterator A configuration node iterator.
3139  * \return The configuration node handle pointed to by \p iterator.
3140  */
3141 snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator)
3142 {
3143         return list_entry(iterator, snd_config_t, list);
3144 }
3145
3146 #ifndef DOC_HIDDEN
3147 typedef enum _snd_config_walk_pass {
3148         SND_CONFIG_WALK_PASS_PRE,
3149         SND_CONFIG_WALK_PASS_POST,
3150         SND_CONFIG_WALK_PASS_LEAF,
3151 } snd_config_walk_pass_t;
3152 #endif
3153
3154 /* Return 1 if node needs to be attached to father */
3155 /* Return 2 if compound is replaced with standard node */
3156 #ifndef DOC_HIDDEN
3157 typedef int (*snd_config_walk_callback_t)(snd_config_t *src,
3158                                           snd_config_t *root,
3159                                           snd_config_t **dst,
3160                                           snd_config_walk_pass_t pass,
3161                                           snd_config_t *private_data);
3162 #endif
3163
3164 static int snd_config_walk(snd_config_t *src,
3165                            snd_config_t *root,
3166                            snd_config_t **dst, 
3167                            snd_config_walk_callback_t callback,
3168                            snd_config_t *private_data)
3169 {
3170         int err;
3171         snd_config_iterator_t i, next;
3172
3173         switch (snd_config_get_type(src)) {
3174         case SND_CONFIG_TYPE_COMPOUND:
3175                 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, private_data);
3176                 if (err <= 0)
3177                         return err;
3178                 snd_config_for_each(i, next, src) {
3179                         snd_config_t *s = snd_config_iterator_entry(i);
3180                         snd_config_t *d = NULL;
3181
3182                         err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL,
3183                                               callback, private_data);
3184                         if (err < 0)
3185                                 goto _error;
3186                         if (err && d) {
3187                                 err = snd_config_add(*dst, d);
3188                                 if (err < 0)
3189                                         goto _error;
3190                         }
3191                 }
3192                 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, private_data);
3193                 if (err <= 0) {
3194                 _error:
3195                         if (dst && *dst)
3196                                 snd_config_delete(*dst);
3197                 }
3198                 break;
3199         default:
3200                 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, private_data);
3201                 break;
3202         }
3203         return err;
3204 }
3205
3206 static int _snd_config_copy(snd_config_t *src,
3207                             snd_config_t *root ATTRIBUTE_UNUSED,
3208                             snd_config_t **dst,
3209                             snd_config_walk_pass_t pass,
3210                             snd_config_t *private_data ATTRIBUTE_UNUSED)
3211 {
3212         int err;
3213         const char *id = src->id;
3214         snd_config_type_t type = snd_config_get_type(src);
3215         switch (pass) {
3216         case SND_CONFIG_WALK_PASS_PRE:
3217                 err = snd_config_make_compound(dst, id, src->u.compound.join);
3218                 if (err < 0)
3219                         return err;
3220                 break;
3221         case SND_CONFIG_WALK_PASS_LEAF:
3222                 err = snd_config_make(dst, id, type);
3223                 if (err < 0)
3224                         return err;
3225                 switch (type) {
3226                 case SND_CONFIG_TYPE_INTEGER:
3227                 {
3228                         long v;
3229                         err = snd_config_get_integer(src, &v);
3230                         assert(err >= 0);
3231                         snd_config_set_integer(*dst, v);
3232                         break;
3233                 }
3234                 case SND_CONFIG_TYPE_INTEGER64:
3235                 {
3236                         long long v;
3237                         err = snd_config_get_integer64(src, &v);
3238                         assert(err >= 0);
3239                         snd_config_set_integer64(*dst, v);
3240                         break;
3241                 }
3242                 case SND_CONFIG_TYPE_REAL:
3243                 {
3244                         double v;
3245                         err = snd_config_get_real(src, &v);
3246                         assert(err >= 0);
3247                         snd_config_set_real(*dst, v);
3248                         break;
3249                 }
3250                 case SND_CONFIG_TYPE_STRING:
3251                 {
3252                         const char *s;
3253                         err = snd_config_get_string(src, &s);
3254                         assert(err >= 0);
3255                         err = snd_config_set_string(*dst, s);
3256                         if (err < 0)
3257                                 return err;
3258                         break;
3259                 }
3260                 default:
3261                         assert(0);
3262                 }
3263                 break;
3264         default:
3265                 break;
3266         }
3267         return 1;
3268 }
3269
3270 /**
3271  * \brief Creates a copy of a configuration node.
3272  * \param dst The function puts the handle to the new configuration node
3273  *            at the address specified by \p dst.
3274  * \param src Handle to the source configuration node.
3275  * \return A non-negative value if successful, otherwise a negative error code.
3276  */
3277 int snd_config_copy(snd_config_t **dst,
3278                     snd_config_t *src)
3279 {
3280         return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL);
3281 }
3282
3283 static int _snd_config_expand(snd_config_t *src,
3284                               snd_config_t *root ATTRIBUTE_UNUSED,
3285                               snd_config_t **dst,
3286                               snd_config_walk_pass_t pass,
3287                               snd_config_t *private_data)
3288 {
3289         int err;
3290         const char *id = src->id;
3291         snd_config_type_t type = snd_config_get_type(src);
3292         switch (pass) {
3293         case SND_CONFIG_WALK_PASS_PRE:
3294         {
3295                 if (strcmp(id, "@args") == 0)
3296                         return 0;
3297                 err = snd_config_make_compound(dst, id, src->u.compound.join);
3298                 if (err < 0)
3299                         return err;
3300                 break;
3301         }
3302         case SND_CONFIG_WALK_PASS_LEAF:
3303                 switch (type) {
3304                 case SND_CONFIG_TYPE_INTEGER:
3305                 {
3306                         long v;
3307                         err = snd_config_get_integer(src, &v);
3308                         assert(err >= 0);
3309                         err = snd_config_imake_integer(dst, id, v);
3310                         if (err < 0)
3311                                 return err;
3312                         break;
3313                 }
3314                 case SND_CONFIG_TYPE_INTEGER64:
3315                 {
3316                         long long v;
3317                         err = snd_config_get_integer64(src, &v);
3318                         assert(err >= 0);
3319                         err = snd_config_imake_integer64(dst, id, v);
3320                         if (err < 0)
3321                                 return err;
3322                         break;
3323                 }
3324                 case SND_CONFIG_TYPE_REAL:
3325                 {
3326                         double v;
3327                         err = snd_config_get_real(src, &v);
3328                         assert(err >= 0);
3329                         err = snd_config_imake_real(dst, id, v);
3330                         if (err < 0)
3331                                 return err;
3332                         break;
3333                 }
3334                 case SND_CONFIG_TYPE_STRING:
3335                 {
3336                         const char *s;
3337                         snd_config_t *val;
3338                         snd_config_t *vars = private_data;
3339                         snd_config_get_string(src, &s);
3340                         if (*s == '$') {
3341                                 s++;
3342                                 if (snd_config_search(vars, s, &val) < 0)
3343                                         return 0;
3344                                 err = snd_config_copy(dst, val);
3345                                 if (err < 0)
3346                                         return err;
3347                                 err = snd_config_set_id(*dst, id);
3348                                 if (err < 0) {
3349                                         snd_config_delete(*dst);
3350                                         return err;
3351                                 }
3352                         } else {
3353                                 err = snd_config_imake_string(dst, id, s);
3354                                 if (err < 0)
3355                                         return err;
3356                         }
3357                         break;
3358                 }
3359                 default:
3360                         assert(0);
3361                 }
3362                 break;
3363         default:
3364                 break;
3365         }
3366         return 1;
3367 }
3368
3369 static int _snd_config_evaluate(snd_config_t *src,
3370                                 snd_config_t *root,
3371                                 snd_config_t **dst ATTRIBUTE_UNUSED,
3372                                 snd_config_walk_pass_t pass,
3373                                 snd_config_t *private_data)
3374 {
3375         int err;
3376         if (pass == SND_CONFIG_WALK_PASS_PRE) {
3377                 char *buf = NULL;
3378                 const char *lib = NULL, *func_name = NULL;
3379                 const char *str;
3380                 int (*func)(snd_config_t **dst, snd_config_t *root,
3381                             snd_config_t *src, snd_config_t *private_data) = NULL;
3382                 void *h = NULL;
3383                 snd_config_t *c, *func_conf = NULL;
3384                 err = snd_config_search(src, "@func", &c);
3385                 if (err < 0)
3386                         return 1;
3387                 err = snd_config_get_string(c, &str);
3388                 if (err < 0) {
3389                         SNDERR("Invalid type for @func");
3390                         return err;
3391                 }
3392                 err = snd_config_search_definition(root, "func", str, &func_conf);
3393                 if (err >= 0) {
3394                         snd_config_iterator_t i, next;
3395                         if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
3396                                 SNDERR("Invalid type for func %s definition", str);
3397                                 goto _err;
3398                         }
3399                         snd_config_for_each(i, next, func_conf) {
3400                                 snd_config_t *n = snd_config_iterator_entry(i);
3401                                 const char *id = n->id;
3402                                 if (strcmp(id, "comment") == 0)
3403                                         continue;
3404                                 if (strcmp(id, "lib") == 0) {
3405                                         err = snd_config_get_string(n, &lib);
3406                                         if (err < 0) {
3407                                                 SNDERR("Invalid type for %s", id);
3408                                                 goto _err;
3409                                         }
3410                                         continue;
3411                                 }
3412                                 if (strcmp(id, "func") == 0) {
3413                                         err = snd_config_get_string(n, &func_name);
3414                                         if (err < 0) {
3415                                                 SNDERR("Invalid type for %s", id);
3416                                                 goto _err;
3417                                         }
3418                                         continue;
3419                                 }
3420                                 SNDERR("Unknown field %s", id);
3421                         }
3422                 }
3423                 if (!func_name) {
3424                         int len = 9 + strlen(str) + 1;
3425                         buf = malloc(len);
3426                         snprintf(buf, len, "snd_func_%s", str);
3427                         buf[len-1] = '\0';
3428                         func_name = buf;
3429                 }
3430                 h = snd_dlopen(lib, RTLD_NOW);
3431                 if (h)
3432                         func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE));
3433                 err = 0;
3434                 if (!h) {
3435                         SNDERR("Cannot open shared library %s", lib);
3436                         err = -ENOENT;
3437                         goto _errbuf;
3438                 } else if (!func) {
3439                         SNDERR("symbol %s is not defined inside %s", func_name, lib);
3440                         snd_dlclose(h);
3441                         err = -ENXIO;
3442                         goto _errbuf;
3443                 }
3444                _err:
3445                 if (func_conf)
3446                         snd_config_delete(func_conf);
3447                 if (err >= 0) {
3448                         snd_config_t *eval;
3449                         err = func(&eval, root, src, private_data);
3450                         if (err < 0)
3451                                 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
3452                         snd_dlclose(h);
3453                         if (err >= 0 && eval) {
3454                                 /* substitute merges compound members */
3455                                 /* we don't want merging at all */
3456                                 err = snd_config_delete_compound_members(src);
3457                                 if (err >= 0)
3458                                         err = snd_config_substitute(src, eval);
3459                         }
3460                 }
3461                _errbuf:
3462                 if (buf)
3463                         free(buf);
3464                 if (err < 0)
3465                         return err;
3466                 return 0;
3467         }
3468         return 1;
3469 }
3470
3471 /**
3472  * \brief Evaluates a configuration node at runtime.
3473  * \param config Handle to the source configuration node.
3474  * \param root Handle to the root of the source configuration.
3475  * \param private_data Handle to the private data node for runtime evaluation.
3476  * \param result The function puts the handle to the result node at the
3477  *               address specified by \p result. \p result is \c NULL for
3478  *               in-place evaluation.
3479  * \return A non-negative value if successful, otherwise a negative error code.
3480  * \note Only in-place evaluation is currently implemented.
3481  */
3482 int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
3483                         snd_config_t *private_data, snd_config_t **result)
3484 {
3485         /* FIXME: Only in place evaluation is currently implemented */
3486         assert(result == NULL);
3487         return snd_config_walk(config, root, result, _snd_config_evaluate, private_data);
3488 }
3489
3490 static int load_defaults(snd_config_t *subs, snd_config_t *defs)
3491 {
3492         snd_config_iterator_t d, dnext;
3493         snd_config_for_each(d, dnext, defs) {
3494                 snd_config_t *def = snd_config_iterator_entry(d);
3495                 snd_config_iterator_t f, fnext;
3496                 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND)
3497                         continue;
3498                 snd_config_for_each(f, fnext, def) {
3499                         snd_config_t *fld = snd_config_iterator_entry(f);
3500                         const char *id = fld->id;
3501                         if (strcmp(id, "type") == 0)
3502                                 continue;
3503                         if (strcmp(id, "default") == 0) {
3504                                 snd_config_t *deflt;
3505                                 int err;
3506                                 err = snd_config_copy(&deflt, fld);
3507                                 if (err < 0)
3508                                         return err;
3509                                 err = snd_config_set_id(deflt, def->id);
3510                                 if (err < 0) {
3511                                         snd_config_delete(deflt);
3512                                         return err;
3513                                 }
3514                                 err = snd_config_add(subs, deflt);
3515                                 if (err < 0) {
3516                                         snd_config_delete(deflt);
3517                                         return err;
3518                                 }
3519                                 continue;
3520                         }
3521                         SNDERR("Unknown field %s", id);
3522                         return -EINVAL;
3523                 }
3524         }
3525         return 0;
3526 }
3527
3528 static void skip_blank(const char **ptr)
3529 {
3530         while (1) {
3531                 switch (**ptr) {
3532                 case ' ':
3533                 case '\f':
3534                 case '\t':
3535                 case '\n':
3536                 case '\r':
3537                         break;
3538                 default:
3539                         return;
3540                 }
3541                 (*ptr)++;
3542         }
3543 }
3544
3545 static int parse_char(const char **ptr)
3546 {
3547         int c;
3548         assert(**ptr == '\\');
3549         (*ptr)++;
3550         c = **ptr;
3551         switch (c) {
3552         case 'n':
3553                 c = '\n';
3554                 break;
3555         case 't':
3556                 c = '\t';
3557                 break;
3558         case 'v':
3559                 c = '\v';
3560                 break;
3561         case 'b':
3562                 c = '\b';
3563                 break;
3564         case 'r':
3565                 c = '\r';
3566                 break;
3567         case 'f':
3568                 c = '\f';
3569                 break;
3570         case '0' ... '7':
3571         {
3572                 int num = c - '0';
3573                 int i = 1;
3574                 (*ptr)++;
3575                 do {
3576                         c = **ptr;
3577                         if (c < '0' || c > '7')
3578                                 break;
3579                         num = num * 8 + c - '0';
3580                         i++;
3581                         (*ptr)++;
3582                 } while (i < 3);
3583                 return num;
3584         }
3585         default:
3586                 break;
3587         }
3588         (*ptr)++;
3589         return c;
3590 }
3591
3592 static int parse_id(const char **ptr)
3593 {
3594         if (!**ptr)
3595                 return -EINVAL;
3596         while (1) {
3597                 switch (**ptr) {
3598                 case '\f':
3599                 case '\t':
3600                 case '\n':
3601                 case '\r':
3602                 case ',':
3603                 case '=':
3604                 case '\0':
3605                         return 0;
3606                 default:
3607                         break;
3608                 }
3609                 (*ptr)++;
3610         }
3611 }
3612
3613 static int parse_string(const char **ptr, char **val)
3614 {
3615         const size_t bufsize = 256;
3616         char _buf[bufsize];
3617         char *buf = _buf;
3618         size_t alloc = bufsize;
3619         char delim = **ptr;
3620         size_t idx = 0;
3621         (*ptr)++;
3622         while (1) {
3623                 int c = **ptr;
3624                 switch (c) {
3625                 case '\0':
3626                         SNDERR("Unterminated string");
3627                         return -EINVAL;
3628                 case '\\':
3629                         c = parse_char(ptr);
3630                         if (c < 0)
3631                                 return c;
3632                         break;
3633                 default:
3634                         (*ptr)++;
3635                         if (c == delim) {
3636                                 *val = malloc(idx + 1);
3637                                 if (!*val)
3638                                         return -ENOMEM;
3639                                 memcpy(*val, buf, idx);
3640                                 (*val)[idx] = 0;
3641                                 if (alloc > bufsize)
3642                                         free(buf);
3643                                 return 0;
3644                         }
3645                 }
3646                 if (idx >= alloc) {
3647                         size_t old_alloc = alloc;
3648                         alloc *= 2;
3649                         if (old_alloc == bufsize) {
3650                                 buf = malloc(alloc);
3651                                 memcpy(buf, _buf, old_alloc);
3652                         } else {
3653                                 buf = realloc(buf, alloc);
3654                         }
3655                         if (!buf)
3656                                 return -ENOMEM;
3657                 }
3658                 buf[idx++] = c;
3659         }
3660 }
3661                                 
3662
3663 /* Parse var=val or val */
3664 static int parse_arg(const char **ptr, unsigned int *varlen, char **val)
3665 {
3666         const char *str;
3667         int err, vallen;
3668         skip_blank(ptr);
3669         str = *ptr;
3670         if (*str == '"' || *str == '\'') {
3671                 err = parse_string(ptr, val);
3672                 if (err < 0)
3673                         return err;
3674                 *varlen = 0;
3675                 return 0;
3676         }
3677         err = parse_id(ptr);
3678         if (err < 0)
3679                 return err;
3680         vallen = *ptr - str;
3681         skip_blank(ptr);
3682         if (**ptr != '=') {
3683                 *varlen = 0;
3684                 goto _value;
3685         }
3686         *varlen = vallen;
3687         (*ptr)++;
3688         skip_blank(ptr);
3689         str = *ptr;
3690         if (*str == '"' || *str == '\'') {
3691                 err = parse_string(ptr, val);
3692                 if (err < 0)
3693                         return err;
3694                 return 0;
3695         }
3696         err = parse_id(ptr);
3697         if (err < 0)
3698                 return err;
3699         vallen = *ptr - str;
3700  _value:
3701         *val = malloc(vallen + 1);
3702         if (!*val)
3703                 return -ENOMEM;
3704         memcpy(*val, str, vallen);
3705         (*val)[vallen] = 0;
3706         return 0;
3707 }
3708
3709
3710 /* val1, val2, ...
3711  * var1=val1,var2=val2,...
3712  * { conf syntax }
3713  */
3714 static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
3715 {
3716         int err;
3717         int arg = 0;
3718         if (str == NULL)
3719                 return 0;
3720         skip_blank(&str);
3721         if (!*str)
3722                 return 0;
3723         if (*str == '{') {
3724                 int len = strlen(str);
3725                 snd_input_t *input;
3726                 snd_config_iterator_t i, next;
3727                 while (1) {
3728                         switch (str[--len]) {
3729                         case ' ':
3730                         case '\f':
3731                         case '\t':
3732                         case '\n':
3733                         case '\r':
3734                                 continue;
3735                         default:
3736                                 break;
3737                         }
3738                         break;
3739                 }
3740                 if (str[len] != '}')
3741                         return -EINVAL;
3742                 err = snd_input_buffer_open(&input, str + 1, len - 1);
3743                 if (err < 0)
3744                         return err;
3745                 err = snd_config_load_override(subs, input);
3746                 snd_input_close(input);
3747                 if (err < 0)
3748                         return err;
3749                 snd_config_for_each(i, next, subs) {
3750                         snd_config_t *n = snd_config_iterator_entry(i);
3751                         snd_config_t *d;
3752                         const char *id = n->id;
3753                         err = snd_config_search(defs, id, &d);
3754                         if (err < 0) {
3755                                 SNDERR("Unknown parameter %s", id);
3756                                 return err;
3757                         }
3758                 }
3759                 return 0;
3760         }
3761         
3762         while (1) {
3763                 char buf[256];
3764                 const char *var = buf;
3765                 unsigned int varlen;
3766                 snd_config_t *def, *sub, *typ;
3767                 const char *new = str;
3768                 const char *tmp;
3769                 char *val;
3770                 err = parse_arg(&new, &varlen, &val);
3771                 if (err < 0)
3772                         goto _err;
3773                 if (varlen > 0) {
3774                         assert(varlen < sizeof(buf));
3775                         memcpy(buf, str, varlen);
3776                         buf[varlen] = 0;
3777                 } else {
3778                         sprintf(buf, "%d", arg);
3779                 }
3780                 err = snd_config_search_alias(defs, NULL, var, &def);
3781                 if (err < 0) {
3782                         SNDERR("Unknown parameter %s", var);
3783                         goto _err;
3784                 }
3785                 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) {
3786                         SNDERR("Parameter %s definition is not correct", var);
3787                         err = -EINVAL;
3788                         goto _err;
3789                 }
3790                 var = def->id;
3791                 err = snd_config_search(subs, var, &sub);
3792                 if (err >= 0)
3793                         snd_config_delete(sub);
3794                 err = snd_config_search(def, "type", &typ);
3795                 if (err < 0) {
3796                 _invalid_type:
3797                         SNDERR("Parameter %s definition is missing a valid type info", var);
3798                         goto _err;
3799                 }
3800                 err = snd_config_get_string(typ, &tmp);
3801                 if (err < 0)
3802                         goto _invalid_type;
3803                 if (strcmp(tmp, "integer") == 0) {
3804                         long v;
3805                         err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER);
3806                         if (err < 0)
3807                                 goto _err;
3808                         err = safe_strtol(val, &v);
3809                         if (err < 0) {
3810                                 SNDERR("Parameter %s must be an integer", var);
3811                                 goto _err;
3812                         }
3813                         err = snd_config_set_integer(sub, v);
3814                         if (err < 0)
3815                                 goto _err;
3816                 } else if (strcmp(tmp, "integer64") == 0) {
3817                         long long v;
3818                         err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER64);
3819                         if (err < 0)
3820                                 goto _err;
3821                         err = safe_strtoll(val, &v);
3822                         if (err < 0) {
3823                                 SNDERR("Parameter %s must be an integer", var);
3824                                 goto _err;
3825                         }
3826                         err = snd_config_set_integer64(sub, v);
3827                         if (err < 0)
3828                                 goto _err;
3829                 } else if (strcmp(tmp, "real") == 0) {
3830                         double v;
3831                         err = snd_config_make(&sub, var, SND_CONFIG_TYPE_REAL);
3832                         if (err < 0)
3833                                 goto _err;
3834                         err = safe_strtod(val, &v);
3835                         if (err < 0) {
3836                                 SNDERR("Parameter %s must be a real", var);
3837                                 goto _err;
3838                         }
3839                         err = snd_config_set_real(sub, v);
3840                         if (err < 0)
3841                                 goto _err;
3842                 } else if (strcmp(tmp, "string") == 0) {
3843                         err = snd_config_make(&sub, var, SND_CONFIG_TYPE_STRING);
3844                         if (err < 0)
3845                                 goto _err;
3846                         err = snd_config_set_string(sub, val);
3847                         if (err < 0)
3848                                 goto _err;
3849                 } else {
3850                         err = -EINVAL;
3851                         goto _invalid_type;
3852                 }
3853                 err = snd_config_set_id(sub, var);
3854                 if (err < 0)
3855                         goto _err;
3856                 err = snd_config_add(subs, sub);
3857                 if (err < 0) {
3858                 _err:
3859                         free(val);
3860                         return err;
3861                 }
3862                 free(val);
3863                 if (!*new)
3864                         break;
3865                 if (*new != ',')
3866                         return -EINVAL;
3867                 str = new + 1;
3868                 arg++;
3869         }
3870         return 0;
3871 }
3872
3873 /**
3874  * \brief Expands a configuration node applying arguments and functions.
3875  * \param config Handle to the configuration node.
3876  * \param root Handle to the root configuration node.
3877  * \param args Arguments string (optional).
3878  * \param private_data Handle to the private data node for functions.
3879  * \param result The function puts the handle to the result configuration node
3880  *               at the address specified by \p result.
3881  * \return A non-negative value if successful, otherwise a negative error code.
3882  */
3883 int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args,
3884                       snd_config_t *private_data, snd_config_t **result)
3885 {
3886         int err;
3887         snd_config_t *defs, *subs = NULL, *res;
3888         err = snd_config_search(config, "@args", &defs);
3889         if (err < 0) {
3890                 err = snd_config_copy(&res, config);
3891                 if (err < 0)
3892                         return err;
3893         } else {
3894                 err = snd_config_top(&subs);
3895                 if (err < 0)
3896                         return err;
3897                 err = load_defaults(subs, defs);
3898                 if (err < 0) {
3899                         SNDERR("Load defaults error: %s", snd_strerror(err));
3900                         goto _end;
3901                 }
3902                 err = parse_args(subs, args, defs);
3903                 if (err < 0) {
3904                         SNDERR("Parse arguments error: %s", snd_strerror(err));
3905                         goto _end;
3906                 }
3907                 err = snd_config_evaluate(subs, root, private_data, NULL);
3908                 if (err < 0) {
3909                         SNDERR("Args evaluate error: %s", snd_strerror(err));
3910                         goto _end;
3911                 }
3912                 err = snd_config_walk(config, root, &res, _snd_config_expand, subs);
3913                 if (err < 0) {
3914                         SNDERR("Expand error (walk): %s", snd_strerror(err));
3915                         goto _end;
3916                 }
3917         }
3918         err = snd_config_evaluate(res, root, private_data, NULL);
3919         if (err < 0) {
3920                 SNDERR("Evaluate error: %s", snd_strerror(err));
3921                 snd_config_delete(res);
3922                 goto _end;
3923         }
3924         *result = res;
3925         err = 1;
3926  _end:
3927         if (subs)
3928                 snd_config_delete(subs);
3929         return err;
3930 }
3931         
3932 /**
3933  * \brief Searches for a definition in a configuration tree, using aliases and expanding hooks and arguments.
3934  * \param config Handle to the configuration (sub)tree to search.
3935  * \param base Implicit key base, or \c NULL for none.
3936  * \param key Key suffix.
3937  * \param result The function puts the handle to the expanded found node at
3938  *               the address specified by \p result.
3939  * \return Zero if successful, otherwise a negative error code.
3940  *
3941  * First the key is tried, then, if nothing is found, base.key is tried.
3942  * If the value found is a string, this is recursively tried in the
3943  * same way.
3944  *
3945  * If \p key contains a dot (.), the implicit base is ignored and the key
3946  * starts from the root given by \p config.
3947  */
3948 int snd_config_search_definition(snd_config_t *config,
3949                                  const char *base, const char *name,
3950                                  snd_config_t **result)
3951 {
3952         snd_config_t *conf;
3953         char *key;
3954         const char *args = strchr(name, ':');
3955         int err;
3956         if (args) {
3957                 args++;
3958                 key = alloca(args - name);
3959                 memcpy(key, name, args - name - 1);
3960                 key[args - name - 1] = '\0';
3961         } else {
3962                 key = (char *) name;
3963         }
3964         /*
3965          *  if key contains dot (.), the implicit base is ignored
3966          *  and the key starts from root given by the 'config' parameter
3967          */
3968         err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf);
3969         if (err < 0)
3970                 return err;
3971         return snd_config_expand(conf, config, args, NULL, result);
3972 }
3973
3974
3975 #if 0
3976 /* Not strictly needed, but useful to check for memory leaks */
3977 void _snd_config_end(void) __attribute__ ((destructor));
3978
3979 static void _snd_config_end(void)
3980 {
3981         int k;
3982         if (snd_config)
3983                 snd_config_delete(snd_config);
3984         snd_config = 0;
3985         for (k = 0; k < files_info_count; ++k)
3986                 free(files_info[k].name);
3987         free(files_info);
3988         files_info = NULL;
3989         files_info_count = 0;
3990 }
3991 #endif