blob: e0391091e147891ca2639142a7b29180030db125 [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
John Keepingf2e8ca82015-08-13 12:14:16 +01009#include <git-compat-util.h>
Lars Hjemli20a33542008-03-28 00:09:11 +010010#include "configfile.h"
11
Lukas Fleischerbafab422013-03-04 08:52:33 +010012static int next_char(FILE *f)
Lars Hjemli20a33542008-03-28 00:09:11 +010013{
14 int c = fgetc(f);
Lukas Fleischer53bc7472013-03-03 16:04:29 +010015 if (c == '\r') {
Lars Hjemli20a33542008-03-28 00:09:11 +010016 c = fgetc(f);
Lukas Fleischer53bc7472013-03-03 16:04:29 +010017 if (c != '\n') {
Lars Hjemli20a33542008-03-28 00:09:11 +010018 ungetc(c, f);
19 c = '\r';
20 }
21 }
22 return c;
23}
24
Lukas Fleischerbafab422013-03-04 08:52:33 +010025static void skip_line(FILE *f)
Lars Hjemli20a33542008-03-28 00:09:11 +010026{
27 int c;
28
Jason A. Donenfeldbdae1d82013-03-03 23:21:33 -050029 while ((c = next_char(f)) && c != '\n' && c != EOF)
Lars Hjemli20a33542008-03-28 00:09:11 +010030 ;
31}
32
Lukas Fleischer50e70d32013-06-04 14:47:53 +000033static int read_config_line(FILE *f, struct strbuf *name, struct strbuf *value)
Lars Hjemli20a33542008-03-28 00:09:11 +010034{
Lukas Fleischer50e70d32013-06-04 14:47:53 +000035 int c = next_char(f);
Lars Hjemli20a33542008-03-28 00:09:11 +010036
Lukas Fleischer50e70d32013-06-04 14:47:53 +000037 strbuf_reset(name);
38 strbuf_reset(value);
39
40 /* Skip comments and preceding spaces. */
41 for(;;) {
John Keeping35df7102016-08-07 15:54:14 +010042 if (c == EOF)
43 return 0;
44 else if (c == '#' || c == ';')
Lars Hjemli20a33542008-03-28 00:09:11 +010045 skip_line(f);
Lukas Fleischer50e70d32013-06-04 14:47:53 +000046 else if (!isspace(c))
Lars Hjemli20a33542008-03-28 00:09:11 +010047 break;
Lukas Fleischer50e70d32013-06-04 14:47:53 +000048 c = next_char(f);
Lars Hjemli20a33542008-03-28 00:09:11 +010049 }
Lukas Fleischer50e70d32013-06-04 14:47:53 +000050
51 /* Read variable name. */
52 while (c != '=') {
53 if (c == '\n' || c == EOF)
54 return 0;
55 strbuf_addch(name, c);
56 c = next_char(f);
57 }
58
59 /* Read variable value. */
60 c = next_char(f);
61 while (c != '\n' && c != EOF) {
62 strbuf_addch(value, c);
63 c = next_char(f);
64 }
65
66 return 1;
Lars Hjemli20a33542008-03-28 00:09:11 +010067}
68
69int parse_configfile(const char *filename, configfile_value_fn fn)
70{
71 static int nesting;
Lukas Fleischer50e70d32013-06-04 14:47:53 +000072 struct strbuf name = STRBUF_INIT;
73 struct strbuf value = STRBUF_INIT;
Lars Hjemli20a33542008-03-28 00:09:11 +010074 FILE *f;
75
76 /* cancel deeply nested include-commands */
77 if (nesting > 8)
78 return -1;
79 if (!(f = fopen(filename, "r")))
80 return -1;
81 nesting++;
Lukas Fleischer50e70d32013-06-04 14:47:53 +000082 while (read_config_line(f, &name, &value))
83 fn(name.buf, value.buf);
Lars Hjemli20a33542008-03-28 00:09:11 +010084 nesting--;
85 fclose(f);
Lukas Fleischer50e70d32013-06-04 14:47:53 +000086 strbuf_release(&name);
87 strbuf_release(&value);
Lars Hjemli20a33542008-03-28 00:09:11 +010088 return 0;
89}
90