X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/e385d93e5aad6a6fce754c00c804ff1d6a6746d4..6f396c89ab48c4897ebbcb846c5914b06a8225fb:/src/pulsecore/conf-parser.c diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index db1e3719..b4ab23cc 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -1,11 +1,11 @@ -/* $Id$ */ - /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but @@ -23,7 +23,6 @@ #include #endif -#include #include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include #include "conf-parser.h" @@ -40,26 +40,47 @@ #define COMMENTS "#;\n" /* Run the user supplied parser for an assignment */ -static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { - assert(filename && t && lvalue && rvalue); - - for (; t->parse; t++) - if (!strcmp(lvalue, t->lvalue)) - return t->parse(filename, line, lvalue, rvalue, t->data, userdata); - - pa_log("[%s:%u] Unknown lvalue '%s'.", filename, line, lvalue); - +static int next_assignment( + const char *filename, + unsigned line, + const char *section, + const pa_config_item *t, + const char *lvalue, + const char *rvalue, + void *userdata) { + + pa_assert(filename); + pa_assert(t); + pa_assert(lvalue); + pa_assert(rvalue); + + for (; t->parse; t++) { + + if (t->lvalue && !pa_streq(lvalue, t->lvalue)) + continue; + + if (t->section && !section) + continue; + + if (t->section && !pa_streq(section, t->section)) + continue; + + return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata); + } + + pa_log("[%s:%u] Unknown lvalue '%s' in section '%s'.", filename, line, lvalue, pa_strna(section)); + return -1; } /* Returns non-zero when c is contained in s */ static int in_string(char c, const char *s) { - assert(s); - + pa_assert(s); + for (; *s; s++) if (*s == c) return 1; - + return 0; } @@ -80,15 +101,52 @@ static char *strip(char *s) { } /* Parse a variable assignment line */ -static int parse_line(const char *filename, unsigned line, const pa_config_item *t, char *l, void *userdata) { - char *e, *c, *b = l+strspn(l, WHITESPACE); +static int parse_line(const char *filename, unsigned line, char **section, const pa_config_item *t, char *l, void *userdata) { + char *e, *c, *b; + + b = l+strspn(l, WHITESPACE); if ((c = strpbrk(b, COMMENTS))) *c = 0; - + if (!*b) return 0; + if (pa_startswith(b, ".include ")) { + char *path, *fn; + int r; + + fn = strip(b+9); + if (!pa_is_path_absolute(fn)) { + const char *k; + if ((k = strrchr(filename, '/'))) { + char *dir = pa_xstrndup(filename, k-filename); + fn = path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", dir, fn); + pa_xfree(dir); + } + } + + r = pa_config_parse(fn, NULL, t, userdata); + pa_xfree(path); + return r; + } + + if (*b == '[') { + size_t k; + + k = strlen(b); + pa_assert(k > 0); + + if (b[k-1] != ']') { + pa_log("[%s:%u] Invalid section header.", filename, line); + return -1; + } + + pa_xfree(*section); + *section = pa_xstrndup(b+1, k-2); + return 0; + } + if (!(e = strchr(b, '='))) { pa_log("[%s:%u] Missing '='.", filename, line); return -1; @@ -97,83 +155,160 @@ static int parse_line(const char *filename, unsigned line, const pa_config_item *e = 0; e++; - return next_assignment(filename, line, t, strip(b), strip(e), userdata); + return next_assignment(filename, line, *section, t, strip(b), strip(e), userdata); } /* Go through the file and parse each line */ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata) { int r = -1; unsigned line = 0; - int do_close = !f; - assert(filename && t); - + pa_bool_t do_close = !f; + char *section = NULL; + + pa_assert(filename); + pa_assert(t); + if (!f && !(f = fopen(filename, "r"))) { if (errno == ENOENT) { + pa_log_debug("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); r = 0; goto finish; } - - pa_log_warn("WARNING: failed to open configuration file '%s': %s", - filename, pa_cstrerror(errno)); + + pa_log_warn("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } while (!feof(f)) { - char l[256]; + char l[4096]; + if (!fgets(l, sizeof(l), f)) { if (feof(f)) break; - - pa_log_warn("WARNING: failed to read configuration file '%s': %s", - filename, pa_cstrerror(errno)); + + pa_log_warn("Failed to read configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } - - if (parse_line(filename, ++line, t, l, userdata) < 0) + + if (parse_line(filename, ++line, §ion, t, l, userdata) < 0) goto finish; } - + r = 0; - + finish: + pa_xfree(section); if (do_close && f) fclose(f); - + return r; } -int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +int pa_config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { int *i = data; int32_t k; - assert(filename && lvalue && rvalue && data); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); if (pa_atoi(rvalue, &k) < 0) { pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); return -1; } - + *i = (int) k; - return 0; + return 0; } -int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { - int *b = data, k; - assert(filename && lvalue && rvalue && data); - +int pa_config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { + unsigned *u = data; + uint32_t k; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atou(rvalue, &k) < 0) { + pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); + return -1; + } + + *u = (unsigned) k; + return 0; +} + +int pa_config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { + size_t *i = data; + uint32_t k; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atou(rvalue, &k) < 0) { + pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); + return -1; + } + + *i = (size_t) k; + return 0; +} + +int pa_config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { + int k; + pa_bool_t *b = data; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if ((k = pa_parse_boolean(rvalue)) < 0) { + pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue); + return -1; + } + + *b = !!k; + + return 0; +} + +int pa_config_parse_not_bool( + const char *filename, unsigned line, + const char *section, + const char *lvalue, const char *rvalue, + void *data, void *userdata) { + + int k; + pa_bool_t *b = data; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + if ((k = pa_parse_boolean(rvalue)) < 0) { pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue); return -1; } - - *b = k; - + + *b = !k; + return 0; } -int pa_config_parse_string(const char *filename, PA_GCC_UNUSED unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { +int pa_config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { char **s = data; - assert(filename && lvalue && rvalue && data); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); pa_xfree(*s); *s = *rvalue ? pa_xstrdup(rvalue) : NULL;