blob: 833f158e1a76469bbfdc9a1e5aac7dc0947a603f [file] [log] [blame]
Lars Hjemli20a33542008-03-28 00:09:11 +01001/* configfile.c: parsing of config files
2 *
Lukas Fleischerf7f26f82014-01-08 15:10:49 +01003 * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com>
Lars Hjemli20a33542008-03-28 00:09:11 +01004 *
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
Lukas Fleischerbafab422013-03-04 08:52:33 +010013static int next_char(FILE *f)
Lars Hjemli20a33542008-03-28 00:09:11 +010014{
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
Lukas Fleischerbafab422013-03-04 08:52:33 +010026static void skip_line(FILE *f)
Lars Hjemli20a33542008-03-28 00:09:11 +010027{
28 int c;
29
Jason A. Donenfeldbdae1d82013-03-03 23:21:33 -050030 while ((c = next_char(f)) && c != '\n' && c != EOF)
Lars Hjemli20a33542008-03-28 00:09:11 +010031 ;
32}
33
Lukas Fleischer50e70d32013-06-04 14:47:53 +000034static int read_config_line(FILE *f, struct strbuf *name, struct strbuf *value)
Lars Hjemli20a33542008-03-28 00:09:11 +010035{
Lukas Fleischer50e70d32013-06-04 14:47:53 +000036 int c = next_char(f);
Lars Hjemli20a33542008-03-28 00:09:11 +010037
Lukas Fleischer50e70d32013-06-04 14:47:53 +000038 strbuf_reset(name);
39 strbuf_reset(value);
40
41 /* Skip comments and preceding spaces. */
42 for(;;) {
43 if (c == '#' || c == ';')
Lars Hjemli20a33542008-03-28 00:09:11 +010044 skip_line(f);
Lukas Fleischer50e70d32013-06-04 14:47:53 +000045 else if (!isspace(c))
Lars Hjemli20a33542008-03-28 00:09:11 +010046 break;
Lukas Fleischer50e70d32013-06-04 14:47:53 +000047 c = next_char(f);
Lars Hjemli20a33542008-03-28 00:09:11 +010048 }
Lukas Fleischer50e70d32013-06-04 14:47:53 +000049
50 /* Read variable name. */
51 while (c != '=') {
52 if (c == '\n' || c == EOF)
53 return 0;
54 strbuf_addch(name, c);
55 c = next_char(f);
56 }
57
58 /* Read variable value. */
59 c = next_char(f);
60 while (c != '\n' && c != EOF) {
61 strbuf_addch(value, c);
62 c = next_char(f);
63 }
64
65 return 1;
Lars Hjemli20a33542008-03-28 00:09:11 +010066}
67
68int parse_configfile(const char *filename, configfile_value_fn fn)
69{
70 static int nesting;
Lukas Fleischer50e70d32013-06-04 14:47:53 +000071 struct strbuf name = STRBUF_INIT;
72 struct strbuf value = STRBUF_INIT;
Lars Hjemli20a33542008-03-28 00:09:11 +010073 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++;
Lukas Fleischer50e70d32013-06-04 14:47:53 +000081 while (read_config_line(f, &name, &value))
82 fn(name.buf, value.buf);
Lars Hjemli20a33542008-03-28 00:09:11 +010083 nesting--;
84 fclose(f);
Lukas Fleischer50e70d32013-06-04 14:47:53 +000085 strbuf_release(&name);
86 strbuf_release(&value);
Lars Hjemli20a33542008-03-28 00:09:11 +010087 return 0;
88}
89