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