3 * \ingroup Configuration
4 * \brief Configuration helper functions
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \author Jaroslav Kysela <perex@perex.cz>
9 * Tree based, full nesting configuration functions.
11 * See the \ref conf page for more details.
14 * Configuration helper functions
15 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>,
16 * Jaroslav Kysela <perex@perex.cz>
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.
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.
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
35 /*! \page conf Configuration files
37 <P>Configuration files use a simple format allowing modern
38 data description like nesting and array assignments.</P>
40 \section conf_whitespace Whitespace
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
58 are lexically equivalent and parse identically to give the four tokens:
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:
75 parses to two tokens, including the single literal-string token "John
78 \section conf_linesplicing Line continuation with \
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.
89 is parsed as "John Smith".
91 \section conf_comments Comments
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.
97 a 1 # this is a comment
100 \section conf_include Including configuration files
102 To include another configuration file, write the file name in angle brackets.
103 The prefix \c confdir: will reference the global configuration directory.
107 <confdir:pcm/surround.conf>
110 \section conf_punctuators Punctuators
112 The configuration punctuators (also known as separators) are:
115 {} [] , ; = . ' " new-line form-feed carriage-return whitespace
118 \subsection conf_braces Braces
120 Opening and closing braces { } indicate the start and end of a compound
129 \subsection conf_brackets Brackets
131 Opening and closing brackets indicate a single array definition. The
132 identifiers are automatically generated starting with zero.
141 The above code is equal to
148 \subsection conf_comma_semicolon Comma and semicolon
150 The comma (,) or semicolon (;) can separate value assignments. It is not
151 strictly required to use these separators because whitespace suffices to
159 \subsection conf_equal Equal sign
161 The equal sign (=) can separate variable declarations from
162 initialization lists:
169 Using equal signs is not required because whitespace suffices to separate
172 \section conf_assigns Assignments
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.
179 \subsection conf_single Single assignments
188 \subsection conf_compound Compound assignments (definitions using braces)
199 \section conf_compound1 Compound assignments (one key definitions)
206 \subsection conf_array Array assignments (definitions using brackets)
215 \subsection conf_array1 Array assignments (one key definitions)
222 \section conf_mode Operation modes for parsing nodes
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 (+).
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 (-).
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 (?).
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 (!).
242 defaults.pcm.!device 1
245 \section conf_syntax_summary Syntax summary
248 # Configuration file syntax
250 # Include a new configuration file
256 # Compound assignment (first style)
258 name1 [=] value [,|;]
262 # Compound assignment (second style)
263 name.name1 [=] value [,|;]
265 # Array assignment (first style)
272 # Array assignment (second style)
273 name.0 [=] value0 [,|;]
274 name.1 [=] value1 [,|;]
277 \section conf_syntax_ref References
285 /*! \page confarg Runtime arguments in configuration files
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
291 \section confarg_define Defining arguments
293 Arguments are defined using the id (key) \c \@args and array values containing
294 the string names of the arguments:
301 \section confarg_type Defining argument types and default values
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:
313 \section confarg_refer Referring to arguments
315 Arguments are referred to with a dollar-sign ($) and the name of the argument:
321 \section confarg_usage Usage
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:
332 plug:{SLAVE="hw:{CARD 0 DEV 1}"}
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.
339 \section confarg_example Example
343 @args [ CARD DEVICE ]
360 /*! \page conffunc Runtime functions in configuration files
362 <P>The ALSA library can modify the configuration at runtime.
363 Several built-in functions are available.</P>
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>
373 func.remove_first_char {
374 lib "/usr/lib/libasoundextend.so"
375 func "extend_remove_first_char"
381 /*! \page confhooks Hooks in configuration files
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>
387 <P>This example defines a hook which loads two configuration files at the
403 \section confhooks_ref Function reference
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.
421 #include <sys/stat.h>
424 #ifdef HAVE_LIBPTHREAD
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;
437 snd_config_type_t type;
438 int refcount; /* default = 0 */
446 struct list_head fields;
450 struct list_head list;
451 snd_config_t *parent;
458 unsigned int line, column;
459 struct filedesc *next;
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.
465 struct list_head include_paths;
468 /* path to search included files */
469 struct include_path {
471 struct list_head list;
474 #define LOCAL_ERROR (-0x68000000)
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)
482 struct filedesc *current;
487 #ifdef HAVE_LIBPTHREAD
489 static void snd_config_init_mutex(void)
491 pthread_mutexattr_t attr;
493 pthread_mutexattr_init(&attr);
494 #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE
495 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
497 pthread_mutex_init(&snd_config_update_mutex, &attr);
498 pthread_mutexattr_destroy(&attr);
501 static inline void snd_config_lock(void)
503 pthread_once(&snd_config_update_mutex_once, snd_config_init_mutex);
504 pthread_mutex_lock(&snd_config_update_mutex);
507 static inline void snd_config_unlock(void)
509 pthread_mutex_unlock(&snd_config_update_mutex);
514 static inline void snd_config_lock(void) { }
515 static inline void snd_config_unlock(void) { }
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.
526 * The direcotry should be a subdiretory of top configuration directory
527 * "/usr/share/alsa/".
529 static int add_include_path(struct filedesc *fd, const char *dir)
531 struct include_path *path;
532 struct filedesc *fd1;
533 struct list_head *pos;
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)
544 path = calloc(1, sizeof(*path));
548 path->dir = strdup(dir);
549 if (path->dir == NULL) {
554 list_add_tail(&path->list, &fd->include_paths);
559 * Free all include paths of a file descriptor.
560 * param fd - File object that owns these paths to search files included by it.
562 static void free_include_paths(struct filedesc *fd)
564 struct list_head *pos, *npos, *base;
565 struct include_path *path;
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);
578 * \brief Returns the default top-level config directory
579 * \return The top-level config directory path string
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".
586 const char *snd_config_topdir(void)
591 topdir = getenv("ALSA_CONFIG_DIR");
592 if (!topdir || *topdir != '/' || strlen(topdir) >= PATH_MAX)
593 topdir = ALSA_CONFIG_DIR;
598 static char *_snd_config_path(const char *name)
600 const char *root = snd_config_topdir();
601 char *path = malloc(strlen(root) + strlen(name) + 2);
604 sprintf(path, "%s/%s", root, name);
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.
616 * This function will search and open the file in the following order
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.
624 static int input_stdio_open(snd_input_t **inputp, const char *file,
625 struct filedesc *current)
627 struct list_head *pos;
628 struct include_path *path;
629 char full_path[PATH_MAX];
633 return snd_input_stdio_open(inputp, file, "r");
635 /* search file in user specified include paths. These directories
636 * are subdirectories of /usr/share/alsa.
640 list_for_each(pos, ¤t->include_paths) {
641 path = list_entry(pos, struct include_path, list);
645 snprintf(full_path, PATH_MAX, "%s/%s", path->dir, file);
646 err = snd_input_stdio_open(inputp, full_path, "r");
650 current = current->next;
656 static int safe_strtoll(const char *str, long long *val)
663 if (sscanf(str, "%lli%n", &v, &endidx) < 1)
671 int safe_strtol(const char *str, long *val)
678 v = strtol(str, &end, 0);
687 static int safe_strtod(const char *str, double *val)
691 #ifdef HAVE_USELOCALE
692 locale_t saved_locale, c_locale;
695 char locstr[64]; /* enough? */
701 #ifdef HAVE_USELOCALE
702 c_locale = newlocale(LC_NUMERIC_MASK, "C", 0);
703 saved_locale = uselocale(c_locale);
705 saved_locale = setlocale(LC_NUMERIC, NULL);
707 snprintf(locstr, sizeof(locstr), "%s", saved_locale);
708 setlocale(LC_NUMERIC, "C");
712 v = strtod(str, &end);
714 #ifdef HAVE_USELOCALE
715 if (c_locale != (locale_t)0) {
716 uselocale(saved_locale);
717 freelocale(c_locale);
721 setlocale(LC_NUMERIC, locstr);
731 static int get_char(input_t *input)
741 c = snd_input_getc(fd->in);
748 fd->column += 8 - fd->column % 8;
752 snd_input_close(fd->in);
754 input->current = fd->next;
758 return LOCAL_UNEXPECTED_EOF;
763 return (unsigned char)c;
766 static void unget_char(int c, input_t *input)
768 assert(!input->unget);
773 static int get_delimstring(char **string, int delim, input_t *input);
775 static int get_char_skip_comments(input_t *input)
785 int err = get_delimstring(&str, '>', input);
789 if (!strncmp(str, "searchdir:", 10)) {
790 /* directory to search included files */
791 char *tmp = _snd_config_path(str + 10);
799 SNDERR("Invalid search dir %s", str);
805 err = add_include_path(input->current, str);
808 SNDERR("Cannot add search dir %s", str);
814 if (!strncmp(str, "confdir:", 8)) {
815 /* file in the specified directory */
816 char *tmp = _snd_config_path(str + 8);
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);
827 SNDERR("Cannot access file %s", str);
831 fd = malloc(sizeof(*fd));
838 fd->next = input->current;
841 INIT_LIST_HEAD(&fd->include_paths);
860 static int get_nonwhite(input_t *input)
864 c = get_char_skip_comments(input);
878 static inline int get_hexachar(input_t *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;
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;
893 static int get_quotedchar(input_t *input)
911 return get_hexachar(input);
912 case '0': case '1': case '2': case '3':
913 case '4': case '5': case '6': case '7':
919 if (c < '0' || c > '7') {
920 unget_char(c, input);
923 num = num * 8 + c - '0';
933 #define LOCAL_STR_BUFSIZE 64
934 struct local_string {
938 char tmpbuf[LOCAL_STR_BUFSIZE];
941 static void init_local_string(struct local_string *s)
943 memset(s, 0, sizeof(*s));
945 s->alloc = LOCAL_STR_BUFSIZE;
948 static void free_local_string(struct local_string *s)
950 if (s->buf != s->tmpbuf)
954 static int add_char_local_string(struct local_string *s, int c)
956 if (s->idx >= s->alloc) {
957 size_t nalloc = s->alloc * 2;
958 if (s->buf == s->tmpbuf) {
959 s->buf = malloc(nalloc);
962 memcpy(s->buf, s->tmpbuf, s->alloc);
964 char *ptr = realloc(s->buf, nalloc);
971 s->buf[s->idx++] = c;
975 static char *copy_local_string(struct local_string *s)
977 char *dst = malloc(s->idx + 1);
979 memcpy(dst, s->buf, s->idx);
985 static int get_freestring(char **string, int id, input_t *input)
987 struct local_string str;
990 init_local_string(&str);
994 if (c == LOCAL_UNEXPECTED_EOF) {
995 *string = copy_local_string(&str);
1024 *string = copy_local_string(&str);
1028 unget_char(c, input);
1035 if (add_char_local_string(&str, c) < 0) {
1041 free_local_string(&str);
1045 static int get_delimstring(char **string, int delim, input_t *input)
1047 struct local_string str;
1050 init_local_string(&str);
1052 c = get_char(input);
1056 c = get_quotedchar(input);
1061 } else if (c == delim) {
1062 *string = copy_local_string(&str);
1069 if (add_char_local_string(&str, c) < 0) {
1074 free_local_string(&str);
1078 /* Return 0 for free string, 1 for delimited string */
1079 static int get_string(char **string, int id, input_t *input)
1081 int c = get_nonwhite(input), err;
1094 return LOCAL_UNEXPECTED_CHAR;
1097 err = get_delimstring(string, c, input);
1102 unget_char(c, input);
1103 err = get_freestring(string, id, input);
1110 static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
1114 n = calloc(1, sizeof(*n));
1127 if (type == SND_CONFIG_TYPE_COMPOUND)
1128 INIT_LIST_HEAD(&n->u.compound.fields);
1134 static int _snd_config_make_add(snd_config_t **config, char **id,
1135 snd_config_type_t type, snd_config_t *parent)
1139 assert(parent->type == SND_CONFIG_TYPE_COMPOUND);
1140 err = _snd_config_make(&n, id, type);
1144 list_add_tail(&n->list, &parent->u.compound.fields);
1149 static int _snd_config_search(snd_config_t *config,
1150 const char *id, int len, snd_config_t **result)
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);
1156 if (strcmp(n->id, id) != 0)
1158 } else if (strlen(n->id) != (size_t) len ||
1159 memcmp(n->id, id, (size_t) len) != 0)
1168 static int parse_value(snd_config_t **_n, snd_config_t *parent, input_t *input, char **id, int skip)
1170 snd_config_t *n = *_n;
1174 err = get_string(&s, 0, input);
1181 if (err == 0 && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) {
1184 err = safe_strtoll(s, &i);
1187 err = safe_strtod(s, &r);
1191 if (n->type != SND_CONFIG_TYPE_REAL) {
1192 SNDERR("%s is not a real", *id);
1196 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, parent);
1207 if (n->type != SND_CONFIG_TYPE_INTEGER && n->type != SND_CONFIG_TYPE_INTEGER64) {
1208 SNDERR("%s is not an integer", *id);
1213 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, parent);
1215 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER64, parent);
1219 if (n->type == SND_CONFIG_TYPE_INTEGER)
1220 n->u.integer = (long) i;
1228 if (n->type != SND_CONFIG_TYPE_STRING) {
1229 SNDERR("%s is not a string", *id);
1234 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, parent);
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);
1247 static int parse_array_def(snd_config_t *parent, input_t *input, int *idx, int skip, int override)
1252 snd_config_t *n = NULL;
1258 snprintf(static_id, sizeof(static_id), "%i", *idx);
1259 if (_snd_config_search(parent, static_id, -1, &g) == 0) {
1261 snd_config_delete(n);
1270 id = strdup(static_id);
1274 c = get_nonwhite(input);
1286 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1287 SNDERR("%s is not a compound", id);
1292 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1298 err = parse_defs(n, input, skip, override);
1301 err = parse_array_defs(n, input, skip, override);
1304 c = get_nonwhite(input);
1311 snd_config_delete(n);
1312 err = LOCAL_UNEXPECTED_CHAR;
1318 unget_char(c, input);
1319 err = parse_value(&n, parent, input, &id, skip);
1330 static int parse_array_defs(snd_config_t *parent, input_t *input, int skip, int override)
1334 int c = get_nonwhite(input), err;
1337 unget_char(c, input);
1340 err = parse_array_def(parent, input, &idx, skip, override);
1348 static int parse_def(snd_config_t *parent, input_t *input, int skip, int override)
1354 enum {MERGE_CREATE, MERGE, OVERRIDE, DONT_OVERRIDE} mode;
1356 c = get_nonwhite(input);
1361 mode = MERGE_CREATE;
1367 mode = DONT_OVERRIDE;
1373 mode = !override ? MERGE_CREATE : OVERRIDE;
1374 unget_char(c, input);
1376 err = get_string(&id, 1, input);
1379 c = get_nonwhite(input);
1386 if (_snd_config_search(parent, id, -1, &n) == 0) {
1387 if (mode == DONT_OVERRIDE) {
1392 if (mode != OVERRIDE) {
1393 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1394 SNDERR("%s is not a compound", id);
1397 n->u.compound.join = true;
1402 snd_config_delete(n);
1404 if (mode == MERGE) {
1405 SNDERR("%s does not exists", id);
1409 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1412 n->u.compound.join = true;
1416 c = get_nonwhite(input);
1421 if (_snd_config_search(parent, id, -1, &n) == 0) {
1422 if (mode == DONT_OVERRIDE) {
1425 } else if (mode == OVERRIDE) {
1426 snd_config_delete(n);
1431 if (mode == MERGE) {
1432 SNDERR("%s does not exists", id);
1445 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1446 SNDERR("%s is not a compound", id);
1451 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1457 err = parse_defs(n, input, skip, override);
1460 err = parse_array_defs(n, input, skip, override);
1463 c = get_nonwhite(input);
1466 snd_config_delete(n);
1467 err = LOCAL_UNEXPECTED_CHAR;
1473 unget_char(c, input);
1474 err = parse_value(&n, parent, input, &id, skip);
1479 c = get_nonwhite(input);
1485 unget_char(c, input);
1492 static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override)
1496 c = get_nonwhite(input);
1498 return c == LOCAL_UNEXPECTED_EOF ? 0 : c;
1499 unget_char(c, input);
1502 err = parse_def(parent, input, skip, override);
1509 static void string_print(char *str, int id, snd_output_t *out)
1512 unsigned char *p = (unsigned char *)str;
1514 snd_output_puts(out, "''");
1519 case '0': case '1': case '2': case '3': case '4':
1520 case '5': case '6': case '7': case '8': case '9':
1544 if (*p <= 31 || *p >= 127)
1550 snd_output_puts(out, str);
1553 q = strchr(str, '\'') ? '"' : '\'';
1554 snd_output_putc(out, q);
1555 p = (unsigned char *)str;
1561 snd_output_putc(out, '\\');
1562 snd_output_putc(out, 'n');
1565 snd_output_putc(out, '\\');
1566 snd_output_putc(out, 't');
1569 snd_output_putc(out, '\\');
1570 snd_output_putc(out, 'v');
1573 snd_output_putc(out, '\\');
1574 snd_output_putc(out, 'b');
1577 snd_output_putc(out, '\\');
1578 snd_output_putc(out, 'r');
1581 snd_output_putc(out, '\\');
1582 snd_output_putc(out, 'f');
1586 snd_output_putc(out, '\\');
1587 snd_output_putc(out, c);
1589 if (c >= 32 && c <= 126)
1590 snd_output_putc(out, c);
1592 snd_output_printf(out, "\\%04o", c);
1598 snd_output_putc(out, q);
1601 static void level_print(snd_output_t *out, unsigned int level)
1604 memset(a, '\t', level);
1606 snd_output_puts(out, a);
1609 static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1610 unsigned int level, unsigned int joins,
1613 int _snd_config_save_node_value(snd_config_t *n, snd_output_t *out,
1618 case SND_CONFIG_TYPE_INTEGER:
1619 snd_output_printf(out, "%ld", n->u.integer);
1621 case SND_CONFIG_TYPE_INTEGER64:
1622 snd_output_printf(out, "%lld", n->u.integer64);
1624 case SND_CONFIG_TYPE_REAL:
1625 snd_output_printf(out, "%-16g", n->u.real);
1627 case SND_CONFIG_TYPE_STRING:
1628 string_print(n->u.string, 0, out);
1630 case SND_CONFIG_TYPE_POINTER:
1631 SNDERR("cannot save runtime pointer type");
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);
1640 level_print(out, level);
1641 snd_output_putc(out, array ? ']' : '}');
1647 static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins)
1651 id_print(n->parent, out, joins - 1);
1652 snd_output_putc(out, '.');
1654 string_print(n->id, 1, out);
1657 static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1658 unsigned int level, unsigned int joins,
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);
1673 level_print(out, level);
1675 id_print(n, out, joins);
1676 snd_output_putc(out, ' ');
1678 snd_output_putc(out, '=');
1681 err = _snd_config_save_node_value(n, out, level);
1685 snd_output_putc(out, ';');
1687 snd_output_putc(out, '\n');
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.
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).
1704 * If the destination node is a compound and the source node is
1705 * an ordinary type, the compound members are deleted (including
1708 * Otherwise, the source node's value replaces the destination node's
1711 * In any case, a successful call to this function frees the source
1714 int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
1717 if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
1718 int err = snd_config_delete_compound_members(dst);
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);
1729 src->u.compound.fields.next->prev = &dst->u.compound.fields;
1730 src->u.compound.fields.prev->next = &dst->u.compound.fields;
1734 dst->type = src->type;
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.
1746 * This function recognizes at least the following node types:
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
1757 * <dt>-EINVAL<dd>Unknown note type in \a type.
1760 int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
1762 assert(ascii && type);
1763 if (!strcmp(ascii, "integer")) {
1764 *type = SND_CONFIG_TYPE_INTEGER;
1767 if (!strcmp(ascii, "integer64")) {
1768 *type = SND_CONFIG_TYPE_INTEGER64;
1771 if (!strcmp(ascii, "real")) {
1772 *type = SND_CONFIG_TYPE_REAL;
1775 if (!strcmp(ascii, "string")) {
1776 *type = SND_CONFIG_TYPE_STRING;
1779 if (!strcmp(ascii, "compound")) {
1780 *type = SND_CONFIG_TYPE_COMPOUND;
1787 * \brief Returns the type of a configuration node.
1788 * \param config Handle to the configuration node.
1789 * \return The node's type.
1791 * \par Conforming to:
1794 snd_config_type_t snd_config_get_type(const snd_config_t *config)
1796 return config->type;
1799 static int check_array_item(const char *id, int index)
1804 for (p = id; *p; p++) {
1805 if (*p < '0' || *p > '9')
1809 if (safe_strtol(id, &val))
1811 return val == index;
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.
1820 int snd_config_is_array(const snd_config_t *config)
1823 snd_config_iterator_t i, next;
1827 if (config->type != SND_CONFIG_TYPE_COMPOUND)
1830 snd_config_for_each(i, next, config) {
1831 node = snd_config_iterator_entry(i);
1832 if (!check_array_item(node->id, idx))
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.
1844 int snd_config_is_empty(const snd_config_t *config)
1847 if (config->type != SND_CONFIG_TYPE_COMPOUND)
1849 return list_empty(&config->u.compound.fields);
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.
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.
1863 * If the node does not have an id, \a *id is set to \c NULL.
1865 * \par Conforming to:
1868 int snd_config_get_id(const snd_config_t *config, const char **id)
1870 assert(config && id);
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.
1881 * This function stores a copy of \a id in the node.
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.
1890 int snd_config_set_id(snd_config_t *config, const char *id)
1892 snd_config_iterator_t i, next;
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)
1903 new_id = strdup(id);
1912 config->id = new_id;
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.
1921 * The returned node is an empty compound node without a parent and
1926 * <dt>-ENOMEM<dd>Out of memory.
1929 * \par Conforming to:
1932 int snd_config_top(snd_config_t **config)
1935 return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
1939 int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in,
1940 int override, const char * const *include_paths)
1944 struct filedesc *fd, *fd_next;
1946 assert(config && in);
1947 fd = malloc(sizeof(*fd));
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);
1963 err = add_include_path(fd, snd_config_topdir());
1969 err = parse_defs(config, &input, 0, override);
1974 case LOCAL_UNTERMINATED_STRING:
1975 str = "Unterminated string";
1978 case LOCAL_UNTERMINATED_QUOTE:
1979 str = "Unterminated quote";
1982 case LOCAL_UNEXPECTED_CHAR:
1983 str = "Unexpected char";
1986 case LOCAL_UNEXPECTED_EOF:
1987 str = "Unexpected end of file";
1991 str = strerror(-err);
1994 SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
1997 err = get_char(&input);
1999 if (err != LOCAL_UNEXPECTED_EOF) {
2000 SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
2008 snd_input_close(fd->in);
2010 free_include_paths(fd);
2015 free_include_paths(fd);
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.
2027 * The definitions loaded from the input are added to \a config, which
2028 * must be a compound node.
2031 * Any errors encountered when parsing the input or returned by hooks or
2034 * \par Conforming to:
2037 int snd_config_load(snd_config_t *config, snd_input_t *in)
2039 return _snd_config_load_with_include(config, in, 0, NULL);
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.
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' (+).
2052 int snd_config_load_override(snd_config_t *config, snd_input_t *in)
2054 return _snd_config_load_with_include(config, in, 1, NULL);
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.
2063 * This function makes the node \a child a child of the node \a parent.
2065 * The parent node then owns the child node, i.e., the child node gets
2066 * deleted together with its parent.
2068 * \a child must have an id.
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
2078 * \par Conforming to:
2081 int snd_config_add(snd_config_t *parent, snd_config_t *child)
2083 snd_config_iterator_t i, next;
2084 assert(parent && child);
2085 if (!child->id || child->parent)
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)
2092 child->parent = parent;
2093 list_add_tail(&child->list, &parent->u.compound.fields);
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.
2103 * This function makes the node \a child a child of the parent of
2104 * the node \a after.
2106 * The parent node then owns the child node, i.e., the child node gets
2107 * deleted together with its parent.
2109 * \a child must have an id.
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
2119 int snd_config_add_after(snd_config_t *after, snd_config_t *child)
2121 snd_config_iterator_t i, next;
2122 snd_config_t *parent;
2123 assert(after && child);
2124 parent = after->parent;
2126 if (!child->id || child->parent)
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)
2133 child->parent = parent;
2134 list_insert(&child->list, &after->list, after->list.next);
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.
2144 * This function makes the node \a child a child of the parent of
2145 * the node \a before.
2147 * The parent node then owns the child node, i.e., the child node gets
2148 * deleted together with its parent.
2150 * \a child must have an id.
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
2160 int snd_config_add_before(snd_config_t *before, snd_config_t *child)
2162 snd_config_iterator_t i, next;
2163 snd_config_t *parent;
2164 assert(before && child);
2165 parent = before->parent;
2167 if (!child->id || child->parent)
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)
2174 child->parent = parent;
2175 list_insert(&child->list, before->list.prev, &before->list);
2180 * append all src items to the end of dst arrray
2182 static int _snd_config_array_merge(snd_config_t *dst, snd_config_t *src, int index)
2184 snd_config_iterator_t si, snext;
2187 snd_config_for_each(si, snext, src) {
2188 snd_config_t *sn = snd_config_iterator_entry(si);
2190 snd_config_remove(sn);
2191 snprintf(id, sizeof(id), "%d", index++);
2192 err = snd_config_set_id(sn, id);
2194 snd_config_delete(sn);
2198 list_add_tail(&sn->list, &dst->u.compound.fields);
2200 snd_config_delete(src);
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.
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.
2214 * When \a override is not set, the child compounds are traversed and merged.
2216 * The configuration elements other than compounds are always substituted (overwritten)
2217 * from the \a src config handle.
2219 * The src handle is deleted.
2221 * Note: On error, config handles may be modified.
2225 * <dt>-EEXIST<dd>identifier already exists (!overwrite)
2226 * <dt>-ENOMEM<dd>not enough memory
2229 int snd_config_merge(snd_config_t *dst, snd_config_t *src, int override)
2231 snd_config_iterator_t di, si, dnext, snext;
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);
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) {
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);
2257 err = snd_config_merge(dn, sn, 0);
2266 /* move config from src to dst */
2267 snd_config_remove(sn);
2269 list_add_tail(&sn->list, &dst->u.compound.fields);
2272 snd_config_delete(src);
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.
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
2285 * This functions does \e not free the removed node.
2287 * \sa snd_config_delete
2289 int snd_config_remove(snd_config_t *config)
2293 list_del(&config->list);
2294 config->parent = NULL;
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.
2303 * This function frees a configuration node and all its resources.
2305 * If the node is a child node, it is removed from the tree before being
2308 * If the node is a compound node, its descendants (the whole subtree)
2309 * are deleted recursively.
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.
2315 * \par Conforming to:
2318 * \sa snd_config_remove
2320 int snd_config_delete(snd_config_t *config)
2323 if (config->refcount > 0) {
2327 switch (config->type) {
2328 case SND_CONFIG_TYPE_COMPOUND:
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);
2343 case SND_CONFIG_TYPE_STRING:
2344 free(config->u.string);
2350 list_del(&config->list);
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.
2361 * This function removes and frees all children of a configuration node.
2363 * Any compound nodes among the children of \a config are deleted
2366 * After a successful call to this function, \a config is an empty
2371 * <dt>-EINVAL<dd>\a config is not a compound node.
2374 int snd_config_delete_compound_members(const snd_config_t *config)
2377 struct list_head *i;
2380 if (config->type != SND_CONFIG_TYPE_COMPOUND)
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);
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.
2402 * This functions creates a new node of the specified type.
2403 * The new node has id \a id, which may be \c NULL.
2405 * The value of the new node is zero (for numbers), or \c NULL (for
2406 * strings and pointers), or empty (for compound nodes).
2410 * <dt>-ENOMEM<dd>Out of memory.
2413 int snd_config_make(snd_config_t **config, const char *id,
2414 snd_config_type_t type)
2424 return _snd_config_make(config, &id1, type);
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.
2434 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
2439 * <dt>-ENOMEM<dd>Out of memory.
2442 * \par Conforming to:
2445 * \sa snd_config_imake_integer
2447 int snd_config_make_integer(snd_config_t **config, const char *id)
2449 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
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.
2459 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
2460 * and with value \c 0.
2464 * <dt>-ENOMEM<dd>Out of memory.
2467 * \par Conforming to:
2470 * \sa snd_config_imake_integer64
2472 int snd_config_make_integer64(snd_config_t **config, const char *id)
2474 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
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.
2484 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
2485 * with value \c 0.0.
2489 * <dt>-ENOMEM<dd>Out of memory.
2492 * \sa snd_config_imake_real
2494 int snd_config_make_real(snd_config_t **config, const char *id)
2496 return snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
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.
2506 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2507 * with value \c NULL.
2511 * <dt>-ENOMEM<dd>Out of memory.
2514 * \par Conforming to:
2517 * \sa snd_config_imake_string
2519 int snd_config_make_string(snd_config_t **config, const char *id)
2521 return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
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.
2531 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2532 * with value \c NULL.
2536 * <dt>-ENOMEM<dd>Out of memory.
2539 * \sa snd_config_imake_pointer
2541 int snd_config_make_pointer(snd_config_t **config, const char *id)
2543 return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
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.
2554 * This function creates a new empty node of type
2555 * #SND_CONFIG_TYPE_COMPOUND.
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:
2566 * If, however, the join flag of \c a is nonzero, its id will be joined
2567 * with its children's ids, like this:
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.
2578 * <dt>-ENOMEM<dd>Out of memory.
2581 * \par Conforming to:
2584 int snd_config_make_compound(snd_config_t **config, const char *id,
2588 err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND);
2591 (*config)->u.compound.join = join;
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
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.
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.
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:
2620 * If, however, the join flag of \c a is nonzero, its id will be joined
2621 * with its children's ids, like this:
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.
2632 * <dt>-ENOMEM<dd>Out of memory.
2633 * <dt>-EACCESS<dd>Path exists, but it's not a compound (!override)
2636 int snd_config_make_path(snd_config_t **config, snd_config_t *root,
2637 const char *key, int join, int override)
2644 p = strchr(key, '.');
2646 err = _snd_config_search(root, key, p - key, &n);
2649 char *s = malloc(l + 1);
2654 err = snd_config_make_compound(&n, s, join);
2658 err = snd_config_add(root, n);
2665 err = _snd_config_search(root, key, -1, config);
2667 if ((*config)->type != SND_CONFIG_TYPE_COMPOUND) {
2669 err = snd_config_delete(*config);
2680 err = snd_config_make_compound(&n, key, join);
2683 err = snd_config_add(root, n);
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.
2700 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
2701 * with value \a value.
2705 * <dt>-ENOMEM<dd>Out of memory.
2708 * \par Conforming to:
2711 int snd_config_imake_integer(snd_config_t **config, const char *id, const long value)
2715 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
2718 (*config)->u.integer = value;
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.
2730 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
2731 * and with value \a value.
2735 * <dt>-ENOMEM<dd>Out of memory.
2738 * \par Conforming to:
2741 int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value)
2745 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
2748 (*config)->u.integer64 = value;
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.
2760 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
2761 * with value \a value.
2765 * <dt>-ENOMEM<dd>Out of memory.
2768 int snd_config_imake_real(snd_config_t **config, const char *id, const double value)
2772 err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
2775 (*config)->u.real = value;
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.
2787 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2788 * with a copy of the string \c value.
2792 * <dt>-ENOMEM<dd>Out of memory.
2795 * \par Conforming to:
2798 int snd_config_imake_string(snd_config_t **config, const char *id, const char *value)
2803 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
2807 tmp->u.string = strdup(value);
2808 if (!tmp->u.string) {
2809 snd_config_delete(tmp);
2813 tmp->u.string = NULL;
2819 int snd_config_imake_safe_string(snd_config_t **config, const char *id, const char *value)
2825 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
2829 tmp->u.string = strdup(value);
2830 if (!tmp->u.string) {
2831 snd_config_delete(tmp);
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'))
2844 tmp->u.string = NULL;
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.
2859 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2860 * with value \c value.
2864 * <dt>-ENOMEM<dd>Out of memory.
2867 int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value)
2871 err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2874 (*config)->u.ptr = value;
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.
2886 * <dt>-EINVAL<dd>\a config is not an integer node.
2889 * \par Conforming to:
2892 int snd_config_set_integer(snd_config_t *config, long value)
2895 if (config->type != SND_CONFIG_TYPE_INTEGER)
2897 config->u.integer = value;
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.
2909 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2912 * \par Conforming to:
2915 int snd_config_set_integer64(snd_config_t *config, long long value)
2918 if (config->type != SND_CONFIG_TYPE_INTEGER64)
2920 config->u.integer64 = value;
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.
2932 * <dt>-EINVAL<dd>\a config is not a real-number node.
2935 int snd_config_set_real(snd_config_t *config, double value)
2938 if (config->type != SND_CONFIG_TYPE_REAL)
2940 config->u.real = value;
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.
2950 * This function deletes the old string in the node and stores a copy of
2951 * \a value string in the node.
2955 * <dt>-EINVAL<dd>\a config is not a string node.
2958 * \par Conforming to:
2961 int snd_config_set_string(snd_config_t *config, const char *value)
2965 if (config->type != SND_CONFIG_TYPE_STRING)
2968 new_string = strdup(value);
2974 free(config->u.string);
2975 config->u.string = new_string;
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.
2985 * This function does not free the old pointer in the node.
2989 * <dt>-EINVAL<dd>\a config is not a pointer node.
2992 int snd_config_set_pointer(snd_config_t *config, const void *value)
2995 if (config->type != SND_CONFIG_TYPE_POINTER)
2997 config->u.ptr = value;
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.
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
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.
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.
3023 * \par Conforming to:
3026 int snd_config_set_ascii(snd_config_t *config, const char *ascii)
3028 assert(config && ascii);
3029 switch (config->type) {
3030 case SND_CONFIG_TYPE_INTEGER:
3033 int err = safe_strtol(ascii, &i);
3036 config->u.integer = i;
3039 case SND_CONFIG_TYPE_INTEGER64:
3042 int err = safe_strtoll(ascii, &i);
3045 config->u.integer64 = i;
3048 case SND_CONFIG_TYPE_REAL:
3051 int err = safe_strtod(ascii, &d);
3057 case SND_CONFIG_TYPE_STRING:
3059 char *ptr = strdup(ascii);
3062 free(config->u.string);
3063 config->u.string = ptr;
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.
3080 * <dt>-EINVAL<dd>\a config is not an integer node.
3083 * \par Conforming to:
3086 int snd_config_get_integer(const snd_config_t *config, long *ptr)
3088 assert(config && ptr);
3089 if (config->type != SND_CONFIG_TYPE_INTEGER)
3091 *ptr = config->u.integer;
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.
3103 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
3106 * \par Conforming to:
3109 int snd_config_get_integer64(const snd_config_t *config, long long *ptr)
3111 assert(config && ptr);
3112 if (config->type != SND_CONFIG_TYPE_INTEGER64)
3114 *ptr = config->u.integer64;
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.
3126 * <dt>-EINVAL<dd>\a config is not a real-number node.
3129 int snd_config_get_real(const snd_config_t *config, double *ptr)
3131 assert(config && ptr);
3132 if (config->type != SND_CONFIG_TYPE_REAL)
3134 *ptr = config->u.real;
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.
3144 * If the node's type is integer or integer64, the value is converted
3145 * to the \c double type on the fly.
3149 * <dt>-EINVAL<dd>\a config is not a number node.
3152 int snd_config_get_ireal(const snd_config_t *config, double *ptr)
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;
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.
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.
3177 * The string may be \c NULL.
3181 * <dt>-EINVAL<dd>\a config is not a string node.
3184 * \par Conforming to:
3187 int snd_config_get_string(const snd_config_t *config, const char **ptr)
3189 assert(config && ptr);
3190 if (config->type != SND_CONFIG_TYPE_STRING)
3192 *ptr = config->u.string;
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.
3205 * <dt>-EINVAL<dd>\a config is not a string node.
3208 int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
3210 assert(config && ptr);
3211 if (config->type != SND_CONFIG_TYPE_POINTER)
3213 *ptr = config->u.ptr;
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.
3224 * This function dynamically allocates the returned string. The
3225 * application is responsible for deleting it with \c free() when it is
3228 * For a string node with \c NULL value, the returned string is \c NULL.
3230 * Supported node types are #SND_CONFIG_TYPE_INTEGER,
3231 * #SND_CONFIG_TYPE_INTEGER64, #SND_CONFIG_TYPE_REAL, and
3232 * #SND_CONFIG_TYPE_STRING.
3236 * <dt>-EINVAL<dd>\a config is not a (64-bit) integer or real number or
3238 * <dt>-ENOMEM<dd>Out of memory.
3241 * \par Conforming to:
3244 int snd_config_get_ascii(const snd_config_t *config, char **ascii)
3246 assert(config && ascii);
3247 switch (config->type) {
3248 case SND_CONFIG_TYPE_INTEGER:
3252 err = snprintf(res, sizeof(res), "%li", config->u.integer);
3253 if (err < 0 || err == sizeof(res)) {
3257 *ascii = strdup(res);
3260 case SND_CONFIG_TYPE_INTEGER64:
3264 err = snprintf(res, sizeof(res), "%lli", config->u.integer64);
3265 if (err < 0 || err == sizeof(res)) {
3269 *ascii = strdup(res);
3272 case SND_CONFIG_TYPE_REAL:
3276 err = snprintf(res, sizeof(res), "%-16g", config->u.real);
3277 if (err < 0 || err == sizeof(res)) {
3281 if (res[0]) { /* trim the string */
3283 ptr = res + strlen(res) - 1;
3284 while (ptr != res && *ptr == ' ')
3290 *ascii = strdup(res);
3293 case SND_CONFIG_TYPE_STRING:
3294 if (config->u.string)
3295 *ascii = strdup(config->u.string);
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.
3318 int snd_config_test_id(const snd_config_t *config, const char *id)
3320 assert(config && id);
3322 return strcmp(config->id, id);
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.
3333 * This function writes a textual representation of \a config's value to
3334 * the output \a out.
3338 * <dt>-EINVAL<dd>A node in the tree has a type that cannot be printed,
3339 * i.e., #SND_CONFIG_TYPE_POINTER.
3342 * \par Conforming to:
3345 int snd_config_save(snd_config_t *config, snd_output_t *out)
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);
3352 return _snd_config_save_node_value(config, out, 0);
3357 * *** search macros ***
3362 #define SND_CONFIG_SEARCH(config, key, result, extra_code) \
3367 assert(config && key); \
3369 if (config->type != SND_CONFIG_TYPE_COMPOUND) \
3372 p = strchr(key, '.'); \
3374 err = _snd_config_search(config, key, p - key, &n); \
3380 return _snd_config_search(config, key, -1, result); \
3384 #define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \
3389 assert(config && key); \
3391 if (config->type != SND_CONFIG_TYPE_COMPOUND) { \
3392 if (snd_config_get_string(config, &p) < 0) \
3394 err = fcn(root, root, p, &config); \
3399 p = strchr(key, '.'); \
3401 err = _snd_config_search(config, key, p - key, &n); \
3407 return _snd_config_search(config, key, -1, result); \
3411 #define SND_CONFIG_SEARCHV(config, result, fcn) \
3416 va_start(arg, result); \
3418 const char *k = va_arg(arg, const char *); \
3422 err = fcn(config, k, &n); \
3435 #define SND_CONFIG_SEARCHVA(root, config, result, fcn) \
3440 va_start(arg, result); \
3442 const char *k = va_arg(arg, const char *); \
3446 err = fcn(root, config, k, &n); \
3459 #define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
3461 snd_config_t *res = NULL; \
3463 int err, first = 1, maxloop = 1000; \
3464 assert(config && key); \
3466 old_key = strdup(key); \
3467 if (old_key == NULL) { \
3472 err = first && base ? -EIO : fcn1(config, config, key, &res); \
3476 err = fcn2(config, config, &res, base, key, NULL); \
3480 if (snd_config_get_string(res, &key) < 0) \
3483 if (!first && (strcmp(key, old_key) == 0 || maxloop <= 0)) { \
3485 SNDERR("maximum loop count reached (circular configuration?)"); \
3487 SNDERR("key %s refers to itself", key); \
3504 #endif /* DOC_HIDDEN */
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
3513 * \return Zero if successful, otherwise a negative error code.
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
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:
3530 * e 2.71828 # "b.d.e"
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.
3543 * \par Conforming to:
3546 int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
3548 SND_CONFIG_SEARCH(config, key, result, );
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
3560 * \return Zero if successful, otherwise a negative error code.
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.
3567 * \a root must be a compound node.
3568 * \a root and \a config may be the same node.
3570 * For example, with the following configuration, the call
3572 * snd_config_searcha(root, config, "a.b.c.d", &result);
3574 * would return the node with id \c d:
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.
3601 int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
3603 SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, );
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
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.
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
3620 * snd_config_searchv(cfg, &res, "a", "b.c", "d.e", NULL);
3622 * is equivalent to the call
3624 * snd_config_search(cfg, "a.b.c.d.e", &res);
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.
3634 * \par Conforming to:
3637 int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...)
3639 SND_CONFIG_SEARCHV(config, result, snd_config_search);
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
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.
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.
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.
3666 int snd_config_searchva(snd_config_t *root, snd_config_t *config, snd_config_t **result, ...)
3668 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha);
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
3679 * \return Zero if successful, otherwise a negative error code.
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".
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.
3697 int snd_config_search_alias(snd_config_t *config,
3698 const char *base, const char *key,
3699 snd_config_t **result)
3701 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3702 snd_config_searcha, snd_config_searchva);
3705 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
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.
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.
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.
3726 * Additionally, any errors encountered when parsing the hook
3727 * definitions or returned by the hook functions.
3729 int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
3731 SND_CONFIG_SEARCH(config, key, result, \
3732 err = snd_config_hooks(config, NULL); \
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.
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.
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.
3759 * Additionally, any errors encountered when parsing the hook
3760 * definitions or returned by the hook functions.
3762 int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
3764 SND_CONFIG_SEARCHA(root, config, key, result,
3765 snd_config_searcha_hooks,
3766 err = snd_config_hooks(config, NULL); \
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.
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.
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.
3795 * Additionally, any errors encountered when parsing the hook
3796 * definitions or returned by the hook functions.
3798 int snd_config_searchva_hooks(snd_config_t *root, snd_config_t *config,
3799 snd_config_t **result, ...)
3801 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha_hooks);
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
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.
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.
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.
3824 * Additionally, any errors encountered when parsing the hook
3825 * definitions or returned by the hook functions.
3827 int snd_config_search_alias_hooks(snd_config_t *config,
3828 const char *base, const char *key,
3829 snd_config_t **result)
3831 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3832 snd_config_searcha_hooks,
3833 snd_config_searchva_hooks);
3836 /** The name of the environment variable containing the files list for #snd_config_update. */
3837 #define ALSA_CONFIG_PATH_VAR "ALSA_CONFIG_PATH"
3841 * \brief Configuration top-level node (the global configuration).
3843 * This variable contains a handle to the top-level configuration node,
3844 * as loaded from global configuration file.
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.
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".
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.
3859 * \par Conforming to:
3862 snd_config_t *snd_config = NULL;
3872 struct _snd_config_update {
3874 struct finfo *finfo;
3876 #endif /* DOC_HIDDEN */
3878 static snd_config_update_t *snd_config_global_update = NULL;
3880 static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
3883 snd_config_t *c, *func_conf = NULL;
3884 char *buf = NULL, errbuf[256];
3885 const char *lib = NULL, *func_name = NULL;
3887 int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL;
3890 err = snd_config_search(config, "func", &c);
3892 SNDERR("Field func is missing");
3895 err = snd_config_get_string(c, &str);
3897 SNDERR("Invalid type for field func");
3901 err = snd_config_search_definition(root, "hook_func", str, &func_conf);
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);
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)
3914 if (strcmp(id, "lib") == 0) {
3915 err = snd_config_get_string(n, &lib);
3917 SNDERR("Invalid type for %s", id);
3922 if (strcmp(id, "func") == 0) {
3923 err = snd_config_get_string(n, &func_name);
3925 SNDERR("Invalid type for %s", id);
3930 SNDERR("Unknown field %s", id);
3934 int len = 16 + strlen(str) + 1;
3940 snprintf(buf, len, "snd_config_hook_%s", str);
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;
3948 SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
3951 SNDERR("symbol %s is not defined inside %s", func_name, lib);
3957 snd_config_delete(func_conf);
3959 snd_config_t *nroot;
3960 err = func(root, config, &nroot, private_data);
3962 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
3964 if (err >= 0 && nroot)
3965 err = snd_config_substitute(root, nroot);
3973 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
3976 snd_config_iterator_t i, next;
3977 int err, hit, idx = 0;
3979 if ((err = snd_config_search(config, "@hooks", &n)) < 0)
3982 snd_config_remove(n);
3985 snd_config_for_each(i, next, n) {
3986 snd_config_t *n = snd_config_iterator_entry(i);
3987 const char *id = n->id;
3989 err = safe_strtol(id, &i);
3991 SNDERR("id of field %s is not and integer", id);
3996 err = snd_config_hooks_call(config, n, private_data);
4006 snd_config_delete(n);
4007 snd_config_unlock();
4011 static int config_filename_filter(const struct dirent *dirent)
4017 if (dirent->d_type == DT_DIR)
4020 flen = strlen(dirent->d_name);
4024 if (strncmp(&dirent->d_name[flen-5], ".conf", 5) == 0)
4030 static int config_file_open(snd_config_t *root, const char *filename)
4035 err = snd_input_stdio_open(&in, filename, "r");
4037 err = snd_config_load(root, in);
4038 snd_input_close(in);
4040 SNDERR("%s may be old or corrupted: consider to remove or fix it", filename);
4042 SNDERR("cannot access file %s", filename);
4047 static int config_file_load(snd_config_t *root, const char *fn, int errors)
4050 struct dirent **namelist;
4053 if (!errors && access(fn, R_OK) < 0)
4055 if (stat(fn, &st) < 0) {
4056 SNDERR("cannot stat file/directory %s", fn);
4059 if (!S_ISDIR(st.st_mode))
4060 return config_file_open(root, fn);
4062 #if defined(_GNU_SOURCE) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__sun) && !defined(ANDROID)
4063 #define SORTFUNC versionsort
4065 #define SORTFUNC alphasort
4068 n = scandir(fn, &namelist, config_filename_filter, SORTFUNC);
4072 for (j = 0; j < n; ++j) {
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';
4079 err = config_file_open(root, filename);
4091 static int config_file_load_user(snd_config_t *root, const char *fn, int errors)
4096 err = snd_user_file(fn, &fn2);
4098 return config_file_load(root, fn, errors);
4099 err = config_file_load(root, fn2, errors);
4104 static int config_file_load_user_all(snd_config_t *_root, snd_config_t *_file, int errors)
4106 snd_config_t *file = _file, *root = _root, *n;
4107 char *name, *name2, *remain, *rname = NULL;
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");
4115 if ((err = snd_config_search(_file, "root", &root)) >= 0) {
4116 err = snd_config_get_ascii(root, &rname);
4118 SNDERR("Field root is bad");
4121 err = snd_config_make_compound(&root, rname, 0);
4126 if ((err = snd_config_get_ascii(file, &name)) < 0)
4129 remain = strstr(name, "|||");
4135 err = config_file_load_user(root, name2, errors);
4138 if (err == 0) /* first hit wins */
4143 remain = strstr(remain, "|||");
4146 if (root != _root) {
4148 if (snd_config_get_type(root) == SND_CONFIG_TYPE_COMPOUND) {
4149 if (snd_config_is_empty(root))
4152 err = snd_config_make_path(&n, _root, rname, 0, 1);
4155 err = snd_config_substitute(n, root);
4160 snd_config_delete(root);
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
4175 * \param[in] private_data Handle to the private data configuration node.
4176 * \return Zero if successful, otherwise a negative error code.
4178 * See \ref confhooks for an example.
4180 int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
4183 snd_config_iterator_t i, next;
4184 int err, idx = 0, errors = 1, hit;
4186 assert(root && dst);
4187 if ((err = snd_config_search(config, "errors", &n)) >= 0) {
4188 errors = snd_config_get_bool(n);
4190 SNDERR("Invalid bool value in field errors");
4194 if ((err = snd_config_search(config, "files", &n)) < 0) {
4195 SNDERR("Unable to find field files in the pre-load section");
4198 if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) {
4199 SNDERR("Unable to expand filenames in the pre-load section");
4202 if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
4203 SNDERR("Invalid type for field filenames");
4208 snd_config_for_each(i, next, n) {
4209 snd_config_t *n = snd_config_iterator_entry(i);
4210 const char *id = n->id;
4212 err = safe_strtol(id, &i);
4214 SNDERR("id of field %s is not and integer", id);
4219 err = config_file_load_user_all(root, n, errors);
4230 snd_config_delete(n);
4234 SND_DLSYM_BUILD_VERSION(snd_config_hook_load, SND_CONFIG_DLSYM_VERSION_HOOK);
4238 int snd_determine_driver(int card, char **driver);
4241 snd_config_t *_snd_config_hook_private_data(int card, const char *driver)
4243 snd_config_t *private_data, *v;
4246 err = snd_config_make_compound(&private_data, NULL, 0);
4249 err = snd_config_imake_integer(&v, "integer", card);
4252 err = snd_config_add(private_data, v);
4254 snd_config_delete(v);
4257 err = snd_config_imake_string(&v, "string", driver);
4260 err = snd_config_add(private_data, v);
4262 snd_config_delete(v);
4265 return private_data;
4268 snd_config_delete(private_data);
4272 static int _snd_config_hook_table(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
4274 snd_config_t *n, *tn;
4278 if (snd_config_search(config, "table", &n) < 0)
4280 if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) {
4281 SNDERR("Unable to expand table compound");
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);
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);
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);
4302 snd_config_delete(n);
4303 if ((err = snd_config_add(root, tn)) < 0) {
4304 snd_config_delete(tn);
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
4318 * \param[in] private_data Handle to the private data configuration node.
4319 * \return Zero if successful, otherwise a negative error code.
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.
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)
4328 snd_config_t *loaded; // trace loaded cards
4330 err = snd_config_top(&loaded);
4334 err = snd_card_next(&card);
4338 snd_config_t *n, *m, *private_data = NULL;
4340 char *fdriver = NULL;
4342 err = snd_determine_driver(card, &fdriver);
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);
4354 char *s = strchr(driver, '.');
4359 if (snd_config_search(root, driver, &n) >= 0)
4366 err = snd_config_imake_integer(&m, driver, 1);
4369 err = snd_config_add(loaded, m);
4371 if (err == -EEXIST) {
4372 snd_config_delete(m);
4378 private_data = _snd_config_hook_private_data(card, driver);
4379 if (!private_data) {
4383 err = _snd_config_hook_table(root, config, private_data);
4387 err = snd_config_hook_load(root, config, &n, private_data);
4390 snd_config_delete(private_data);
4395 } while (card >= 0);
4396 snd_config_delete(loaded);
4400 snd_config_delete(loaded);
4404 SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK);
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.
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.
4423 * The global configuration files are specified in the environment variable
4424 * \c ALSA_CONFIG_PATH.
4426 * \warning If the configuration tree is reread, all string pointers and
4427 * configuration node handles previously obtained from this tree become
4431 * Any errors encountered when parsing the input or returned by hooks or
4434 int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs)
4437 const char *configs, *c;
4440 snd_config_update_t *local;
4441 snd_config_update_t *update;
4444 assert(_top && _update);
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);
4458 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
4469 local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t));
4473 local->finfo = calloc(local->count, sizeof(struct finfo));
4474 if (!local->finfo) {
4478 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
4482 err = snd_user_file(name, &local->finfo[k].name);
4491 for (k = 0; k < local->count; ++k) {
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;
4499 SNDERR("Cannot access file %s", lf->name);
4501 memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1));
4508 if (local->count != update->count)
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)
4524 snd_config_delete(top);
4528 snd_config_update_free(update);
4533 snd_config_update_free(local);
4540 snd_config_update_free(update);
4544 snd_config_delete(top);
4547 err = snd_config_top(&top);
4552 for (k = 0; k < local->count; ++k) {
4554 err = snd_input_stdio_open(&in, local->finfo[k].name, "r");
4556 err = snd_config_load(top, in);
4557 snd_input_close(in);
4559 SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name);
4563 SNDERR("cannot access file %s", local->finfo[k].name);
4567 err = snd_config_hooks(top, NULL);
4569 SNDERR("hooks failed, removing configuration");
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.
4582 * \warning Whenever #snd_config is updated, all string pointers and
4583 * configuration node handles previously obtained from it may become
4585 * For safer operations, use #snd_config_update_ref and release the config
4586 * via #snd_config_unref.
4589 * Any errors encountered when parsing the input or returned by hooks or
4592 * \par Conforming to:
4595 int snd_config_update(void)
4600 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
4601 snd_config_unlock();
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.
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.
4614 * This function is supposed to be thread-safe.
4616 int snd_config_update_ref(snd_config_t **top)
4623 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
4627 snd_config->refcount++;
4634 snd_config_unlock();
4639 * \brief Take the reference of the config tree.
4641 * Increases a reference counter of the given config tree.
4643 * This function is supposed to be thread-safe.
4645 void snd_config_ref(snd_config_t *cfg)
4650 snd_config_unlock();
4654 * \brief Unreference the config tree.
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.
4660 * Also, the config taken via #snd_config_update_ref must be unreferenced
4661 * by this function, too.
4663 * This function is supposed to be thread-safe.
4665 void snd_config_unref(snd_config_t *cfg)
4669 snd_config_delete(cfg);
4670 snd_config_unlock();
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.
4678 int snd_config_update_free(snd_config_update_t *update)
4683 for (k = 0; k < update->count; k++)
4684 free(update->finfo[k].name);
4685 free(update->finfo);
4691 * \brief Frees the global configuration tree in #snd_config.
4692 * \return Zero if successful, otherwise a negative error code.
4694 * This functions releases all resources of the global configuration
4695 * tree, and sets #snd_config to \c NULL.
4697 * \par Conforming to:
4700 int snd_config_update_free_global(void)
4704 snd_config_delete(snd_config);
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();
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.
4721 * \a config must be a compound node.
4723 * The returned iterator is valid if it is not equal to the return value
4724 * of #snd_config_iterator_end on \a config.
4726 * Use #snd_config_iterator_entry to get the handle of the node pointed
4729 * \par Conforming to:
4732 snd_config_iterator_t snd_config_iterator_first(const snd_config_t *config)
4734 assert(config->type == SND_CONFIG_TYPE_COMPOUND);
4735 return config->u.compound.fields.next;
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.
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.
4746 * Use #snd_config_iterator_entry to get the handle of the node pointed
4749 * \par Conforming to:
4752 snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator)
4754 return iterator->next;
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.
4762 * \a config must be a compound node.
4764 * The return value can be understood as pointing past the last child of
4767 * \par Conforming to:
4770 snd_config_iterator_t snd_config_iterator_end(const snd_config_t *config)
4772 assert(config->type == SND_CONFIG_TYPE_COMPOUND);
4773 return (const snd_config_iterator_t)&config->u.compound.fields;
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.
4781 * \par Conforming to:
4784 snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator)
4786 return list_entry(iterator, snd_config_t, list);
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;
4797 /* Return 1 if node needs to be attached to parent */
4798 /* Return 2 if compound is replaced with standard node */
4800 typedef int (*snd_config_walk_callback_t)(snd_config_t *src,
4803 snd_config_walk_pass_t pass,
4804 snd_config_t *private_data);
4807 static int snd_config_walk(snd_config_t *src,
4810 snd_config_walk_callback_t callback,
4811 snd_config_t *private_data)
4814 snd_config_iterator_t i, next;
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);
4821 snd_config_for_each(i, next, src) {
4822 snd_config_t *s = snd_config_iterator_entry(i);
4823 snd_config_t *d = NULL;
4825 err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL,
4826 callback, private_data);
4830 err = snd_config_add(*dst, d);
4835 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, private_data);
4839 snd_config_delete(*dst);
4843 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, private_data);
4849 static int _snd_config_copy(snd_config_t *src,
4850 snd_config_t *root ATTRIBUTE_UNUSED,
4852 snd_config_walk_pass_t pass,
4853 snd_config_t *private_data ATTRIBUTE_UNUSED)
4856 const char *id = src->id;
4857 snd_config_type_t type = snd_config_get_type(src);
4859 case SND_CONFIG_WALK_PASS_PRE:
4860 err = snd_config_make_compound(dst, id, src->u.compound.join);
4864 case SND_CONFIG_WALK_PASS_LEAF:
4865 err = snd_config_make(dst, id, type);
4869 case SND_CONFIG_TYPE_INTEGER:
4872 err = snd_config_get_integer(src, &v);
4874 snd_config_set_integer(*dst, v);
4877 case SND_CONFIG_TYPE_INTEGER64:
4880 err = snd_config_get_integer64(src, &v);
4882 snd_config_set_integer64(*dst, v);
4885 case SND_CONFIG_TYPE_REAL:
4888 err = snd_config_get_real(src, &v);
4890 snd_config_set_real(*dst, v);
4893 case SND_CONFIG_TYPE_STRING:
4896 err = snd_config_get_string(src, &s);
4898 err = snd_config_set_string(*dst, s);
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.
4920 * This function creates a deep copy, i.e., if \a src is a compound
4921 * node, all children are copied recursively.
4925 * <dt>-ENOMEM<dd>Out of memory.
4928 * \par Conforming to:
4931 int snd_config_copy(snd_config_t **dst,
4934 return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL);
4937 static int _snd_config_expand(snd_config_t *src,
4938 snd_config_t *root ATTRIBUTE_UNUSED,
4940 snd_config_walk_pass_t pass,
4941 snd_config_t *private_data)
4944 const char *id = src->id;
4945 snd_config_type_t type = snd_config_get_type(src);
4947 case SND_CONFIG_WALK_PASS_PRE:
4949 if (id && strcmp(id, "@args") == 0)
4951 err = snd_config_make_compound(dst, id, src->u.compound.join);
4956 case SND_CONFIG_WALK_PASS_LEAF:
4958 case SND_CONFIG_TYPE_INTEGER:
4961 err = snd_config_get_integer(src, &v);
4963 err = snd_config_imake_integer(dst, id, v);
4968 case SND_CONFIG_TYPE_INTEGER64:
4971 err = snd_config_get_integer64(src, &v);
4973 err = snd_config_imake_integer64(dst, id, v);
4978 case SND_CONFIG_TYPE_REAL:
4981 err = snd_config_get_real(src, &v);
4983 err = snd_config_imake_real(dst, id, v);
4988 case SND_CONFIG_TYPE_STRING:
4992 snd_config_t *vars = private_data;
4993 snd_config_get_string(src, &s);
4994 if (s && *s == '$') {
4996 if (snd_config_search(vars, s, &val) < 0)
4998 err = snd_config_copy(dst, val);
5001 err = snd_config_set_id(*dst, id);
5003 snd_config_delete(*dst);
5007 err = snd_config_imake_string(dst, id, s);
5023 static int _snd_config_evaluate(snd_config_t *src,
5025 snd_config_t **dst ATTRIBUTE_UNUSED,
5026 snd_config_walk_pass_t pass,
5027 snd_config_t *private_data)
5030 if (pass == SND_CONFIG_WALK_PASS_PRE) {
5031 char *buf = NULL, errbuf[256];
5032 const char *lib = NULL, *func_name = NULL;
5034 int (*func)(snd_config_t **dst, snd_config_t *root,
5035 snd_config_t *src, snd_config_t *private_data) = NULL;
5037 snd_config_t *c, *func_conf = NULL;
5038 err = snd_config_search(src, "@func", &c);
5041 err = snd_config_get_string(c, &str);
5043 SNDERR("Invalid type for @func");
5047 err = snd_config_search_definition(root, "func", str, &func_conf);
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);
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)
5060 if (strcmp(id, "lib") == 0) {
5061 err = snd_config_get_string(n, &lib);
5063 SNDERR("Invalid type for %s", id);
5068 if (strcmp(id, "func") == 0) {
5069 err = snd_config_get_string(n, &func_name);
5071 SNDERR("Invalid type for %s", id);
5076 SNDERR("Unknown field %s", id);
5080 int len = 9 + strlen(str) + 1;
5086 snprintf(buf, len, "snd_func_%s", str);
5090 h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf));
5092 func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE));
5095 SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
5099 SNDERR("symbol %s is not defined inside %s", func_name, lib);
5106 snd_config_delete(func_conf);
5109 err = func(&eval, root, src, private_data);
5111 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
5113 if (err >= 0 && eval)
5114 err = snd_config_substitute(src, eval);
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.
5133 * This function evaluates any functions (\c \@func) in \a config and
5134 * replaces those nodes with the respective function results.
5136 int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
5137 snd_config_t *private_data, snd_config_t **result)
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);
5144 static int load_defaults(snd_config_t *subs, snd_config_t *defs)
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)
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)
5157 if (strcmp(id, "default") == 0) {
5158 snd_config_t *deflt;
5160 err = snd_config_copy(&deflt, fld);
5163 err = snd_config_set_id(deflt, def->id);
5165 snd_config_delete(deflt);
5168 err = snd_config_add(subs, deflt);
5170 snd_config_delete(deflt);
5175 SNDERR("Unknown field %s", id);
5182 static void skip_blank(const char **ptr)
5199 static int parse_char(const char **ptr)
5202 assert(**ptr == '\\');
5224 case '0': case '1': case '2': case '3':
5225 case '4': case '5': case '6': case '7':
5232 if (c < '0' || c > '7')
5234 num = num * 8 + c - '0';
5247 static int parse_id(const char **ptr)
5268 static int parse_string(const char **ptr, char **val)
5270 const size_t bufsize = 256;
5273 size_t alloc = bufsize;
5281 SNDERR("Unterminated string");
5284 c = parse_char(ptr);
5286 if (alloc > bufsize)
5294 *val = malloc(idx + 1);
5297 memcpy(*val, buf, idx);
5299 if (alloc > bufsize)
5305 size_t old_alloc = alloc;
5307 if (old_alloc == bufsize) {
5308 buf = malloc(alloc);
5311 memcpy(buf, _buf, old_alloc);
5313 char *buf2 = realloc(buf, alloc);
5326 /* Parse var=val or val */
5327 static int parse_arg(const char **ptr, unsigned int *varlen, char **val)
5333 if (*str == '"' || *str == '\'') {
5334 err = parse_string(ptr, val);
5340 err = parse_id(ptr);
5343 vallen = *ptr - str;
5353 if (*str == '"' || *str == '\'') {
5354 err = parse_string(ptr, val);
5359 err = parse_id(ptr);
5362 vallen = *ptr - str;
5364 *val = malloc(vallen + 1);
5367 memcpy(*val, str, vallen);
5374 * var1=val1,var2=val2,...
5377 static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
5387 int len = strlen(str);
5389 snd_config_iterator_t i, next;
5391 switch (str[--len]) {
5403 if (str[len] != '}')
5405 err = snd_input_buffer_open(&input, str + 1, len - 1);
5408 err = snd_config_load_override(subs, input);
5409 snd_input_close(input);
5412 snd_config_for_each(i, next, subs) {
5413 snd_config_t *n = snd_config_iterator_entry(i);
5415 const char *id = n->id;
5416 err = snd_config_search(defs, id, &d);
5418 SNDERR("Unknown parameter %s", id);
5427 const char *var = buf;
5428 unsigned int varlen;
5429 snd_config_t *def, *sub, *typ;
5430 const char *new = str;
5435 err = parse_arg(&new, &varlen, &val);
5439 assert(varlen < sizeof(buf));
5440 memcpy(buf, str, varlen);
5443 sprintf(buf, "%d", arg);
5445 err = snd_config_search_alias(defs, NULL, var, &def);
5447 SNDERR("Unknown parameter %s", var);
5450 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) {
5451 SNDERR("Parameter %s definition is not correct", var);
5456 err = snd_config_search(subs, var, &sub);
5458 snd_config_delete(sub);
5460 err = snd_config_search(def, "type", &typ);
5463 SNDERR("Parameter %s definition is missing a valid type info", var);
5466 err = snd_config_get_string(typ, &tmp);
5467 if (err < 0 || !tmp)
5469 if (strcmp(tmp, "integer") == 0) {
5471 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER);
5474 err = safe_strtol(val, &v);
5476 SNDERR("Parameter %s must be an integer", var);
5479 err = snd_config_set_integer(sub, v);
5482 } else if (strcmp(tmp, "integer64") == 0) {
5484 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER64);
5487 err = safe_strtoll(val, &v);
5489 SNDERR("Parameter %s must be an integer", var);
5492 err = snd_config_set_integer64(sub, v);
5495 } else if (strcmp(tmp, "real") == 0) {
5497 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_REAL);
5500 err = safe_strtod(val, &v);
5502 SNDERR("Parameter %s must be a real", var);
5505 err = snd_config_set_real(sub, v);
5508 } else if (strcmp(tmp, "string") == 0) {
5509 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_STRING);
5512 err = snd_config_set_string(sub, val);
5519 err = snd_config_set_id(sub, var);
5522 err = snd_config_add(subs, sub);
5526 snd_config_delete(sub);
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
5550 * \return A non-negative value if successful, otherwise a negative error code.
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.
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)
5562 snd_config_t *defs, *subs = NULL, *res;
5563 err = snd_config_search(config, "@args", &defs);
5566 SNDERR("Unknown parameters %s", args);
5569 err = snd_config_copy(&res, config);
5573 err = snd_config_top(&subs);
5576 err = load_defaults(subs, defs);
5578 SNDERR("Load defaults error: %s", snd_strerror(err));
5581 err = parse_args(subs, args, defs);
5583 SNDERR("Parse arguments error: %s", snd_strerror(err));
5586 err = snd_config_evaluate(subs, root, private_data, NULL);
5588 SNDERR("Args evaluate error: %s", snd_strerror(err));
5591 err = snd_config_walk(config, root, &res, _snd_config_expand, subs);
5593 SNDERR("Expand error (walk): %s", snd_strerror(err));
5597 err = snd_config_evaluate(res, root, private_data, NULL);
5599 SNDERR("Evaluate error: %s", snd_strerror(err));
5600 snd_config_delete(res);
5607 snd_config_delete(subs);
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.
5621 * This functions searches for a child node of \a config, allowing
5622 * aliases and expanding hooks, like #snd_config_search_alias_hooks.
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.
5628 * In any case, \a result is a new node that must be freed by the
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.
5637 * Additionally, any errors encountered when parsing the hook
5638 * definitions or arguments, or returned by (hook) functions.
5640 int snd_config_search_definition(snd_config_t *config,
5641 const char *base, const char *name,
5642 snd_config_t **result)
5646 const char *args = strchr(name, ':');
5650 key = alloca(args - name);
5651 memcpy(key, name, args - name - 1);
5652 key[args - name - 1] = '\0';
5654 key = (char *) name;
5657 * if key contains dot (.), the implicit base is ignored
5658 * and the key starts from root given by the 'config' parameter
5661 err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf);
5663 snd_config_unlock();
5666 err = snd_config_expand(conf, config, args, NULL, result);
5667 snd_config_unlock();
5672 void snd_config_set_hop(snd_config_t *conf, int hop)
5677 int snd_config_check_hop(snd_config_t *conf)
5680 if (conf->hop >= SND_CONF_MAX_HOPS) {
5681 SYSERR("Too many definition levels (looped?)\n");
5691 /* Not strictly needed, but useful to check for memory leaks */
5692 void _snd_config_end(void) __attribute__ ((destructor));
5694 static void _snd_config_end(void)
5698 snd_config_delete(snd_config);
5700 for (k = 0; k < files_info_count; ++k)
5701 free(files_info[k].name);
5704 files_info_count = 0;
5708 size_t page_size(void)
5710 long s = sysconf(_SC_PAGE_SIZE);
5715 size_t page_align(size_t size)
5718 long psz = page_size();
5721 return size + psz - r;
5725 size_t page_ptr(size_t object_offset, size_t object_size, size_t *offset, size_t *mmap_offset)
5728 long psz = page_size();
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;
5737 r = object_size + psz - r;
5740 *offset = object_offset;