OSDN Git Service

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