blob: fe5f9c56df603f88f96816e8e4f128e7aedfd884 [file] [log] [blame]
Lars Hjemli20a33542008-03-28 00:09:11 +01001/* configfile.c: parsing of config files
2 *
3 * Copyright (C) 2008 Lars Hjemli
4 *
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
7 */
8
9#include <ctype.h>
10#include <stdio.h>
11#include "configfile.h"
12
13int next_char(FILE *f)
14{
15 int c = fgetc(f);
Lukas Fleischer53bc7472013-03-03 16:04:29 +010016 if (c == '\r') {
Lars Hjemli20a33542008-03-28 00:09:11 +010017 c = fgetc(f);
Lukas Fleischer53bc7472013-03-03 16:04:29 +010018 if (c != '\n') {
Lars Hjemli20a33542008-03-28 00:09:11 +010019 ungetc(c, f);
20 c = '\r';
21 }
22 }
23 return c;
24}
25
26void skip_line(FILE *f)
27{
28 int c;
29
Lukas Fleischer53bc7472013-03-03 16:04:29 +010030 while((c = next_char(f)) && c != '\n' && c != EOF)
Lars Hjemli20a33542008-03-28 00:09:11 +010031 ;
32}
33
34int read_config_line(FILE *f, char *line, const char **value, int bufsize)
35{
36 int i = 0, isname = 0;
37
38 *value = NULL;
Lukas Fleischer53bc7472013-03-03 16:04:29 +010039 while(i < bufsize - 1) {
Lars Hjemli20a33542008-03-28 00:09:11 +010040 int c = next_char(f);
Lukas Fleischer53bc7472013-03-03 16:04:29 +010041 if (!isname && (c == '#' || c == ';')) {
Lars Hjemli20a33542008-03-28 00:09:11 +010042 skip_line(f);
43 continue;
44 }
45 if (!isname && isspace(c))
46 continue;
47
Lukas Fleischer53bc7472013-03-03 16:04:29 +010048 if (c == '=' && !*value) {
Lars Hjemli20a33542008-03-28 00:09:11 +010049 line[i] = 0;
Lukas Fleischer53bc7472013-03-03 16:04:29 +010050 *value = &line[i + 1];
51 } else if (c == '\n' && !isname) {
Lars Hjemli20a33542008-03-28 00:09:11 +010052 i = 0;
53 continue;
Lukas Fleischer53bc7472013-03-03 16:04:29 +010054 } else if (c == '\n' || c == EOF) {
Lars Hjemli20a33542008-03-28 00:09:11 +010055 line[i] = 0;
56 break;
57 } else {
Lukas Fleischer53bc7472013-03-03 16:04:29 +010058 line[i] = c;
Lars Hjemli20a33542008-03-28 00:09:11 +010059 }
60 isname = 1;
61 i++;
62 }
Lukas Fleischer53bc7472013-03-03 16:04:29 +010063 line[i + 1] = 0;
Lars Hjemli20a33542008-03-28 00:09:11 +010064 return i;
65}
66
67int parse_configfile(const char *filename, configfile_value_fn fn)
68{
69 static int nesting;
70 int len;
71 char line[256];
72 const char *value;
73 FILE *f;
74
75 /* cancel deeply nested include-commands */
76 if (nesting > 8)
77 return -1;
78 if (!(f = fopen(filename, "r")))
79 return -1;
80 nesting++;
81 while((len = read_config_line(f, line, &value, sizeof(line))) > 0)
82 fn(line, value);
83 nesting--;
84 fclose(f);
85 return 0;
86}
87