~binli/ubuntu/vivid/pulseaudio/load-extcon-module

« back to all changes in this revision

Viewing changes to src/pulsecore/conf-parser.c

  • Committer: Bin Li
  • Date: 2016-01-23 15:04:48 UTC
  • Revision ID: bin.li@canonical.com-20160123150448-5ockvw4p5xxntda4
init the 1:6.0-0ubuntu9.15 from silo 12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***
 
2
  This file is part of PulseAudio.
 
3
 
 
4
  Copyright 2004-2006 Lennart Poettering
 
5
 
 
6
  PulseAudio is free software; you can redistribute it and/or modify
 
7
  it under the terms of the GNU Lesser General Public License as published
 
8
  by the Free Software Foundation; either version 2.1 of the License,
 
9
  or (at your option) any later version.
 
10
 
 
11
  PulseAudio is distributed in the hope that it will be useful, but
 
12
  WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
14
  General Public License for more details.
 
15
 
 
16
  You should have received a copy of the GNU Lesser General Public License
 
17
  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
 
18
***/
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include <config.h>
 
22
#endif
 
23
 
 
24
#include <string.h>
 
25
#include <stdio.h>
 
26
#include <errno.h>
 
27
 
 
28
#include <pulse/xmalloc.h>
 
29
 
 
30
#include <pulsecore/core-error.h>
 
31
#include <pulsecore/log.h>
 
32
#include <pulsecore/core-util.h>
 
33
#include <pulsecore/macro.h>
 
34
 
 
35
#include "conf-parser.h"
 
36
 
 
37
#define WHITESPACE " \t\n"
 
38
#define COMMENTS "#;\n"
 
39
 
 
40
/* Run the user supplied parser for an assignment */
 
41
static int normal_assignment(pa_config_parser_state *state) {
 
42
    const pa_config_item *item;
 
43
 
 
44
    pa_assert(state);
 
45
 
 
46
    for (item = state->item_table; item->parse; item++) {
 
47
 
 
48
        if (item->lvalue && !pa_streq(state->lvalue, item->lvalue))
 
49
            continue;
 
50
 
 
51
        if (item->section && !state->section)
 
52
            continue;
 
53
 
 
54
        if (item->section && !pa_streq(state->section, item->section))
 
55
            continue;
 
56
 
 
57
        state->data = item->data;
 
58
 
 
59
        return item->parse(state);
 
60
    }
 
61
 
 
62
    pa_log("[%s:%u] Unknown lvalue '%s' in section '%s'.", state->filename, state->lineno, state->lvalue, pa_strna(state->section));
 
63
 
 
64
    return -1;
 
65
}
 
66
 
 
67
/* Parse a proplist entry. */
 
68
static int proplist_assignment(pa_config_parser_state *state) {
 
69
    pa_assert(state);
 
70
    pa_assert(state->proplist);
 
71
 
 
72
    if (pa_proplist_sets(state->proplist, state->lvalue, state->rvalue) < 0) {
 
73
        pa_log("[%s:%u] Failed to parse a proplist entry: %s = %s", state->filename, state->lineno, state->lvalue, state->rvalue);
 
74
        return -1;
 
75
    }
 
76
 
 
77
    return 0;
 
78
}
 
79
 
 
80
/* Parse a variable assignment line */
 
81
static int parse_line(pa_config_parser_state *state) {
 
82
    char *c;
 
83
 
 
84
    state->lvalue = state->buf + strspn(state->buf, WHITESPACE);
 
85
 
 
86
    if ((c = strpbrk(state->lvalue, COMMENTS)))
 
87
        *c = 0;
 
88
 
 
89
    if (!*state->lvalue)
 
90
        return 0;
 
91
 
 
92
    if (pa_startswith(state->lvalue, ".include ")) {
 
93
        char *path = NULL, *fn;
 
94
        int r;
 
95
 
 
96
        fn = pa_strip(state->lvalue + 9);
 
97
        if (!pa_is_path_absolute(fn)) {
 
98
            const char *k;
 
99
            if ((k = strrchr(state->filename, '/'))) {
 
100
                char *dir = pa_xstrndup(state->filename, k - state->filename);
 
101
                fn = path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", dir, fn);
 
102
                pa_xfree(dir);
 
103
            }
 
104
        }
 
105
 
 
106
        r = pa_config_parse(fn, NULL, state->item_table, state->proplist, state->userdata);
 
107
        pa_xfree(path);
 
108
        return r;
 
109
    }
 
110
 
 
111
    if (*state->lvalue == '[') {
 
112
        size_t k;
 
113
 
 
114
        k = strlen(state->lvalue);
 
115
        pa_assert(k > 0);
 
116
 
 
117
        if (state->lvalue[k-1] != ']') {
 
118
            pa_log("[%s:%u] Invalid section header.", state->filename, state->lineno);
 
119
            return -1;
 
120
        }
 
121
 
 
122
        pa_xfree(state->section);
 
123
        state->section = pa_xstrndup(state->lvalue + 1, k-2);
 
124
 
 
125
        if (pa_streq(state->section, "Properties")) {
 
126
            if (!state->proplist) {
 
127
                pa_log("[%s:%u] \"Properties\" section is not allowed in this file.", state->filename, state->lineno);
 
128
                return -1;
 
129
            }
 
130
 
 
131
            state->in_proplist = true;
 
132
        } else
 
133
            state->in_proplist = false;
 
134
 
 
135
        return 0;
 
136
    }
 
137
 
 
138
    if (!(state->rvalue = strchr(state->lvalue, '='))) {
 
139
        pa_log("[%s:%u] Missing '='.", state->filename, state->lineno);
 
140
        return -1;
 
141
    }
 
142
 
 
143
    *state->rvalue = 0;
 
144
    state->rvalue++;
 
145
 
 
146
    state->lvalue = pa_strip(state->lvalue);
 
147
    state->rvalue = pa_strip(state->rvalue);
 
148
 
 
149
    if (state->in_proplist)
 
150
        return proplist_assignment(state);
 
151
    else
 
152
        return normal_assignment(state);
 
153
}
 
