]> code.delx.au - pulseaudio/blob - src/pulsecore/conf-parser.c
12efbd2c43c14c9ab58ed7d5c08091eb23f460e5
[pulseaudio] / src / pulsecore / conf-parser.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <assert.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <errno.h>
32
33 #include <pulse/xmalloc.h>
34
35 #include <pulsecore/core-error.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/core-util.h>
38
39 #include "conf-parser.h"
40
41 #define WHITESPACE " \t\n"
42 #define COMMENTS "#;\n"
43
44 /* Run the user supplied parser for an assignment */
45 static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) {
46 assert(filename && t && lvalue && rvalue);
47
48 for (; t->parse; t++)
49 if (!strcmp(lvalue, t->lvalue))
50 return t->parse(filename, line, lvalue, rvalue, t->data, userdata);
51
52 pa_log("[%s:%u] Unknown lvalue '%s'.", filename, line, lvalue);
53
54 return -1;
55 }
56
57 /* Returns non-zero when c is contained in s */
58 static int in_string(char c, const char *s) {
59 assert(s);
60
61 for (; *s; s++)
62 if (*s == c)
63 return 1;
64
65 return 0;
66 }
67
68 /* Remove all whitepsapce from the beginning and the end of *s. *s may
69 * be modified. */
70 static char *strip(char *s) {
71 char *b = s+strspn(s, WHITESPACE);
72 char *e, *l = NULL;
73
74 for (e = b; *e; e++)
75 if (!in_string(*e, WHITESPACE))
76 l = e;
77
78 if (l)
79 *(l+1) = 0;
80
81 return b;
82 }
83
84 /* Parse a variable assignment line */
85 static int parse_line(const char *filename, unsigned line, const pa_config_item *t, char *l, void *userdata) {
86 char *e, *c, *b = l+strspn(l, WHITESPACE);
87
88 if ((c = strpbrk(b, COMMENTS)))
89 *c = 0;
90
91 if (!*b)
92 return 0;
93
94 if (!(e = strchr(b, '='))) {
95 pa_log("[%s:%u] Missing '='.", filename, line);
96 return -1;
97 }
98
99 *e = 0;
100 e++;
101
102 return next_assignment(filename, line, t, strip(b), strip(e), userdata);
103 }
104
105 /* Go through the file and parse each line */
106 int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata) {
107 int r = -1;
108 unsigned line = 0;
109 int do_close = !f;
110 assert(filename && t);
111
112 if (!f && !(f = fopen(filename, "r"))) {
113 if (errno == ENOENT) {
114 r = 0;
115 goto finish;
116 }
117
118 pa_log_warn("WARNING: failed to open configuration file '%s': %s",
119 filename, pa_cstrerror(errno));
120 goto finish;
121 }
122
123 while (!feof(f)) {
124 char l[256];
125 if (!fgets(l, sizeof(l), f)) {
126 if (feof(f))
127 break;
128
129 pa_log_warn("WARNING: failed to read configuration file '%s': %s",
130 filename, pa_cstrerror(errno));
131 goto finish;
132 }
133
134 if (parse_line(filename, ++line, t, l, userdata) < 0)
135 goto finish;
136 }
137
138 r = 0;
139
140 finish:
141
142 if (do_close && f)
143 fclose(f);
144
145 return r;
146 }
147
148 int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
149 int *i = data;
150 int32_t k;
151 assert(filename && lvalue && rvalue && data);
152
153 if (pa_atoi(rvalue, &k) < 0) {
154 pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
155 return -1;
156 }
157
158 *i = (int) k;
159 return 0;
160 }
161
162 int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
163 int *b = data, k;
164 assert(filename && lvalue && rvalue && data);
165
166 if ((k = pa_parse_boolean(rvalue)) < 0) {
167 pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue);
168 return -1;
169 }
170
171 *b = k;
172
173 return 0;
174 }
175
176 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) {
177 char **s = data;
178 assert(filename && lvalue && rvalue && data);
179
180 pa_xfree(*s);
181 *s = *rvalue ? pa_xstrdup(rvalue) : NULL;
182 return 0;
183 }