]> code.delx.au - pulseaudio/blob - src/pulsecore/conf-parser.c
merge 'lennart' branch back into trunk.
[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 <string.h>
29 #include <stdio.h>
30 #include <errno.h>
31
32 #include <pulse/xmalloc.h>
33
34 #include <pulsecore/core-error.h>
35 #include <pulsecore/log.h>
36 #include <pulsecore/core-util.h>
37 #include <pulsecore/macro.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 pa_assert(filename);
47 pa_assert(t);
48 pa_assert(lvalue);
49 pa_assert(rvalue);
50
51 for (; t->parse; t++)
52 if (!strcmp(lvalue, t->lvalue))
53 return t->parse(filename, line, lvalue, rvalue, t->data, userdata);
54
55 pa_log("[%s:%u] Unknown lvalue '%s'.", filename, line, lvalue);
56
57 return -1;
58 }
59
60 /* Returns non-zero when c is contained in s */
61 static int in_string(char c, const char *s) {
62 pa_assert(s);
63
64 for (; *s; s++)
65 if (*s == c)
66 return 1;
67
68 return 0;
69 }
70
71 /* Remove all whitepsapce from the beginning and the end of *s. *s may
72 * be modified. */
73 static char *strip(char *s) {
74 char *b = s+strspn(s, WHITESPACE);
75 char *e, *l = NULL;
76
77 for (e = b; *e; e++)
78 if (!in_string(*e, WHITESPACE))
79 l = e;
80
81 if (l)
82 *(l+1) = 0;
83
84 return b;
85 }
86
87 /* Parse a variable assignment line */
88 static int parse_line(const char *filename, unsigned line, const pa_config_item *t, char *l, void *userdata) {
89 char *e, *c, *b = l+strspn(l, WHITESPACE);
90
91 if ((c = strpbrk(b, COMMENTS)))
92 *c = 0;
93
94 if (!*b)
95 return 0;
96
97 if (!(e = strchr(b, '='))) {
98 pa_log("[%s:%u] Missing '='.", filename, line);
99 return -1;
100 }
101
102 *e = 0;
103 e++;
104
105 return next_assignment(filename, line, t, strip(b), strip(e), userdata);
106 }
107
108 /* Go through the file and parse each line */
109 int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata) {
110 int r = -1;
111 unsigned line = 0;
112 int do_close = !f;
113
114 pa_assert(filename);
115 pa_assert(t);
116
117 if (!f && !(f = fopen(filename, "r"))) {
118 if (errno == ENOENT) {
119 r = 0;
120 goto finish;
121 }
122
123 pa_log_warn("Failed to open configuration file '%s': %s",
124 filename, pa_cstrerror(errno));
125 goto finish;
126 }
127
128 while (!feof(f)) {
129 char l[256];
130 if (!fgets(l, sizeof(l), f)) {
131 if (feof(f))
132 break;
133
134 pa_log_warn("Failed to read configuration file '%s': %s",
135 filename, pa_cstrerror(errno));
136 goto finish;
137 }
138
139 if (parse_line(filename, ++line, t, l, userdata) < 0)
140 goto finish;
141 }
142
143 r = 0;
144
145 finish:
146
147 if (do_close && f)
148 fclose(f);
149
150 return r;
151 }
152
153 int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
154 int *i = data;
155 int32_t k;
156
157 pa_assert(filename);
158 pa_assert(lvalue);
159 pa_assert(rvalue);
160 pa_assert(data);
161
162 if (pa_atoi(rvalue, &k) < 0) {
163 pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
164 return -1;
165 }
166
167 *i = (int) k;
168 return 0;
169 }
170
171 int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
172 int *b = data, k;
173
174 pa_assert(filename);
175 pa_assert(lvalue);
176 pa_assert(rvalue);
177 pa_assert(data);
178
179 if ((k = pa_parse_boolean(rvalue)) < 0) {
180 pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue);
181 return -1;
182 }
183
184 *b = k;
185
186 return 0;
187 }
188
189 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) {
190 char **s = data;
191
192 pa_assert(filename);
193 pa_assert(lvalue);
194 pa_assert(rvalue);
195 pa_assert(data);
196
197 pa_xfree(*s);
198 *s = *rvalue ? pa_xstrdup(rvalue) : NULL;
199 return 0;
200 }