154
 
 
155
/* Go through the file and parse each line */
 
156
int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, pa_proplist *proplist, void *userdata) {
 
157
    int r = -1;
 
158
    bool do_close = !f;
 
159
    pa_config_parser_state state;
 
160
 
 
161
    pa_assert(filename);
 
162
    pa_assert(t);
 
163
 
 
164
    pa_zero(state);
 
165
 
 
166
    if (!f && !(f = pa_fopen_cloexec(filename, "r"))) {
 
167
        if (errno == ENOENT) {
 
168
            pa_log_debug("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno));
 
169
            r = 0;
 
170
            goto finish;
 
171
        }
 
172
 
 
173
        pa_log_warn("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno));
 
174
        goto finish;
 
175
    }
 
176
    pa_log_debug("Parsing configuration file '%s'", filename);
 
177
 
 
178
    state.filename = filename;
 
179
    state.item_table = t;
 
180
    state.userdata = userdata;
 
181
 
 
182
    if (proplist)
 
183
        state.proplist = pa_proplist_new();
 
184
 
 
185
    while (!feof(f)) {
 
186
        if (!fgets(state.buf, sizeof(state.buf), f)) {
 
187
            if (feof(f))
 
188
                break;
 
189
 
 
190
            pa_log_warn("Failed to read configuration file '%s': %s", filename, pa_cstrerror(errno));
 
191
            goto finish;
 
192
        }
 
193
 
 
194
        state.lineno++;
 
195
 
 
196
        if (parse_line(&state) < 0)
 
197
            goto finish;
 
198
    }
 
199
 
 
200
    if (proplist)
 
201
        pa_proplist_update(proplist, PA_UPDATE_REPLACE, state.proplist);
 
202
 
 
203
    r = 0;
 
204
 
 
205
finish:
 
206
    if (state.proplist)
 
207
        pa_proplist_free(state.proplist);
 
208
 
 
209
    pa_xfree(state.section);
 
210
 
 
211
    if (do_close && f)
 
212
        fclose(f);
 
213
 
 
214
    return r;
 
215
}
 
216
 
 
217
int pa_config_parse_int(pa_config_parser_state *state) {
 
218
    int *i;
 
219
    int32_t k;
 
220
 
 
221
    pa_assert(state);
 
222
 
 
223
    i = state->data;
 
224
 
 
225
    if (pa_atoi(state->rvalue, &k) < 0) {
 
226
        pa_log("[%s:%u] Failed to parse numeric value: %s", state->filename, state->lineno, state->rvalue);
 
227
        return -1;
 
228
    }
 
229
 
 
230
    *i = (int) k;
 
231
    return 0;
 
232
}
 
233
 
 
234
int pa_config_parse_unsigned(pa_config_parser_state *state) {
 
235
    unsigned *u;
 
236
    uint32_t k;
 
237
 
 
238
    pa_assert(state);
 
239
 
 
240
    u = state->data;
 
241
 
 
242
    if (pa_atou(state->rvalue, &k) < 0) {
 
243
        pa_log("[%s:%u] Failed to parse numeric value: %s", state->filename, state->lineno, state->rvalue);
 
244
        return -1;
 
245
    }
 
246
 
 
247
    *u = (unsigned) k;
 
248
    return 0;
 
249
}
 
250
 
 
251
int pa_config_parse_size(pa_config_parser_state *state) {
 
252
    size_t *i;
 
253
    uint32_t k;
 
254
 
 
255
    pa_assert(state);
 
256
 
 
257
    i = state->data;
 
258
 
 
259
    if (pa_atou(state->rvalue, &k) < 0) {
 
260
        pa_log("[%s:%u] Failed to parse numeric value: %s", state->filename, state->lineno, state->rvalue);
 
261
        return -1;
 
262
    }
 
263
 
 
264
    *i = (size_t) k;
 
265
    return 0;
 
266
}
 
267
 
 
268
int pa_config_parse_bool(pa_config_parser_state *state) {
 
269
    int k;
 
270
    bool *b;
 
271
 
 
272
    pa_assert(state);
 
273
 
 
274
    b = state->data;
 
275
 
 
276
    if ((k = pa_parse_boolean(state->rvalue)) < 0) {
 
277
        pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue);
 
278
        return -1;
 
279
    }
 
280
 
 
281
    *b = !!k;
 
282
 
 
283
    return 0;
 
284
}
 
285
 
 
286
int pa_config_parse_not_bool(pa_config_parser_state *state) {
 
287
    int k;
 
288
    bool *b;
 
289
 
 
290
    pa_assert(state);
 
291
 
 
292
    b = state->data;
 
293
 
 
294
    if ((k = pa_parse_boolean(state->rvalue)) < 0) {
 
295
        pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue);
 
296
        return -1;
 
297
    }
 
298
 
 
299
    *b = !k;
 
300
 
 
301
    return 0;
 
302
}
 
303
 
 
304
int pa_config_parse_string(pa_config_parser_state *state) {
 
305
    char **s;
 
306
 
 
307
    pa_assert(state);
 
308
 
 
309
    s = state->data;
 
310
 
 
311
    pa_xfree(*s);
 
312
    *s = *state->rvalue ? pa_xstrdup(state->rvalue) : NULL;
 
313
    return 0;
 
314
}