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)
1511 unsigned char *p = (unsigned char *)str;
1513 snd_output_puts(out, "''");
1518 case '0': case '1': case '2': case '3': case '4':
1519 case '5': case '6': case '7': case '8': case '9':
1543 if (*p <= 31 || *p >= 127)
1549 snd_output_puts(out, str);
1552 snd_output_putc(out, '\'');
1553 p = (unsigned char *)str;
1559 snd_output_putc(out, '\\');
1560 snd_output_putc(out, 'n');
1563 snd_output_putc(out, '\\');
1564 snd_output_putc(out, 't');
1567 snd_output_putc(out, '\\');
1568 snd_output_putc(out, 'v');
1571 snd_output_putc(out, '\\');
1572 snd_output_putc(out, 'b');
1575 snd_output_putc(out, '\\');
1576 snd_output_putc(out, 'r');
1579 snd_output_putc(out, '\\');
1580 snd_output_putc(out, 'f');
1583 snd_output_putc(out, '\\');
1584 snd_output_putc(out, c);
1587 if (c >= 32 && c <= 126 && c != '\'')
1588 snd_output_putc(out, c);
1590 snd_output_printf(out, "\\%04o", c);
1595 snd_output_putc(out, '\'');
1598 static void level_print(snd_output_t *out, unsigned int level)
1601 memset(a, '\t', level);
1603 snd_output_puts(out, a);
1606 static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1607 unsigned int level, unsigned int joins,
1610 static int _snd_config_save_node_value(snd_config_t *n, snd_output_t *out,
1615 case SND_CONFIG_TYPE_INTEGER:
1616 snd_output_printf(out, "%ld", n->u.integer);
1618 case SND_CONFIG_TYPE_INTEGER64:
1619 snd_output_printf(out, "%lld", n->u.integer64);
1621 case SND_CONFIG_TYPE_REAL:
1622 snd_output_printf(out, "%-16g", n->u.real);
1624 case SND_CONFIG_TYPE_STRING:
1625 string_print(n->u.string, 0, out);
1627 case SND_CONFIG_TYPE_POINTER:
1628 SNDERR("cannot save runtime pointer type");
1630 case SND_CONFIG_TYPE_COMPOUND:
1631 array = snd_config_is_array(n);
1632 snd_output_putc(out, array ? '[' : '{');
1633 snd_output_putc(out, '\n');
1634 err = _snd_config_save_children(n, out, level + 1, 0, array);
1637 level_print(out, level);
1638 snd_output_putc(out, array ? ']' : '}');
1644 static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins)
1648 id_print(n->parent, out, joins - 1);
1649 snd_output_putc(out, '.');
1651 string_print(n->id, 1, out);
1654 static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1655 unsigned int level, unsigned int joins,
1659 snd_config_iterator_t i, next;
1660 assert(config && out);
1661 snd_config_for_each(i, next, config) {
1662 snd_config_t *n = snd_config_iterator_entry(i);
1663 if (n->type == SND_CONFIG_TYPE_COMPOUND &&
1664 n->u.compound.join) {
1665 err = _snd_config_save_children(n, out, level, joins + 1, 0);
1670 level_print(out, level);
1672 id_print(n, out, joins);
1673 snd_output_putc(out, ' ');
1675 snd_output_putc(out, '=');
1678 err = _snd_config_save_node_value(n, out, level);
1682 snd_output_putc(out, ';');
1684 snd_output_putc(out, '\n');
1692 * \brief Substitutes one configuration node to another.
1693 * \param dst Handle to the destination node.
1694 * \param src Handle to the source node. Must not be the same as \a dst.
1695 * \return Zero if successful, otherwise a negative error code.
1697 * If both nodes are compounds, the source compound node members are
1698 * appended to the destination compound node.
1700 * If the destination node is a compound and the source node is
1701 * an ordinary type, the compound members are deleted (including
1704 * Otherwise, the source node's value replaces the destination node's
1707 * In any case, a successful call to this function frees the source
1710 int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
1713 if (dst->type == SND_CONFIG_TYPE_COMPOUND &&
1714 src->type == SND_CONFIG_TYPE_COMPOUND) { /* append */
1715 snd_config_iterator_t i, next;
1716 snd_config_for_each(i, next, src) {
1717 snd_config_t *n = snd_config_iterator_entry(i);
1720 src->u.compound.fields.next->prev = &dst->u.compound.fields;
1721 src->u.compound.fields.prev->next = &dst->u.compound.fields;
1722 } else if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
1724 err = snd_config_delete_compound_members(dst);
1730 dst->type = src->type;
1737 * \brief Converts an ASCII string to a configuration node type.
1738 * \param[in] ascii A string containing a configuration node type.
1739 * \param[out] type The node type corresponding to \a ascii.
1740 * \return Zero if successful, otherwise a negative error code.
1742 * This function recognizes at least the following node types:
1744 * <dt>integer<dt>#SND_CONFIG_TYPE_INTEGER
1745 * <dt>integer64<dt>#SND_CONFIG_TYPE_INTEGER64
1746 * <dt>real<dt>#SND_CONFIG_TYPE_REAL
1747 * <dt>string<dt>#SND_CONFIG_TYPE_STRING
1748 * <dt>compound<dt>#SND_CONFIG_TYPE_COMPOUND
1753 * <dt>-EINVAL<dd>Unknown note type in \a type.
1756 int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
1758 assert(ascii && type);
1759 if (!strcmp(ascii, "integer")) {
1760 *type = SND_CONFIG_TYPE_INTEGER;
1763 if (!strcmp(ascii, "integer64")) {
1764 *type = SND_CONFIG_TYPE_INTEGER64;
1767 if (!strcmp(ascii, "real")) {
1768 *type = SND_CONFIG_TYPE_REAL;
1771 if (!strcmp(ascii, "string")) {
1772 *type = SND_CONFIG_TYPE_STRING;
1775 if (!strcmp(ascii, "compound")) {
1776 *type = SND_CONFIG_TYPE_COMPOUND;
1783 * \brief Returns the type of a configuration node.
1784 * \param config Handle to the configuration node.
1785 * \return The node's type.
1787 * \par Conforming to:
1790 snd_config_type_t snd_config_get_type(const snd_config_t *config)
1792 return config->type;
1795 static int check_array_item(const char *id, int index)
1800 for (p = id; *p; p++) {
1801 if (*p < '0' || *p > '9')
1805 if (safe_strtol(id, &val))
1807 return val == index;
1811 * \brief Returns if the compound is an array.
1812 * \param config Handle to the configuration node.
1813 * \return A positive value when true, zero when false, otherwise a negative error code.
1815 int snd_config_is_array(const snd_config_t *config)
1818 snd_config_iterator_t i, next;
1822 if (config->type != SND_CONFIG_TYPE_COMPOUND)
1825 snd_config_for_each(i, next, config) {
1826 node = snd_config_iterator_entry(i);
1827 if (!check_array_item(node->id, idx))
1835 * \brief Returns the id of a configuration node.
1836 * \param[in] config Handle to the configuration node.
1837 * \param[out] id The function puts the pointer to the id string at the
1838 * address specified by \a id.
1839 * \return Zero if successful, otherwise a negative error code.
1841 * The returned string is owned by the configuration node; the application
1842 * must not modify or delete it, and the string becomes invalid when the
1843 * node's id changes or when the node is freed.
1845 * If the node does not have an id, \a *id is set to \c NULL.
1847 * \par Conforming to:
1850 int snd_config_get_id(const snd_config_t *config, const char **id)
1852 assert(config && id);
1858 * \brief Sets the id of a configuration node.
1859 * \param config Handle to the configuration node.
1860 * \param id The new node id, must not be \c NULL.
1861 * \return Zero if successful, otherwise a negative error code.
1863 * This function stores a copy of \a id in the node.
1867 * <dt>-EEXIST<dd>One of \a config's siblings already has the id \a id.
1868 * <dt>-EINVAL<dd>The id of a node with a parent cannot be set to \c NULL.
1869 * <dt>-ENOMEM<dd>Out of memory.
1872 int snd_config_set_id(snd_config_t *config, const char *id)
1874 snd_config_iterator_t i, next;
1878 if (config->parent) {
1879 snd_config_for_each(i, next, config->parent) {
1880 snd_config_t *n = snd_config_iterator_entry(i);
1881 if (n != config && strcmp(id, n->id) == 0)
1885 new_id = strdup(id);
1894 config->id = new_id;
1899 * \brief Creates a top level configuration node.
1900 * \param[out] config Handle to the new node.
1901 * \return Zero if successful, otherwise a negative error code.
1903 * The returned node is an empty compound node without a parent and
1908 * <dt>-ENOMEM<dd>Out of memory.
1911 * \par Conforming to:
1914 int snd_config_top(snd_config_t **config)
1917 return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
1921 int _snd_config_load_with_include(snd_config_t *config, snd_input_t *in,
1922 int override, const char * const *include_paths)
1926 struct filedesc *fd, *fd_next;
1928 assert(config && in);
1929 fd = malloc(sizeof(*fd));
1937 INIT_LIST_HEAD(&fd->include_paths);
1938 if (include_paths) {
1939 for (; *include_paths; include_paths++) {
1940 err = add_include_path(fd, *include_paths);
1945 err = add_include_path(fd, snd_config_topdir());
1951 err = parse_defs(config, &input, 0, override);
1956 case LOCAL_UNTERMINATED_STRING:
1957 str = "Unterminated string";
1960 case LOCAL_UNTERMINATED_QUOTE:
1961 str = "Unterminated quote";
1964 case LOCAL_UNEXPECTED_CHAR:
1965 str = "Unexpected char";
1968 case LOCAL_UNEXPECTED_EOF:
1969 str = "Unexpected end of file";
1973 str = strerror(-err);
1976 SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
1979 err = get_char(&input);
1981 if (err != LOCAL_UNEXPECTED_EOF) {
1982 SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
1990 snd_input_close(fd->in);
1992 free_include_paths(fd);
1997 free_include_paths(fd);
2004 * \brief Loads a configuration tree.
2005 * \param config Handle to a top level configuration node.
2006 * \param in Input handle to read the configuration from.
2007 * \return Zero if successful, otherwise a negative error code.
2009 * The definitions loaded from the input are added to \a config, which
2010 * must be a compound node.
2013 * Any errors encountered when parsing the input or returned by hooks or
2016 * \par Conforming to:
2019 int snd_config_load(snd_config_t *config, snd_input_t *in)
2021 return _snd_config_load_with_include(config, in, 0, NULL);
2025 * \brief Loads a configuration tree and overrides existing configuration nodes.
2026 * \param config Handle to a top level configuration node.
2027 * \param in Input handle to read the configuration from.
2028 * \return Zero if successful, otherwise a negative error code.
2030 * This function loads definitions from \a in into \a config like
2031 * #snd_config_load, but the default mode for input nodes is 'override'
2032 * (!) instead of 'merge+create' (+).
2034 int snd_config_load_override(snd_config_t *config, snd_input_t *in)
2036 return _snd_config_load_with_include(config, in, 1, NULL);
2040 * \brief Adds a child to a compound configuration node.
2041 * \param parent Handle to a compound configuration node.
2042 * \param child Handle to the configuration node to be added.
2043 * \return Zero if successful, otherwise a negative error code.
2045 * This function makes the node \a child a child of the node \a parent.
2047 * The parent node then owns the child node, i.e., the child node gets
2048 * deleted together with its parent.
2050 * \a child must have an id.
2054 * <dt>-EINVAL<dd>\a child does not have an id.
2055 * <dt>-EINVAL<dd>\a child already has a parent.
2056 * <dt>-EEXIST<dd>\a parent already contains a child node with the same
2060 * \par Conforming to:
2063 int snd_config_add(snd_config_t *parent, snd_config_t *child)
2065 snd_config_iterator_t i, next;
2066 assert(parent && child);
2067 if (!child->id || child->parent)
2069 snd_config_for_each(i, next, parent) {
2070 snd_config_t *n = snd_config_iterator_entry(i);
2071 if (strcmp(child->id, n->id) == 0)
2074 child->parent = parent;
2075 list_add_tail(&child->list, &parent->u.compound.fields);
2080 * \brief Adds a child after another child configuration node.
2081 * \param after Handle to the start configuration node.
2082 * \param child Handle to the configuration node to be added.
2083 * \return Zero if successful, otherwise a negative error code.
2085 * This function makes the node \a child a child of the parent of
2086 * the node \a after.
2088 * The parent node then owns the child node, i.e., the child node gets
2089 * deleted together with its parent.
2091 * \a child must have an id.
2095 * <dt>-EINVAL<dd>\a child does not have an id.
2096 * <dt>-EINVAL<dd>\a child already has a parent.
2097 * <dt>-EEXIST<dd>\a parent already contains a child node with the same
2101 int snd_config_add_after(snd_config_t *after, snd_config_t *child)
2103 snd_config_iterator_t i, next;
2104 snd_config_t *parent;
2105 assert(after && child);
2106 parent = after->parent;
2108 if (!child->id || child->parent)
2110 snd_config_for_each(i, next, parent) {
2111 snd_config_t *n = snd_config_iterator_entry(i);
2112 if (strcmp(child->id, n->id) == 0)
2115 child->parent = parent;
2116 list_insert(&child->list, &after->list, after->list.next);
2121 * \brief Adds a child before another child configuration node.
2122 * \param before Handle to the start configuration node.
2123 * \param child Handle to the configuration node to be added.
2124 * \return Zero if successful, otherwise a negative error code.
2126 * This function makes the node \a child a child of the parent of
2127 * the node \a before.
2129 * The parent node then owns the child node, i.e., the child node gets
2130 * deleted together with its parent.
2132 * \a child must have an id.
2136 * <dt>-EINVAL<dd>\a child does not have an id.
2137 * <dt>-EINVAL<dd>\a child already has a parent.
2138 * <dt>-EEXIST<dd>\a parent already contains a child node with the same
2142 int snd_config_add_before(snd_config_t *before, snd_config_t *child)
2144 snd_config_iterator_t i, next;
2145 snd_config_t *parent;
2146 assert(before && child);
2147 parent = before->parent;
2149 if (!child->id || child->parent)
2151 snd_config_for_each(i, next, parent) {
2152 snd_config_t *n = snd_config_iterator_entry(i);
2153 if (strcmp(child->id, n->id) == 0)
2156 child->parent = parent;
2157 list_insert(&child->list, before->list.prev, &before->list);
2162 * \brief Removes a configuration node from its tree.
2163 * \param config Handle to the configuration node to be removed.
2164 * \return Zero if successful, otherwise a negative error code.
2166 * This function makes \a config a top-level node, i.e., if \a config
2167 * has a parent, then \a config is removed from the list of the parent's
2170 * This functions does \e not free the removed node.
2172 * \sa snd_config_delete
2174 int snd_config_remove(snd_config_t *config)
2178 list_del(&config->list);
2179 config->parent = NULL;
2184 * \brief Frees a configuration node.
2185 * \param config Handle to the configuration node to be deleted.
2186 * \return Zero if successful, otherwise a negative error code.
2188 * This function frees a configuration node and all its resources.
2190 * If the node is a child node, it is removed from the tree before being
2193 * If the node is a compound node, its descendants (the whole subtree)
2194 * are deleted recursively.
2196 * The function is supposed to be called only for locally copied config
2197 * trees. For the global tree, take the reference via #snd_config_update_ref
2198 * and free it via #snd_config_unref.
2200 * \par Conforming to:
2203 * \sa snd_config_remove
2205 int snd_config_delete(snd_config_t *config)
2208 if (config->refcount > 0) {
2212 switch (config->type) {
2213 case SND_CONFIG_TYPE_COMPOUND:
2216 struct list_head *i;
2217 i = config->u.compound.fields.next;
2218 while (i != &config->u.compound.fields) {
2219 struct list_head *nexti = i->next;
2220 snd_config_t *child = snd_config_iterator_entry(i);
2221 err = snd_config_delete(child);
2228 case SND_CONFIG_TYPE_STRING:
2229 free(config->u.string);
2235 list_del(&config->list);
2242 * \brief Deletes the children of a node.
2243 * \param config Handle to the compound configuration node.
2244 * \return Zero if successful, otherwise a negative error code.
2246 * This function removes and frees all children of a configuration node.
2248 * Any compound nodes among the children of \a config are deleted
2251 * After a successful call to this function, \a config is an empty
2256 * <dt>-EINVAL<dd>\a config is not a compound node.
2259 int snd_config_delete_compound_members(const snd_config_t *config)
2262 struct list_head *i;
2265 if (config->type != SND_CONFIG_TYPE_COMPOUND)
2267 i = config->u.compound.fields.next;
2268 while (i != &config->u.compound.fields) {
2269 struct list_head *nexti = i->next;
2270 snd_config_t *child = snd_config_iterator_entry(i);
2271 err = snd_config_delete(child);
2280 * \brief Creates a configuration node.
2281 * \param[out] config The function puts the handle to the new node at
2282 * the address specified by \a config.
2283 * \param[in] id The id of the new node.
2284 * \param[in] type The type of the new node.
2285 * \return Zero if successful, otherwise a negative error code.
2287 * This functions creates a new node of the specified type.
2288 * The new node has id \a id, which may be \c NULL.
2290 * The value of the new node is zero (for numbers), or \c NULL (for
2291 * strings and pointers), or empty (for compound nodes).
2295 * <dt>-ENOMEM<dd>Out of memory.
2298 int snd_config_make(snd_config_t **config, const char *id,
2299 snd_config_type_t type)
2309 return _snd_config_make(config, &id1, type);
2313 * \brief Creates an integer configuration node.
2314 * \param[out] config The function puts the handle to the new node at
2315 * the address specified by \a config.
2316 * \param[in] id The id of the new node.
2317 * \return Zero if successful, otherwise a negative error code.
2319 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
2324 * <dt>-ENOMEM<dd>Out of memory.
2327 * \par Conforming to:
2330 * \sa snd_config_imake_integer
2332 int snd_config_make_integer(snd_config_t **config, const char *id)
2334 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
2338 * \brief Creates a 64-bit-integer configuration node.
2339 * \param[out] config The function puts the handle to the new node at
2340 * the address specified by \a config.
2341 * \param[in] id The id of the new node.
2342 * \return Zero if successful, otherwise a negative error code.
2344 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
2345 * and with value \c 0.
2349 * <dt>-ENOMEM<dd>Out of memory.
2352 * \par Conforming to:
2355 * \sa snd_config_imake_integer64
2357 int snd_config_make_integer64(snd_config_t **config, const char *id)
2359 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
2363 * \brief Creates a real number configuration node.
2364 * \param[out] config The function puts the handle to the new node at
2365 * the address specified by \a config.
2366 * \param[in] id The id of the new node.
2367 * \return Zero if successful, otherwise a negative error code.
2369 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
2370 * with value \c 0.0.
2374 * <dt>-ENOMEM<dd>Out of memory.
2377 * \sa snd_config_imake_real
2379 int snd_config_make_real(snd_config_t **config, const char *id)
2381 return snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
2385 * \brief Creates a string configuration node.
2386 * \param[out] config The function puts the handle to the new node at
2387 * the address specified by \a config.
2388 * \param[in] id The id of the new node.
2389 * \return Zero if successful, otherwise a negative error code.
2391 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2392 * with value \c NULL.
2396 * <dt>-ENOMEM<dd>Out of memory.
2399 * \par Conforming to:
2402 * \sa snd_config_imake_string
2404 int snd_config_make_string(snd_config_t **config, const char *id)
2406 return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
2410 * \brief Creates a pointer configuration node.
2411 * \param[out] config The function puts the handle to the new node at
2412 * the address specified by \a config.
2413 * \param[in] id The id of the new node.
2414 * \return Zero if successful, otherwise a negative error code.
2416 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2417 * with value \c NULL.
2421 * <dt>-ENOMEM<dd>Out of memory.
2424 * \sa snd_config_imake_pointer
2426 int snd_config_make_pointer(snd_config_t **config, const char *id)
2428 return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2432 * \brief Creates an empty compound configuration node.
2433 * \param[out] config The function puts the handle to the new node at
2434 * the address specified by \a config.
2435 * \param[in] id The id of the new node.
2436 * \param[in] join Join flag.
2437 * \return Zero if successful, otherwise a negative error code.
2439 * This function creates a new empty node of type
2440 * #SND_CONFIG_TYPE_COMPOUND.
2442 * \a join determines how the compound node's id is printed when the
2443 * configuration is saved to a text file. For example, if the join flag
2444 * of compound node \c a is zero, the output will look as follows:
2451 * If, however, the join flag of \c a is nonzero, its id will be joined
2452 * with its children's ids, like this:
2457 * An \e empty compound node with its join flag set would result in no
2458 * output, i.e., after saving and reloading the configuration file, that
2459 * compound node would be lost.
2463 * <dt>-ENOMEM<dd>Out of memory.
2466 * \par Conforming to:
2469 int snd_config_make_compound(snd_config_t **config, const char *id,
2473 err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND);
2476 (*config)->u.compound.join = join;
2481 * \brief Creates an integer configuration node with the given initial value.
2482 * \param[out] config The function puts the handle to the new node at
2483 * the address specified by \a config.
2484 * \param[in] id The id of the new node.
2485 * \param[in] value The initial value of the new node.
2486 * \return Zero if successful, otherwise a negative error code.
2488 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
2489 * with value \a value.
2493 * <dt>-ENOMEM<dd>Out of memory.
2496 * \par Conforming to:
2499 int snd_config_imake_integer(snd_config_t **config, const char *id, const long value)
2503 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
2506 (*config)->u.integer = value;
2511 * \brief Creates a 64-bit-integer configuration node with the given initial value.
2512 * \param[out] config The function puts the handle to the new node at
2513 * the address specified by \a config.
2514 * \param[in] id The id of the new node.
2515 * \param[in] value The initial value of the new node.
2516 * \return Zero if successful, otherwise a negative error code.
2518 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
2519 * and with value \a value.
2523 * <dt>-ENOMEM<dd>Out of memory.
2526 * \par Conforming to:
2529 int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value)
2533 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
2536 (*config)->u.integer64 = value;
2541 * \brief Creates a real number configuration node with the given initial value.
2542 * \param[out] config The function puts the handle to the new node at
2543 * the address specified by \a config.
2544 * \param[in] id The id of the new node.
2545 * \param[in] value The initial value of the new node.
2546 * \return Zero if successful, otherwise a negative error code.
2548 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
2549 * with value \a value.
2553 * <dt>-ENOMEM<dd>Out of memory.
2556 int snd_config_imake_real(snd_config_t **config, const char *id, const double value)
2560 err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
2563 (*config)->u.real = value;
2568 * \brief Creates a string configuration node with the given initial value.
2569 * \param[out] config The function puts the handle to the new node at
2570 * the address specified by \a config.
2571 * \param[in] id The id of the new node.
2572 * \param[in] value The initial value of the new node. May be \c NULL.
2573 * \return Zero if successful, otherwise a negative error code.
2575 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2576 * with a copy of the string \c value.
2580 * <dt>-ENOMEM<dd>Out of memory.
2583 * \par Conforming to:
2586 int snd_config_imake_string(snd_config_t **config, const char *id, const char *value)
2591 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
2595 tmp->u.string = strdup(value);
2596 if (!tmp->u.string) {
2597 snd_config_delete(tmp);
2601 tmp->u.string = NULL;
2607 int snd_config_imake_safe_string(snd_config_t **config, const char *id, const char *value)
2613 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
2617 tmp->u.string = strdup(value);
2618 if (!tmp->u.string) {
2619 snd_config_delete(tmp);
2623 for (c = tmp->u.string; *c; c++) {
2624 if (*c == ' ' || *c == '-' || *c == '_' ||
2625 (*c >= '0' && *c <= '9') ||
2626 (*c >= 'a' && *c <= 'z') ||
2627 (*c >= 'A' && *c <= 'Z'))
2632 tmp->u.string = NULL;
2640 * \brief Creates a pointer configuration node with the given initial value.
2641 * \param[out] config The function puts the handle to the new node at
2642 * the address specified by \a config.
2643 * \param[in] id The id of the new node.
2644 * \param[in] value The initial value of the new node.
2645 * \return Zero if successful, otherwise a negative error code.
2647 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2648 * with value \c value.
2652 * <dt>-ENOMEM<dd>Out of memory.
2655 int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value)
2659 err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2662 (*config)->u.ptr = value;
2667 * \brief Changes the value of an integer configuration node.
2668 * \param config Handle to the configuration node.
2669 * \param value The new value for the node.
2670 * \return Zero if successful, otherwise a negative error code.
2674 * <dt>-EINVAL<dd>\a config is not an integer node.
2677 * \par Conforming to:
2680 int snd_config_set_integer(snd_config_t *config, long value)
2683 if (config->type != SND_CONFIG_TYPE_INTEGER)
2685 config->u.integer = value;
2690 * \brief Changes the value of a 64-bit-integer configuration node.
2691 * \param config Handle to the configuration node.
2692 * \param value The new value for the node.
2693 * \return Zero if successful, otherwise a negative error code.
2697 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2700 * \par Conforming to:
2703 int snd_config_set_integer64(snd_config_t *config, long long value)
2706 if (config->type != SND_CONFIG_TYPE_INTEGER64)
2708 config->u.integer64 = value;
2713 * \brief Changes the value of a real-number configuration node.
2714 * \param config Handle to the configuration node.
2715 * \param value The new value for the node.
2716 * \return Zero if successful, otherwise a negative error code.
2720 * <dt>-EINVAL<dd>\a config is not a real-number node.
2723 int snd_config_set_real(snd_config_t *config, double value)
2726 if (config->type != SND_CONFIG_TYPE_REAL)
2728 config->u.real = value;
2733 * \brief Changes the value of a string configuration node.
2734 * \param config Handle to the configuration node.
2735 * \param value The new value for the node. May be \c NULL.
2736 * \return Zero if successful, otherwise a negative error code.
2738 * This function deletes the old string in the node and stores a copy of
2739 * \a value string in the node.
2743 * <dt>-EINVAL<dd>\a config is not a string node.
2746 * \par Conforming to:
2749 int snd_config_set_string(snd_config_t *config, const char *value)
2753 if (config->type != SND_CONFIG_TYPE_STRING)
2756 new_string = strdup(value);
2762 free(config->u.string);
2763 config->u.string = new_string;
2768 * \brief Changes the value of a pointer configuration node.
2769 * \param config Handle to the configuration node.
2770 * \param value The new value for the node. May be \c NULL.
2771 * \return Zero if successful, otherwise a negative error code.
2773 * This function does not free the old pointer in the node.
2777 * <dt>-EINVAL<dd>\a config is not a pointer node.
2780 int snd_config_set_pointer(snd_config_t *config, const void *value)
2783 if (config->type != SND_CONFIG_TYPE_POINTER)
2785 config->u.ptr = value;
2790 * \brief Changes the value of a configuration node.
2791 * \param config Handle to the configuration node.
2792 * \param ascii The new value for the node, as an ASCII string.
2793 * \return Zero if successful, otherwise a negative error code.
2795 * This function changes the node's value to a new value that is parsed
2796 * from the string \a ascii. \a ascii must not be \c NULL, not even for
2799 * The node's type does not change, i.e., the string must contain a
2800 * valid value with the same type as the node's type. For a string
2801 * node, the node's new value is a copy of \a ascii.
2805 * <dt>-EINVAL<dd>\a config is not a number or string node.
2806 * <dt>-EINVAL<dd>The value in \a ascii cannot be parsed.
2807 * <dt>-ERANGE<dd>The value in \a ascii is too big for the node's type.
2808 * <dt>-ENOMEM<dd>Out of memory.
2811 * \par Conforming to:
2814 int snd_config_set_ascii(snd_config_t *config, const char *ascii)
2816 assert(config && ascii);
2817 switch (config->type) {
2818 case SND_CONFIG_TYPE_INTEGER:
2821 int err = safe_strtol(ascii, &i);
2824 config->u.integer = i;
2827 case SND_CONFIG_TYPE_INTEGER64:
2830 int err = safe_strtoll(ascii, &i);
2833 config->u.integer64 = i;
2836 case SND_CONFIG_TYPE_REAL:
2839 int err = safe_strtod(ascii, &d);
2845 case SND_CONFIG_TYPE_STRING:
2847 char *ptr = strdup(ascii);
2850 free(config->u.string);
2851 config->u.string = ptr;
2861 * \brief Returns the value of an integer configuration node.
2862 * \param[in] config Handle to the configuration node.
2863 * \param[out] ptr The node's value.
2864 * \return Zero if successful, otherwise a negative error code.
2868 * <dt>-EINVAL<dd>\a config is not an integer node.
2871 * \par Conforming to:
2874 int snd_config_get_integer(const snd_config_t *config, long *ptr)
2876 assert(config && ptr);
2877 if (config->type != SND_CONFIG_TYPE_INTEGER)
2879 *ptr = config->u.integer;
2884 * \brief Returns the value of a 64-bit-integer configuration node.
2885 * \param[in] config Handle to the configuration node.
2886 * \param[out] ptr The node's value.
2887 * \return Zero if successful, otherwise a negative error code.
2891 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2894 * \par Conforming to:
2897 int snd_config_get_integer64(const snd_config_t *config, long long *ptr)
2899 assert(config && ptr);
2900 if (config->type != SND_CONFIG_TYPE_INTEGER64)
2902 *ptr = config->u.integer64;
2907 * \brief Returns the value of a real-number configuration node.
2908 * \param[in] config Handle to the configuration node.
2909 * \param[out] ptr The node's value.
2910 * \return Zero if successful, otherwise a negative error code.
2914 * <dt>-EINVAL<dd>\a config is not a real-number node.
2917 int snd_config_get_real(const snd_config_t *config, double *ptr)
2919 assert(config && ptr);
2920 if (config->type != SND_CONFIG_TYPE_REAL)
2922 *ptr = config->u.real;
2927 * \brief Returns the value of a real or integer configuration node.
2928 * \param[in] config Handle to the configuration node.
2929 * \param[out] ptr The node's value.
2930 * \return Zero if successful, otherwise a negative error code.
2932 * If the node's type is integer or integer64, the value is converted
2933 * to the \c double type on the fly.
2937 * <dt>-EINVAL<dd>\a config is not a number node.
2940 int snd_config_get_ireal(const snd_config_t *config, double *ptr)
2942 assert(config && ptr);
2943 if (config->type == SND_CONFIG_TYPE_REAL)
2944 *ptr = config->u.real;
2945 else if (config->type == SND_CONFIG_TYPE_INTEGER)
2946 *ptr = config->u.integer;
2947 else if (config->type == SND_CONFIG_TYPE_INTEGER64)
2948 *ptr = config->u.integer64;
2955 * \brief Returns the value of a string configuration node.
2956 * \param[in] config Handle to the configuration node.
2957 * \param[out] ptr The function puts the node's value at the address
2958 * specified by \a ptr.
2959 * \return Zero if successful, otherwise a negative error code.
2961 * The returned string is owned by the configuration node; the
2962 * application must not modify or delete it, and the string becomes
2963 * invalid when the node's value changes or when the node is freed.
2965 * The string may be \c NULL.
2969 * <dt>-EINVAL<dd>\a config is not a string node.
2972 * \par Conforming to:
2975 int snd_config_get_string(const snd_config_t *config, const char **ptr)
2977 assert(config && ptr);
2978 if (config->type != SND_CONFIG_TYPE_STRING)
2980 *ptr = config->u.string;
2985 * \brief Returns the value of a pointer configuration node.
2986 * \param[in] config Handle to the configuration node.
2987 * \param[out] ptr The function puts the node's value at the address
2988 * specified by \a ptr.
2989 * \return Zero if successful, otherwise a negative error code.
2993 * <dt>-EINVAL<dd>\a config is not a string node.
2996 int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
2998 assert(config && ptr);
2999 if (config->type != SND_CONFIG_TYPE_POINTER)
3001 *ptr = config->u.ptr;
3006 * \brief Returns the value of a configuration node as a string.
3007 * \param[in] config Handle to the configuration node.
3008 * \param[out] ascii The function puts the pointer to the returned
3009 * string at the address specified by \a ascii.
3010 * \return Zero if successful, otherwise a negative error code.
3012 * This function dynamically allocates the returned string. The
3013 * application is responsible for deleting it with \c free() when it is
3016 * For a string node with \c NULL value, the returned string is \c NULL.
3018 * Supported node types are #SND_CONFIG_TYPE_INTEGER,
3019 * #SND_CONFIG_TYPE_INTEGER64, #SND_CONFIG_TYPE_REAL, and
3020 * #SND_CONFIG_TYPE_STRING.
3024 * <dt>-EINVAL<dd>\a config is not a (64-bit) integer or real number or
3026 * <dt>-ENOMEM<dd>Out of memory.
3029 * \par Conforming to:
3032 int snd_config_get_ascii(const snd_config_t *config, char **ascii)
3034 assert(config && ascii);
3035 switch (config->type) {
3036 case SND_CONFIG_TYPE_INTEGER:
3040 err = snprintf(res, sizeof(res), "%li", config->u.integer);
3041 if (err < 0 || err == sizeof(res)) {
3045 *ascii = strdup(res);
3048 case SND_CONFIG_TYPE_INTEGER64:
3052 err = snprintf(res, sizeof(res), "%lli", config->u.integer64);
3053 if (err < 0 || err == sizeof(res)) {
3057 *ascii = strdup(res);
3060 case SND_CONFIG_TYPE_REAL:
3064 err = snprintf(res, sizeof(res), "%-16g", config->u.real);
3065 if (err < 0 || err == sizeof(res)) {
3069 if (res[0]) { /* trim the string */
3071 ptr = res + strlen(res) - 1;
3072 while (ptr != res && *ptr == ' ')
3078 *ascii = strdup(res);
3081 case SND_CONFIG_TYPE_STRING:
3082 if (config->u.string)
3083 *ascii = strdup(config->u.string);
3098 * \brief Compares the id of a configuration node to a given string.
3099 * \param config Handle to the configuration node.
3100 * \param id ASCII id.
3101 * \return The same value as the result of the \c strcmp function, i.e.,
3102 * less than zero if \a config's id is lexicographically less
3103 * than \a id, zero if \a config's id is equal to id, greater
3104 * than zero otherwise.
3106 int snd_config_test_id(const snd_config_t *config, const char *id)
3108 assert(config && id);
3110 return strcmp(config->id, id);
3116 * \brief Dumps the contents of a configuration node or tree.
3117 * \param config Handle to the (root) configuration node.
3118 * \param out Output handle.
3119 * \return Zero if successful, otherwise a negative error code.
3121 * This function writes a textual representation of \a config's value to
3122 * the output \a out.
3126 * <dt>-EINVAL<dd>A node in the tree has a type that cannot be printed,
3127 * i.e., #SND_CONFIG_TYPE_POINTER.
3130 * \par Conforming to:
3133 int snd_config_save(snd_config_t *config, snd_output_t *out)
3135 assert(config && out);
3136 if (config->type == SND_CONFIG_TYPE_COMPOUND) {
3137 int array = snd_config_is_array(config);
3138 return _snd_config_save_children(config, out, 0, 0, array);
3140 return _snd_config_save_node_value(config, out, 0);
3145 * *** search macros ***
3150 #define SND_CONFIG_SEARCH(config, key, result, extra_code) \
3155 assert(config && key); \
3157 if (config->type != SND_CONFIG_TYPE_COMPOUND) \
3160 p = strchr(key, '.'); \
3162 err = _snd_config_search(config, key, p - key, &n); \
3168 return _snd_config_search(config, key, -1, result); \
3172 #define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \
3177 assert(config && key); \
3179 if (config->type != SND_CONFIG_TYPE_COMPOUND) { \
3180 if (snd_config_get_string(config, &p) < 0) \
3182 err = fcn(root, root, p, &config); \
3187 p = strchr(key, '.'); \
3189 err = _snd_config_search(config, key, p - key, &n); \
3195 return _snd_config_search(config, key, -1, result); \
3199 #define SND_CONFIG_SEARCHV(config, result, fcn) \
3204 va_start(arg, result); \
3206 const char *k = va_arg(arg, const char *); \
3210 err = fcn(config, k, &n); \
3223 #define SND_CONFIG_SEARCHVA(root, config, result, fcn) \
3228 va_start(arg, result); \
3230 const char *k = va_arg(arg, const char *); \
3234 err = fcn(root, config, k, &n); \
3247 #define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
3249 snd_config_t *res = NULL; \
3251 int err, first = 1, maxloop = 1000; \
3252 assert(config && key); \
3254 old_key = strdup(key); \
3255 if (old_key == NULL) { \
3260 err = first && base ? -EIO : fcn1(config, config, key, &res); \
3264 err = fcn2(config, config, &res, base, key, NULL); \
3268 if (snd_config_get_string(res, &key) < 0) \
3271 if (!first && (strcmp(key, old_key) == 0 || maxloop <= 0)) { \
3273 SNDERR("maximum loop count reached (circular configuration?)"); \
3275 SNDERR("key %s refers to itself", key); \
3292 #endif /* DOC_HIDDEN */
3295 * \brief Searches for a node in a configuration tree.
3296 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3297 * \param[in] key Search key: one or more node ids, separated with dots.
3298 * \param[out] result When \a result != \c NULL, the function puts the
3299 * handle to the node found at the address specified
3301 * \return Zero if successful, otherwise a negative error code.
3303 * This function searches for a child node of \a config that is
3304 * identified by \a key, which contains either the id of a direct child
3305 * node of \a config, or a series of ids, separated with dots, where
3306 * each id specifies a node that is contained in the previous compound
3309 * In the following example, the comment after each node shows the
3310 * search key to find that node, assuming that \a config is a handle to
3311 * the compound node with id \c config:
3318 * e 2.71828 # "b.d.e"
3326 * <dt>-ENOENT<dd>An id in \a key does not exist.
3327 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3328 * not a compound node.
3331 * \par Conforming to:
3334 int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
3336 SND_CONFIG_SEARCH(config, key, result, );
3340 * \brief Searches for a node in a configuration tree, expanding aliases.
3341 * \param[in] root Handle to the root configuration node containing
3342 * alias definitions.
3343 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3344 * \param[in] key Search key: one or more node keys, separated with dots.
3345 * \param[out] result When \a result != \c NULL, the function puts the
3346 * handle to the node found at the address specified
3348 * \return Zero if successful, otherwise a negative error code.
3350 * This functions searches for a child node of \a config like
3351 * #snd_config_search. However, any compound node can also be
3352 * identified by an alias, which is a string node whose value is taken
3353 * as the id of a compound node below \a root.
3355 * \a root must be a compound node.
3356 * \a root and \a config may be the same node.
3358 * For example, with the following configuration, the call
3360 * snd_config_searcha(root, config, "a.b.c.d", &result);
3362 * would return the node with id \c d:
3384 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3385 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3386 * not a compound or string node.
3389 int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
3391 SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, );
3395 * \brief Searches for a node in a configuration tree.
3396 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3397 * \param[out] result When \a result != \c NULL, the function puts the
3398 * handle to the node found at the address specified
3400 * \param[in] ... One or more concatenated dot-separated search keys,
3401 * terminated with \c NULL.
3402 * \return Zero if successful, otherwise a negative error code.
3404 * This functions searches for a child node of \a config like
3405 * #snd_config_search, but the search key is the concatenation of all
3406 * passed search key strings. For example, the call
3408 * snd_config_searchv(cfg, &res, "a", "b.c", "d.e", NULL);
3410 * is equivalent to the call
3412 * snd_config_search(cfg, "a.b.c.d.e", &res);
3417 * <dt>-ENOENT<dd>An id in a search key does not exist.
3418 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3419 * not a compound node.
3422 * \par Conforming to:
3425 int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...)
3427 SND_CONFIG_SEARCHV(config, result, snd_config_search);
3431 * \brief Searches for a node in a configuration tree, expanding aliases.
3432 * \param[in] root Handle to the root configuration node containing
3433 * alias definitions.
3434 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3435 * \param[out] result When \a result != \c NULL, the function puts the
3436 * handle to the node found at the address specified
3438 * \param[in] ... One or more concatenated dot separated search keys,
3439 * terminated with \c NULL.
3440 * \return Zero if successful, otherwise a negative error code.
3442 * This function searches for a child node of \a config, allowing
3443 * aliases, like #snd_config_searcha, but the search key is the
3444 * concatenation of all passed seach key strings, like with
3445 * #snd_config_searchv.
3449 * <dt>-ENOENT<dd>An id in a search key does not exist.
3450 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3451 * not a compound or string node.
3454 int snd_config_searchva(snd_config_t *root, snd_config_t *config, snd_config_t **result, ...)
3456 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha);
3460 * \brief Searches for a node in a configuration tree, expanding aliases.
3461 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3462 * \param[in] base Search key base, or \c NULL.
3463 * \param[in] key Search key suffix.
3464 * \param[out] result When \a result != \c NULL, the function puts the
3465 * handle to the node found at the address specified
3467 * \return Zero if successful, otherwise a negative error code.
3469 * This functions searches for a child node of \a config, allowing
3470 * aliases, like #snd_config_searcha. However, alias definitions are
3471 * searched below \a config (there is no separate \a root parameter),
3472 * and \a base specifies a seach key that identifies a compound node
3473 * that is used to search for an alias definitions that is not found
3474 * directly below \a config and that does not contain a period. In
3475 * other words, when \c "id" is not found in \a config, this function
3476 * also tries \c "base.id".
3480 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3481 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3482 * not a compound or string node.
3485 int snd_config_search_alias(snd_config_t *config,
3486 const char *base, const char *key,
3487 snd_config_t **result)
3489 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3490 snd_config_searcha, snd_config_searchva);
3493 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
3496 * \brief Searches for a node in a configuration tree and expands hooks.
3497 * \param[in,out] config Handle to the root of the configuration
3498 * (sub)tree to search.
3499 * \param[in] key Search key: one or more node keys, separated with dots.
3500 * \param[out] result The function puts the handle to the node found at
3501 * the address specified by \a result.
3502 * \return Zero if successful, otherwise a negative error code.
3504 * This functions searches for a child node of \a config like
3505 * #snd_config_search, but any compound nodes to be searched that
3506 * contain hooks are modified by the respective hook functions.
3510 * <dt>-ENOENT<dd>An id in \a key does not exist.
3511 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3512 * not a compound node.
3514 * Additionally, any errors encountered when parsing the hook
3515 * definitions or returned by the hook functions.
3517 int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
3519 SND_CONFIG_SEARCH(config, key, result, \
3520 err = snd_config_hooks(config, NULL); \
3527 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
3528 * \param[in] root Handle to the root configuration node containing
3529 * alias definitions.
3530 * \param[in,out] config Handle to the root of the configuration
3531 * (sub)tree to search.
3532 * \param[in] key Search key: one or more node keys, separated with dots.
3533 * \param[out] result The function puts the handle to the node found at
3534 * the address specified by \a result.
3535 * \return Zero if successful, otherwise a negative error code.
3537 * This function searches for a child node of \a config, allowing
3538 * aliases, like #snd_config_searcha, and expanding hooks, like
3539 * #snd_config_search_hooks.
3543 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3544 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3545 * not a compound node.
3547 * Additionally, any errors encountered when parsing the hook
3548 * definitions or returned by the hook functions.
3550 int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
3552 SND_CONFIG_SEARCHA(root, config, key, result,
3553 snd_config_searcha_hooks,
3554 err = snd_config_hooks(config, NULL); \
3561 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
3562 * \param[in] root Handle to the root configuration node containing
3563 * alias definitions.
3564 * \param[in,out] config Handle to the root of the configuration
3565 * (sub)tree to search.
3566 * \param[out] result The function puts the handle to the node found at
3567 * the address specified by \a result.
3568 * \param[in] ... One or more concatenated dot separated search keys,
3569 * terminated with \c NULL.
3570 * \return Zero if successful, otherwise a negative error code.
3572 * This function searches for a child node of \a config, allowing
3573 * aliases and expanding hooks like #snd_config_searcha_hooks, but the
3574 * search key is the concatenation of all passed seach key strings, like
3575 * with #snd_config_searchv.
3579 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3580 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3581 * not a compound node.
3583 * Additionally, any errors encountered when parsing the hook
3584 * definitions or returned by the hook functions.
3586 int snd_config_searchva_hooks(snd_config_t *root, snd_config_t *config,
3587 snd_config_t **result, ...)
3589 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha_hooks);
3593 * \brief Searches for a node in a configuration tree, using an alias and expanding hooks.
3594 * \param[in] config Handle to the root of the configuration (sub)tree
3596 * \param[in] base Search key base, or \c NULL.
3597 * \param[in] key Search key suffix.
3598 * \param[out] result The function puts the handle to the node found at
3599 * the address specified by \a result.
3600 * \return Zero if successful, otherwise a negative error code.
3602 * This functions searches for a child node of \a config, allowing
3603 * aliases, like #snd_config_search_alias, and expanding hooks, like
3604 * #snd_config_search_hooks.
3608 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3609 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3610 * not a compound node.
3612 * Additionally, any errors encountered when parsing the hook
3613 * definitions or returned by the hook functions.
3615 int snd_config_search_alias_hooks(snd_config_t *config,
3616 const char *base, const char *key,
3617 snd_config_t **result)
3619 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3620 snd_config_searcha_hooks,
3621 snd_config_searchva_hooks);
3624 /** The name of the environment variable containing the files list for #snd_config_update. */
3625 #define ALSA_CONFIG_PATH_VAR "ALSA_CONFIG_PATH"
3629 * \brief Configuration top-level node (the global configuration).
3631 * This variable contains a handle to the top-level configuration node,
3632 * as loaded from global configuration file.
3634 * This variable is initialized or updated by #snd_config_update.
3635 * Functions like #snd_pcm_open (that use a device name from the global
3636 * configuration) automatically call #snd_config_update. Before the
3637 * first call to #snd_config_update, this variable is \c NULL.
3639 * The global configuration files are specified in the environment
3640 * variable \c ALSA_CONFIG_PATH. If this is not set, the default value
3641 * is "/usr/share/alsa/alsa.conf".
3643 * \warning Whenever the configuration tree is updated, all string
3644 * pointers and configuration node handles previously obtained from this
3645 * variable may become invalid.
3647 * \par Conforming to:
3650 snd_config_t *snd_config = NULL;
3660 struct _snd_config_update {
3662 struct finfo *finfo;
3664 #endif /* DOC_HIDDEN */
3666 static snd_config_update_t *snd_config_global_update = NULL;
3668 static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
3671 snd_config_t *c, *func_conf = NULL;
3672 char *buf = NULL, errbuf[256];
3673 const char *lib = NULL, *func_name = NULL;
3675 int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL;
3678 err = snd_config_search(config, "func", &c);
3680 SNDERR("Field func is missing");
3683 err = snd_config_get_string(c, &str);
3685 SNDERR("Invalid type for field func");
3689 err = snd_config_search_definition(root, "hook_func", str, &func_conf);
3691 snd_config_iterator_t i, next;
3692 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
3693 SNDERR("Invalid type for func %s definition", str);
3697 snd_config_for_each(i, next, func_conf) {
3698 snd_config_t *n = snd_config_iterator_entry(i);
3699 const char *id = n->id;
3700 if (strcmp(id, "comment") == 0)
3702 if (strcmp(id, "lib") == 0) {
3703 err = snd_config_get_string(n, &lib);
3705 SNDERR("Invalid type for %s", id);
3710 if (strcmp(id, "func") == 0) {
3711 err = snd_config_get_string(n, &func_name);
3713 SNDERR("Invalid type for %s", id);
3718 SNDERR("Unknown field %s", id);
3722 int len = 16 + strlen(str) + 1;
3728 snprintf(buf, len, "snd_config_hook_%s", str);
3732 h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf));
3733 func = h ? snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_HOOK)) : NULL;
3736 SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
3739 SNDERR("symbol %s is not defined inside %s", func_name, lib);
3745 snd_config_delete(func_conf);
3747 snd_config_t *nroot;
3748 err = func(root, config, &nroot, private_data);
3750 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
3752 if (err >= 0 && nroot)
3753 err = snd_config_substitute(root, nroot);
3761 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
3764 snd_config_iterator_t i, next;
3765 int err, hit, idx = 0;
3767 if ((err = snd_config_search(config, "@hooks", &n)) < 0)
3770 snd_config_remove(n);
3773 snd_config_for_each(i, next, n) {
3774 snd_config_t *n = snd_config_iterator_entry(i);
3775 const char *id = n->id;
3777 err = safe_strtol(id, &i);
3779 SNDERR("id of field %s is not and integer", id);
3784 err = snd_config_hooks_call(config, n, private_data);
3794 snd_config_delete(n);
3795 snd_config_unlock();
3799 static int config_filename_filter(const struct dirent *dirent)
3805 if (dirent->d_type == DT_DIR)
3808 flen = strlen(dirent->d_name);
3812 if (strncmp(&dirent->d_name[flen-5], ".conf", 5) == 0)
3818 static int config_file_open(snd_config_t *root, const char *filename)
3823 err = snd_input_stdio_open(&in, filename, "r");
3825 err = snd_config_load(root, in);
3826 snd_input_close(in);
3828 SNDERR("%s may be old or corrupted: consider to remove or fix it", filename);
3830 SNDERR("cannot access file %s", filename);
3835 static int config_file_load(snd_config_t *root, const char *fn, int errors)
3838 struct dirent **namelist;
3841 if (!errors && access(fn, R_OK) < 0)
3843 if (stat(fn, &st) < 0) {
3844 SNDERR("cannot stat file/directory %s", fn);
3847 if (!S_ISDIR(st.st_mode))
3848 return config_file_open(root, fn);
3850 #if defined(_GNU_SOURCE) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__sun) && !defined(ANDROID)
3851 #define SORTFUNC versionsort
3853 #define SORTFUNC alphasort
3856 n = scandir(fn, &namelist, config_filename_filter, SORTFUNC);
3860 for (j = 0; j < n; ++j) {
3862 int sl = strlen(fn) + strlen(namelist[j]->d_name) + 2;
3863 char *filename = malloc(sl);
3864 snprintf(filename, sl, "%s/%s", fn, namelist[j]->d_name);
3865 filename[sl-1] = '\0';
3867 err = config_file_open(root, filename);
3879 static int config_file_load_user(snd_config_t *root, const char *fn, int errors)
3884 err = snd_user_file(fn, &fn2);
3886 return config_file_load(root, fn, errors);
3887 err = config_file_load(root, fn2, errors);
3893 * \brief Loads and parses the given configurations files.
3894 * \param[in] root Handle to the root configuration node.
3895 * \param[in] config Handle to the configuration node for this hook.
3896 * \param[out] dst The function puts the handle to the configuration
3897 * node loaded from the file(s) at the address specified
3899 * \param[in] private_data Handle to the private data configuration node.
3900 * \return Zero if successful, otherwise a negative error code.
3902 * See \ref confhooks for an example.
3904 int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
3907 snd_config_iterator_t i, next;
3908 int err, idx = 0, errors = 1, hit;
3910 assert(root && dst);
3911 if ((err = snd_config_search(config, "errors", &n)) >= 0) {
3913 err = snd_config_get_ascii(n, &tmp);
3916 errors = snd_config_get_bool_ascii(tmp);
3919 SNDERR("Invalid bool value in field errors");
3923 if ((err = snd_config_search(config, "files", &n)) < 0) {
3924 SNDERR("Unable to find field files in the pre-load section");
3927 if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) {
3928 SNDERR("Unable to expand filenames in the pre-load section");
3931 if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
3932 SNDERR("Invalid type for field filenames");
3937 snd_config_for_each(i, next, n) {
3938 snd_config_t *n = snd_config_iterator_entry(i);
3939 const char *id = n->id;
3941 err = safe_strtol(id, &i);
3943 SNDERR("id of field %s is not and integer", id);
3948 char *name, *name2, *remain;
3949 if ((err = snd_config_get_ascii(n, &name)) < 0)
3952 remain = strstr(name, "|||");
3958 err = config_file_load_user(root, name2, errors);
3961 if (err == 0) /* first hit wins */
3966 remain = strstr(remain, "|||");
3977 snd_config_delete(n);
3981 SND_DLSYM_BUILD_VERSION(snd_config_hook_load, SND_CONFIG_DLSYM_VERSION_HOOK);
3985 int snd_determine_driver(int card, char **driver);
3989 * \brief Loads and parses the given configurations files for each
3990 * installed sound card.
3991 * \param[in] root Handle to the root configuration node.
3992 * \param[in] config Handle to the configuration node for this hook.
3993 * \param[out] dst The function puts the handle to the configuration
3994 * node loaded from the file(s) at the address specified
3996 * \param[in] private_data Handle to the private data configuration node.
3997 * \return Zero if successful, otherwise a negative error code.
3999 * This function works like #snd_config_hook_load, but the files are
4000 * loaded once for each sound card. The driver name is available with
4001 * the \c private_string function to customize the file name.
4003 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)
4008 err = snd_card_next(&card);
4012 snd_config_t *n, *v, *private_data = NULL;
4014 char *fdriver = NULL;
4015 err = snd_determine_driver(card, &fdriver);
4018 if (snd_config_search(root, fdriver, &n) >= 0) {
4019 if (snd_config_get_string(n, &driver) < 0)
4023 char *s = strchr(driver, '.');
4028 if (snd_config_search(root, driver, &n) >= 0)
4033 err = snd_config_make_compound(&private_data, NULL, 0);
4036 err = snd_config_imake_integer(&v, "integer", card);
4039 err = snd_config_add(private_data, v);
4041 snd_config_delete(v);
4044 err = snd_config_imake_string(&v, "string", driver);
4047 err = snd_config_add(private_data, v);
4049 snd_config_delete(v);
4052 err = snd_config_hook_load(root, config, &n, private_data);
4055 snd_config_delete(private_data);
4060 } while (card >= 0);
4065 SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK);
4069 * \brief Updates a configuration tree by rereading the configuration files (if needed).
4070 * \param[in,out] _top Address of the handle to the top-level node.
4071 * \param[in,out] _update Address of a pointer to private update information.
4072 * \param[in] cfgs A list of configuration file names, delimited with ':'.
4073 * If \p cfgs is \c NULL, the default global
4074 * configuration file is used.
4075 * \return 0 if \a _top was up to date, 1 if the configuration files
4076 * have been reread, otherwise a negative error code.
4078 * The variables pointed to by \a _top and \a _update can be initialized
4079 * to \c NULL before the first call to this function. The private
4080 * update information holds information about all used configuration
4081 * files that allows this function to detects changes to them; this data
4082 * can be freed with #snd_config_update_free.
4084 * The global configuration files are specified in the environment variable
4085 * \c ALSA_CONFIG_PATH.
4087 * \warning If the configuration tree is reread, all string pointers and
4088 * configuration node handles previously obtained from this tree become
4092 * Any errors encountered when parsing the input or returned by hooks or
4095 int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs)
4098 const char *configs, *c;
4101 snd_config_update_t *local;
4102 snd_config_update_t *update;
4105 assert(_top && _update);
4110 configs = getenv(ALSA_CONFIG_PATH_VAR);
4111 if (!configs || !*configs) {
4112 const char *topdir = snd_config_topdir();
4113 char *s = alloca(strlen(topdir) +
4114 strlen("alsa.conf") + 2);
4115 sprintf(s, "%s/alsa.conf", topdir);
4119 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
4130 local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t));
4134 local->finfo = calloc(local->count, sizeof(struct finfo));
4135 if (!local->finfo) {
4139 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
4143 err = snd_user_file(name, &local->finfo[k].name);
4152 for (k = 0; k < local->count; ++k) {
4154 struct finfo *lf = &local->finfo[k];
4155 if (stat(lf->name, &st) >= 0) {
4156 lf->dev = st.st_dev;
4157 lf->ino = st.st_ino;
4158 lf->mtime = st.st_mtime;
4160 SNDERR("Cannot access file %s", lf->name);
4162 memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1));
4169 if (local->count != update->count)
4171 for (k = 0; k < local->count; ++k) {
4172 struct finfo *lf = &local->finfo[k];
4173 struct finfo *uf = &update->finfo[k];
4174 if (strcmp(lf->name, uf->name) != 0 ||
4175 lf->dev != uf->dev ||
4176 lf->ino != uf->ino ||
4177 lf->mtime != uf->mtime)
4185 snd_config_delete(top);
4189 snd_config_update_free(update);
4194 snd_config_update_free(local);
4201 snd_config_update_free(update);
4205 snd_config_delete(top);
4208 err = snd_config_top(&top);
4213 for (k = 0; k < local->count; ++k) {
4215 err = snd_input_stdio_open(&in, local->finfo[k].name, "r");
4217 err = snd_config_load(top, in);
4218 snd_input_close(in);
4220 SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name);
4224 SNDERR("cannot access file %s", local->finfo[k].name);
4228 err = snd_config_hooks(top, NULL);
4230 SNDERR("hooks failed, removing configuration");
4239 * \brief Updates #snd_config by rereading the global configuration files (if needed).
4240 * \return 0 if #snd_config was up to date, 1 if #snd_config was
4241 * updated, otherwise a negative error code.
4243 * \warning Whenever #snd_config is updated, all string pointers and
4244 * configuration node handles previously obtained from it may become
4246 * For safer operations, use #snd_config_update_ref and release the config
4247 * via #snd_config_unref.
4250 * Any errors encountered when parsing the input or returned by hooks or
4253 * \par Conforming to:
4256 int snd_config_update(void)
4261 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
4262 snd_config_unlock();
4267 * \brief Updates #snd_config and takes its reference.
4268 * \return 0 if #snd_config was up to date, 1 if #snd_config was
4269 * updated, otherwise a negative error code.
4271 * Unlike #snd_config_update, this function increases a reference counter
4272 * so that the obtained tree won't be deleted until unreferenced by
4273 * #snd_config_unref.
4275 * This function is supposed to be thread-safe.
4277 int snd_config_update_ref(snd_config_t **top)
4284 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
4288 snd_config->refcount++;
4295 snd_config_unlock();
4300 * \brief Take the reference of the config tree.
4302 * Increases a reference counter of the given config tree.
4304 * This function is supposed to be thread-safe.
4306 void snd_config_ref(snd_config_t *cfg)
4311 snd_config_unlock();
4315 * \brief Unreference the config tree.
4317 * Decreases a reference counter of the given config tree, and eventually
4318 * deletes the tree if all references are gone. This is the counterpart of
4319 * #snd_config_unref.
4321 * Also, the config taken via #snd_config_update_ref must be unreferenced
4322 * by this function, too.
4324 * This function is supposed to be thread-safe.
4326 void snd_config_unref(snd_config_t *cfg)
4330 snd_config_delete(cfg);
4331 snd_config_unlock();
4335 * \brief Frees a private update structure.
4336 * \param[in] update The private update structure to free.
4337 * \return Zero if successful, otherwise a negative error code.
4339 int snd_config_update_free(snd_config_update_t *update)
4344 for (k = 0; k < update->count; k++)
4345 free(update->finfo[k].name);
4346 free(update->finfo);
4352 * \brief Frees the global configuration tree in #snd_config.
4353 * \return Zero if successful, otherwise a negative error code.
4355 * This functions releases all resources of the global configuration
4356 * tree, and sets #snd_config to \c NULL.
4358 * \par Conforming to:
4361 int snd_config_update_free_global(void)
4365 snd_config_delete(snd_config);
4367 if (snd_config_global_update)
4368 snd_config_update_free(snd_config_global_update);
4369 snd_config_global_update = NULL;
4370 snd_config_unlock();
4371 /* FIXME: better to place this in another place... */
4372 snd_dlobj_cache_cleanup();
4378 * \brief Returns an iterator pointing to a node's first child.
4379 * \param[in] config Handle to a configuration node.
4380 * \return An iterator pointing to \a config's first child.
4382 * \a config must be a compound node.
4384 * The returned iterator is valid if it is not equal to the return value
4385 * of #snd_config_iterator_end on \a config.
4387 * Use #snd_config_iterator_entry to get the handle of the node pointed
4390 * \par Conforming to:
4393 snd_config_iterator_t snd_config_iterator_first(const snd_config_t *config)
4395 assert(config->type == SND_CONFIG_TYPE_COMPOUND);
4396 return config->u.compound.fields.next;
4400 * \brief Returns an iterator pointing to the next sibling.
4401 * \param[in] iterator An iterator pointing to a child configuration node.
4402 * \return An iterator pointing to the next sibling of \a iterator.
4404 * The returned iterator is valid if it is not equal to the return value
4405 * of #snd_config_iterator_end on the node's parent.
4407 * Use #snd_config_iterator_entry to get the handle of the node pointed
4410 * \par Conforming to:
4413 snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator)
4415 return iterator->next;
4419 * \brief Returns an iterator that ends a node's children list.
4420 * \param[in] config Handle to a configuration node.
4421 * \return An iterator that indicates the end of \a config's children list.
4423 * \a config must be a compound node.
4425 * The return value can be understood as pointing past the last child of
4428 * \par Conforming to:
4431 snd_config_iterator_t snd_config_iterator_end(const snd_config_t *config)
4433 assert(config->type == SND_CONFIG_TYPE_COMPOUND);
4434 return (const snd_config_iterator_t)&config->u.compound.fields;
4438 * \brief Returns the configuration node handle pointed to by an iterator.
4439 * \param[in] iterator A configuration node iterator.
4440 * \return The configuration node handle pointed to by \a iterator.
4442 * \par Conforming to:
4445 snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator)
4447 return list_entry(iterator, snd_config_t, list);
4451 typedef enum _snd_config_walk_pass {
4452 SND_CONFIG_WALK_PASS_PRE,
4453 SND_CONFIG_WALK_PASS_POST,
4454 SND_CONFIG_WALK_PASS_LEAF,
4455 } snd_config_walk_pass_t;
4458 /* Return 1 if node needs to be attached to parent */
4459 /* Return 2 if compound is replaced with standard node */
4461 typedef int (*snd_config_walk_callback_t)(snd_config_t *src,
4464 snd_config_walk_pass_t pass,
4465 snd_config_t *private_data);
4468 static int snd_config_walk(snd_config_t *src,
4471 snd_config_walk_callback_t callback,
4472 snd_config_t *private_data)
4475 snd_config_iterator_t i, next;
4477 switch (snd_config_get_type(src)) {
4478 case SND_CONFIG_TYPE_COMPOUND:
4479 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, private_data);
4482 snd_config_for_each(i, next, src) {
4483 snd_config_t *s = snd_config_iterator_entry(i);
4484 snd_config_t *d = NULL;
4486 err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL,
4487 callback, private_data);
4491 err = snd_config_add(*dst, d);
4496 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, private_data);
4500 snd_config_delete(*dst);
4504 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, private_data);
4510 static int _snd_config_copy(snd_config_t *src,
4511 snd_config_t *root ATTRIBUTE_UNUSED,
4513 snd_config_walk_pass_t pass,
4514 snd_config_t *private_data ATTRIBUTE_UNUSED)
4517 const char *id = src->id;
4518 snd_config_type_t type = snd_config_get_type(src);
4520 case SND_CONFIG_WALK_PASS_PRE:
4521 err = snd_config_make_compound(dst, id, src->u.compound.join);
4525 case SND_CONFIG_WALK_PASS_LEAF:
4526 err = snd_config_make(dst, id, type);
4530 case SND_CONFIG_TYPE_INTEGER:
4533 err = snd_config_get_integer(src, &v);
4535 snd_config_set_integer(*dst, v);
4538 case SND_CONFIG_TYPE_INTEGER64:
4541 err = snd_config_get_integer64(src, &v);
4543 snd_config_set_integer64(*dst, v);
4546 case SND_CONFIG_TYPE_REAL:
4549 err = snd_config_get_real(src, &v);
4551 snd_config_set_real(*dst, v);
4554 case SND_CONFIG_TYPE_STRING:
4557 err = snd_config_get_string(src, &s);
4559 err = snd_config_set_string(*dst, s);
4575 * \brief Creates a copy of a configuration node.
4576 * \param[out] dst The function puts the handle to the new configuration
4577 * node at the address specified by \a dst.
4578 * \param[in] src Handle to the source configuration node.
4579 * \return A non-negative value if successful, otherwise a negative error code.
4581 * This function creates a deep copy, i.e., if \a src is a compound
4582 * node, all children are copied recursively.
4586 * <dt>-ENOMEM<dd>Out of memory.
4589 * \par Conforming to:
4592 int snd_config_copy(snd_config_t **dst,
4595 return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL);
4598 static int _snd_config_expand(snd_config_t *src,
4599 snd_config_t *root ATTRIBUTE_UNUSED,
4601 snd_config_walk_pass_t pass,
4602 snd_config_t *private_data)
4605 const char *id = src->id;
4606 snd_config_type_t type = snd_config_get_type(src);
4608 case SND_CONFIG_WALK_PASS_PRE:
4610 if (id && strcmp(id, "@args") == 0)
4612 err = snd_config_make_compound(dst, id, src->u.compound.join);
4617 case SND_CONFIG_WALK_PASS_LEAF:
4619 case SND_CONFIG_TYPE_INTEGER:
4622 err = snd_config_get_integer(src, &v);
4624 err = snd_config_imake_integer(dst, id, v);
4629 case SND_CONFIG_TYPE_INTEGER64:
4632 err = snd_config_get_integer64(src, &v);
4634 err = snd_config_imake_integer64(dst, id, v);
4639 case SND_CONFIG_TYPE_REAL:
4642 err = snd_config_get_real(src, &v);
4644 err = snd_config_imake_real(dst, id, v);
4649 case SND_CONFIG_TYPE_STRING:
4653 snd_config_t *vars = private_data;
4654 snd_config_get_string(src, &s);
4655 if (s && *s == '$') {
4657 if (snd_config_search(vars, s, &val) < 0)
4659 err = snd_config_copy(dst, val);
4662 err = snd_config_set_id(*dst, id);
4664 snd_config_delete(*dst);
4668 err = snd_config_imake_string(dst, id, s);
4684 static int _snd_config_evaluate(snd_config_t *src,
4686 snd_config_t **dst ATTRIBUTE_UNUSED,
4687 snd_config_walk_pass_t pass,
4688 snd_config_t *private_data)
4691 if (pass == SND_CONFIG_WALK_PASS_PRE) {
4692 char *buf = NULL, errbuf[256];
4693 const char *lib = NULL, *func_name = NULL;
4695 int (*func)(snd_config_t **dst, snd_config_t *root,
4696 snd_config_t *src, snd_config_t *private_data) = NULL;
4698 snd_config_t *c, *func_conf = NULL;
4699 err = snd_config_search(src, "@func", &c);
4702 err = snd_config_get_string(c, &str);
4704 SNDERR("Invalid type for @func");
4708 err = snd_config_search_definition(root, "func", str, &func_conf);
4710 snd_config_iterator_t i, next;
4711 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
4712 SNDERR("Invalid type for func %s definition", str);
4716 snd_config_for_each(i, next, func_conf) {
4717 snd_config_t *n = snd_config_iterator_entry(i);
4718 const char *id = n->id;
4719 if (strcmp(id, "comment") == 0)
4721 if (strcmp(id, "lib") == 0) {
4722 err = snd_config_get_string(n, &lib);
4724 SNDERR("Invalid type for %s", id);
4729 if (strcmp(id, "func") == 0) {
4730 err = snd_config_get_string(n, &func_name);
4732 SNDERR("Invalid type for %s", id);
4737 SNDERR("Unknown field %s", id);
4741 int len = 9 + strlen(str) + 1;
4747 snprintf(buf, len, "snd_func_%s", str);
4751 h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf));
4753 func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE));
4756 SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
4760 SNDERR("symbol %s is not defined inside %s", func_name, lib);
4767 snd_config_delete(func_conf);
4770 err = func(&eval, root, src, private_data);
4772 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
4774 if (err >= 0 && eval) {
4775 /* substitute merges compound members */
4776 /* we don't want merging at all */
4777 err = snd_config_delete_compound_members(src);
4779 err = snd_config_substitute(src, eval);
4792 * \brief Evaluates a configuration node at runtime.
4793 * \param[in,out] config Handle to the source configuration node.
4794 * \param[in] root Handle to the root of the source configuration.
4795 * \param[in] private_data Handle to the private data node for runtime evaluation.
4796 * \param result Must be \c NULL.
4797 * \return A non-negative value if successful, otherwise a negative error code.
4799 * This function evaluates any functions (\c \@func) in \a config and
4800 * replaces those nodes with the respective function results.
4802 int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
4803 snd_config_t *private_data, snd_config_t **result)
4805 /* FIXME: Only in place evaluation is currently implemented */
4806 assert(result == NULL);
4807 return snd_config_walk(config, root, result, _snd_config_evaluate, private_data);
4810 static int load_defaults(snd_config_t *subs, snd_config_t *defs)
4812 snd_config_iterator_t d, dnext;
4813 snd_config_for_each(d, dnext, defs) {
4814 snd_config_t *def = snd_config_iterator_entry(d);
4815 snd_config_iterator_t f, fnext;
4816 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND)
4818 snd_config_for_each(f, fnext, def) {
4819 snd_config_t *fld = snd_config_iterator_entry(f);
4820 const char *id = fld->id;
4821 if (strcmp(id, "type") == 0)
4823 if (strcmp(id, "default") == 0) {
4824 snd_config_t *deflt;
4826 err = snd_config_copy(&deflt, fld);
4829 err = snd_config_set_id(deflt, def->id);
4831 snd_config_delete(deflt);
4834 err = snd_config_add(subs, deflt);
4836 snd_config_delete(deflt);
4841 SNDERR("Unknown field %s", id);
4848 static void skip_blank(const char **ptr)
4865 static int parse_char(const char **ptr)
4868 assert(**ptr == '\\');
4890 case '0': case '1': case '2': case '3':
4891 case '4': case '5': case '6': case '7':
4898 if (c < '0' || c > '7')
4900 num = num * 8 + c - '0';
4913 static int parse_id(const char **ptr)
4934 static int parse_string(const char **ptr, char **val)
4936 const size_t bufsize = 256;
4939 size_t alloc = bufsize;
4947 SNDERR("Unterminated string");
4950 c = parse_char(ptr);
4952 if (alloc > bufsize)
4960 *val = malloc(idx + 1);
4963 memcpy(*val, buf, idx);
4965 if (alloc > bufsize)
4971 size_t old_alloc = alloc;
4973 if (old_alloc == bufsize) {
4974 buf = malloc(alloc);
4977 memcpy(buf, _buf, old_alloc);
4979 char *buf2 = realloc(buf, alloc);
4992 /* Parse var=val or val */
4993 static int parse_arg(const char **ptr, unsigned int *varlen, char **val)
4999 if (*str == '"' || *str == '\'') {
5000 err = parse_string(ptr, val);
5006 err = parse_id(ptr);
5009 vallen = *ptr - str;
5019 if (*str == '"' || *str == '\'') {
5020 err = parse_string(ptr, val);
5025 err = parse_id(ptr);
5028 vallen = *ptr - str;
5030 *val = malloc(vallen + 1);
5033 memcpy(*val, str, vallen);
5040 * var1=val1,var2=val2,...
5043 static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
5053 int len = strlen(str);
5055 snd_config_iterator_t i, next;
5057 switch (str[--len]) {
5069 if (str[len] != '}')
5071 err = snd_input_buffer_open(&input, str + 1, len - 1);
5074 err = snd_config_load_override(subs, input);
5075 snd_input_close(input);
5078 snd_config_for_each(i, next, subs) {
5079 snd_config_t *n = snd_config_iterator_entry(i);
5081 const char *id = n->id;
5082 err = snd_config_search(defs, id, &d);
5084 SNDERR("Unknown parameter %s", id);
5093 const char *var = buf;
5094 unsigned int varlen;
5095 snd_config_t *def, *sub, *typ;
5096 const char *new = str;
5101 err = parse_arg(&new, &varlen, &val);
5105 assert(varlen < sizeof(buf));
5106 memcpy(buf, str, varlen);
5109 sprintf(buf, "%d", arg);
5111 err = snd_config_search_alias(defs, NULL, var, &def);
5113 SNDERR("Unknown parameter %s", var);
5116 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) {
5117 SNDERR("Parameter %s definition is not correct", var);
5122 err = snd_config_search(subs, var, &sub);
5124 snd_config_delete(sub);
5126 err = snd_config_search(def, "type", &typ);
5129 SNDERR("Parameter %s definition is missing a valid type info", var);
5132 err = snd_config_get_string(typ, &tmp);
5133 if (err < 0 || !tmp)
5135 if (strcmp(tmp, "integer") == 0) {
5137 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER);
5140 err = safe_strtol(val, &v);
5142 SNDERR("Parameter %s must be an integer", var);
5145 err = snd_config_set_integer(sub, v);
5148 } else if (strcmp(tmp, "integer64") == 0) {
5150 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER64);
5153 err = safe_strtoll(val, &v);
5155 SNDERR("Parameter %s must be an integer", var);
5158 err = snd_config_set_integer64(sub, v);
5161 } else if (strcmp(tmp, "real") == 0) {
5163 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_REAL);
5166 err = safe_strtod(val, &v);
5168 SNDERR("Parameter %s must be a real", var);
5171 err = snd_config_set_real(sub, v);
5174 } else if (strcmp(tmp, "string") == 0) {
5175 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_STRING);
5178 err = snd_config_set_string(sub, val);
5185 err = snd_config_set_id(sub, var);
5188 err = snd_config_add(subs, sub);
5192 snd_config_delete(sub);
5208 * \brief Expands a configuration node, applying arguments and functions.
5209 * \param[in] config Handle to the configuration node.
5210 * \param[in] root Handle to the root configuration node.
5211 * \param[in] args Arguments string, can be \c NULL.
5212 * \param[in] private_data Handle to the private data node for functions.
5213 * \param[out] result The function puts the handle to the result
5214 * configuration node at the address specified by
5216 * \return A non-negative value if successful, otherwise a negative error code.
5218 * If \a config has arguments (defined by a child with id \c \@args),
5219 * this function replaces any string node beginning with $ with the
5220 * respective argument value, or the default argument value, or nothing.
5221 * Furthermore, any functions are evaluated (see #snd_config_evaluate).
5222 * The resulting copy of \a config is returned in \a result.
5224 int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args,
5225 snd_config_t *private_data, snd_config_t **result)
5228 snd_config_t *defs, *subs = NULL, *res;
5229 err = snd_config_search(config, "@args", &defs);
5232 SNDERR("Unknown parameters %s", args);
5235 err = snd_config_copy(&res, config);
5239 err = snd_config_top(&subs);
5242 err = load_defaults(subs, defs);
5244 SNDERR("Load defaults error: %s", snd_strerror(err));
5247 err = parse_args(subs, args, defs);
5249 SNDERR("Parse arguments error: %s", snd_strerror(err));
5252 err = snd_config_evaluate(subs, root, private_data, NULL);
5254 SNDERR("Args evaluate error: %s", snd_strerror(err));
5257 err = snd_config_walk(config, root, &res, _snd_config_expand, subs);
5259 SNDERR("Expand error (walk): %s", snd_strerror(err));
5263 err = snd_config_evaluate(res, root, private_data, NULL);
5265 SNDERR("Evaluate error: %s", snd_strerror(err));
5266 snd_config_delete(res);
5273 snd_config_delete(subs);
5278 * \brief Searches for a definition in a configuration tree, using
5279 * aliases and expanding hooks and arguments.
5280 * \param[in] config Handle to the configuration (sub)tree to search.
5281 * \param[in] base Implicit key base, or \c NULL for none.
5282 * \param[in] name Key suffix, optionally with arguments.
5283 * \param[out] result The function puts the handle to the expanded found
5284 * node at the address specified by \a result.
5285 * \return A non-negative value if successful, otherwise a negative error code.
5287 * This functions searches for a child node of \a config, allowing
5288 * aliases and expanding hooks, like #snd_config_search_alias_hooks.
5290 * If \a name contains a colon (:), the rest of the string after the
5291 * colon contains arguments that are expanded as with
5292 * #snd_config_expand.
5294 * In any case, \a result is a new node that must be freed by the
5299 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
5300 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
5301 * not a compound node.
5303 * Additionally, any errors encountered when parsing the hook
5304 * definitions or arguments, or returned by (hook) functions.
5306 int snd_config_search_definition(snd_config_t *config,
5307 const char *base, const char *name,
5308 snd_config_t **result)
5312 const char *args = strchr(name, ':');
5316 key = alloca(args - name);
5317 memcpy(key, name, args - name - 1);
5318 key[args - name - 1] = '\0';
5320 key = (char *) name;
5323 * if key contains dot (.), the implicit base is ignored
5324 * and the key starts from root given by the 'config' parameter
5327 err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf);
5329 snd_config_unlock();
5332 err = snd_config_expand(conf, config, args, NULL, result);
5333 snd_config_unlock();
5338 void snd_config_set_hop(snd_config_t *conf, int hop)
5343 int snd_config_check_hop(snd_config_t *conf)
5346 if (conf->hop >= SND_CONF_MAX_HOPS) {
5347 SYSERR("Too many definition levels (looped?)\n");
5357 /* Not strictly needed, but useful to check for memory leaks */
5358 void _snd_config_end(void) __attribute__ ((destructor));
5360 static void _snd_config_end(void)
5364 snd_config_delete(snd_config);
5366 for (k = 0; k < files_info_count; ++k)
5367 free(files_info[k].name);
5370 files_info_count = 0;
5374 size_t page_size(void)
5376 long s = sysconf(_SC_PAGE_SIZE);
5381 size_t page_align(size_t size)
5384 long psz = page_size();
5387 return size + psz - r;
5391 size_t page_ptr(size_t object_offset, size_t object_size, size_t *offset, size_t *mmap_offset)
5394 long psz = page_size();
5396 assert(mmap_offset);
5397 *mmap_offset = object_offset;
5398 object_offset %= psz;
5399 *mmap_offset -= object_offset;
5400 object_size += object_offset;
5401 r = object_size % psz;
5403 r = object_size + psz - r;
5406 *offset = object_offset;