Only compile parallel HTTP support with CURL >= 7.9.8
[git.git] / config.c
1 #include <ctype.h>
2
3 #include "cache.h"
4
5 #define MAXNAME (256)
6
7 static FILE *config_file;
8 static int config_linenr;
9 static int get_next_char(void)
10 {
11         int c;
12         FILE *f;
13
14         c = '\n';
15         if ((f = config_file) != NULL) {
16                 c = fgetc(f);
17                 if (c == '\n')
18                         config_linenr++;
19                 if (c == EOF) {
20                         config_file = NULL;
21                         c = '\n';
22                 }
23         }
24         return c;
25 }
26
27 static char *parse_value(void)
28 {
29         static char value[1024];
30         int quote = 0, comment = 0, len = 0, space = 0;
31
32         for (;;) {
33                 int c = get_next_char();
34                 if (len >= sizeof(value))
35                         return NULL;
36                 if (c == '\n') {
37                         if (quote)
38                                 return NULL;
39                         value[len] = 0;
40                         return value;
41                 }
42                 if (comment)
43                         continue;
44                 if (isspace(c) && !quote) {
45                         space = 1;
46                         continue;
47                 }
48                 if (space) {
49                         if (len)
50                                 value[len++] = ' ';
51                         space = 0;
52                 }
53                 if (c == '\\') {
54                         c = get_next_char();
55                         switch (c) {
56                         case '\n':
57                                 continue;
58                         case 't':
59                                 c = '\t';
60                                 break;
61                         case 'b':
62                                 c = '\b';
63                                 break;
64                         case 'n':
65                                 c = '\n';
66                                 break;
67                         return NULL;
68                         }
69                         value[len++] = c;
70                         continue;
71                 }
72                 if (c == '"') {
73                         quote = 1-quote;
74                         continue;
75                 }
76                 if (!quote) {
77                         if (c == ';' || c == '#') {
78                                 comment = 1;
79                                 continue;
80                         }
81                 }
82                 value[len++] = c;
83         }
84 }
85
86 static int get_value(config_fn_t fn, char *name, unsigned int len)
87 {
88         int c;
89         char *value;
90
91         /* Get the full name */
92         for (;;) {
93                 c = get_next_char();
94                 if (c == EOF)
95                         break;
96                 if (!isalnum(c))
97                         break;
98                 name[len++] = tolower(c);
99                 if (len >= MAXNAME)
100                         return -1;
101         }
102         name[len] = 0;
103         while (c == ' ' || c == '\t')
104                 c = get_next_char();
105
106         value = NULL;
107         if (c != '\n') {
108                 if (c != '=')
109                         return -1;
110                 value = parse_value();
111                 if (!value)
112                         return -1;
113         }
114         return fn(name, value);
115 }
116
117 static int get_base_var(char *name)
118 {
119         int baselen = 0;
120
121         for (;;) {
122                 int c = get_next_char();
123                 if (c == EOF)
124                         return -1;
125                 if (c == ']')
126                         return baselen;
127                 if (!isalnum(c))
128                         return -1;
129                 if (baselen > MAXNAME / 2)
130                         return -1;
131                 name[baselen++] = tolower(c);
132         }
133 }
134
135 static int git_parse_file(config_fn_t fn)
136 {
137         int comment = 0;
138         int baselen = 0;
139         static char var[MAXNAME];
140
141         for (;;) {
142                 int c = get_next_char();
143                 if (c == '\n') {
144                         /* EOF? */
145                         if (!config_file)
146                                 return 0;
147                         comment = 0;
148                         continue;
149                 }
150                 if (comment || isspace(c))
151                         continue;
152                 if (c == '#' || c == ';') {
153                         comment = 1;
154                         continue;
155                 }
156                 if (c == '[') {
157                         baselen = get_base_var(var);
158                         if (baselen <= 0)
159                                 break;
160                         var[baselen++] = '.';
161                         var[baselen] = 0;
162                         continue;
163                 }
164                 if (!isalpha(c))
165                         break;
166                 var[baselen] = c;
167                 if (get_value(fn, var, baselen+1) < 0)
168                         break;
169         }
170         die("bad config file line %d", config_linenr);
171 }
172
173 int git_config_int(const char *name, const char *value)
174 {
175         if (value && *value) {
176                 char *end;
177                 int val = strtol(value, &end, 0);
178                 if (!*end)
179                         return val;
180         }
181         die("bad config value for '%s'", name);
182 }
183
184 int git_config_bool(const char *name, const char *value)
185 {
186         if (!value)
187                 return 1;
188         if (!*value)
189                 return 0;
190         if (!strcasecmp(value, "true"))
191                 return 1;
192         if (!strcasecmp(value, "false"))
193                 return 0;
194         return git_config_int(name, value) != 0;
195 }
196
197 int git_default_config(const char *var, const char *value)
198 {
199         /* This needs a better name */
200         if (!strcmp(var, "core.filemode")) {
201                 trust_executable_bit = git_config_bool(var, value);
202                 return 0;
203         }
204
205         /* Add other config variables here.. */
206         return 0;
207 }
208
209 int git_config(config_fn_t fn)
210 {
211         int ret;
212         FILE *f = fopen(git_path("config"), "r");
213
214         ret = -1;
215         if (f) {
216                 config_file = f;
217                 config_linenr = 1;
218                 ret = git_parse_file(fn);
219                 fclose(f);
220         }
221         return ret;
222 }