Skip to content

Commit 4d8dd14

Browse files
hvoigtgitster
authored andcommitted
config: make parsing stack struct independent from actual data source
To simplify adding other sources we extract all functions needed for parsing into a list of callbacks. We implement those callbacks for the current file parsing. A new source can implement its own set of callbacks. Instead of storing the concrete FILE pointer for parsing we store a void pointer. A new source can use this to store its custom data. Signed-off-by: Heiko Voigt <[email protected]> Acked-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent dbb9a81 commit 4d8dd14

File tree

1 file changed

+43
-21
lines changed

1 file changed

+43
-21
lines changed

config.c

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,41 @@
1010
#include "strbuf.h"
1111
#include "quote.h"
1212

13-
typedef struct config_file {
14-
struct config_file *prev;
15-
FILE *f;
13+
struct config_source {
14+
struct config_source *prev;
15+
union {
16+
FILE *file;
17+
} u;
1618
const char *name;
1719
int linenr;
1820
int eof;
1921
struct strbuf value;
2022
struct strbuf var;
21-
} config_file;
2223

23-
static config_file *cf;
24+
int (*fgetc)(struct config_source *c);
25+
int (*ungetc)(int c, struct config_source *conf);
26+
long (*ftell)(struct config_source *c);
27+
};
28+
29+
static struct config_source *cf;
2430

2531
static int zlib_compression_seen;
2632

33+
static int config_file_fgetc(struct config_source *conf)
34+
{
35+
return fgetc(conf->u.file);
36+
}
37+
38+
static int config_file_ungetc(int c, struct config_source *conf)
39+
{
40+
return ungetc(c, conf->u.file);
41+
}
42+
43+
static long config_file_ftell(struct config_source *conf)
44+
{
45+
return ftell(conf->u.file);
46+
}
47+
2748
#define MAX_INCLUDE_DEPTH 10
2849
static const char include_depth_advice[] =
2950
"exceeded maximum include depth (%d) while including\n"
@@ -168,15 +189,13 @@ int git_config_from_parameters(config_fn_t fn, void *data)
168189

169190
static int get_next_char(void)
170191
{
171-
int c;
172-
FILE *f = cf->f;
192+
int c = cf->fgetc(cf);
173193

174-
c = fgetc(f);
175194
if (c == '\r') {
176195
/* DOS like systems */
177-
c = fgetc(f);
196+
c = cf->fgetc(cf);
178197
if (c != '\n') {
179-
ungetc(c, f);
198+
cf->ungetc(c, cf);
180199
c = '\r';
181200
}
182201
}
@@ -336,7 +355,7 @@ static int get_base_var(struct strbuf *name)
336355
}
337356
}
338357

339-
static int git_parse_file(config_fn_t fn, void *data)
358+
static int git_parse_source(config_fn_t fn, void *data)
340359
{
341360
int comment = 0;
342361
int baselen = 0;
@@ -894,10 +913,11 @@ int git_default_config(const char *var, const char *value, void *dummy)
894913
}
895914

896915
/*
897-
* The fields f and name of top need to be initialized before calling
916+
* All source specific fields in the union, name and the callbacks
917+
* fgetc, ungetc, ftell of top need to be initialized before calling
898918
* this function.
899919
*/
900-
static int do_config_from(struct config_file *top, config_fn_t fn, void *data)
920+
static int do_config_from(struct config_source *top, config_fn_t fn, void *data)
901921
{
902922
int ret;
903923

@@ -909,7 +929,7 @@ static int do_config_from(struct config_file *top, config_fn_t fn, void *data)
909929
strbuf_init(&top->var, 1024);
910930
cf = top;
911931

912-
ret = git_parse_file(fn, data);
932+
ret = git_parse_source(fn, data);
913933

914934
/* pop config-file parsing state stack */
915935
strbuf_release(&top->value);
@@ -926,10 +946,13 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
926946

927947
ret = -1;
928948
if (f) {
929-
config_file top;
949+
struct config_source top;
930950

931-
top.f = f;
951+
top.u.file = f;
932952
top.name = filename;
953+
top.fgetc = config_file_fgetc;
954+
top.ungetc = config_file_ungetc;
955+
top.ftell = config_file_ftell;
933956

934957
ret = do_config_from(&top, fn, data);
935958

@@ -1064,7 +1087,6 @@ static int store_aux(const char *key, const char *value, void *cb)
10641087
{
10651088
const char *ep;
10661089
size_t section_len;
1067-
FILE *f = cf->f;
10681090

10691091
switch (store.state) {
10701092
case KEY_SEEN:
@@ -1076,7 +1098,7 @@ static int store_aux(const char *key, const char *value, void *cb)
10761098
return 1;
10771099
}
10781100

1079-
store.offset[store.seen] = ftell(f);
1101+
store.offset[store.seen] = cf->ftell(cf);
10801102
store.seen++;
10811103
}
10821104
break;
@@ -1103,19 +1125,19 @@ static int store_aux(const char *key, const char *value, void *cb)
11031125
* Do not increment matches: this is no match, but we
11041126
* just made sure we are in the desired section.
11051127
*/
1106-
store.offset[store.seen] = ftell(f);
1128+
store.offset[store.seen] = cf->ftell(cf);
11071129
/* fallthru */
11081130
case SECTION_END_SEEN:
11091131
case START:
11101132
if (matches(key, value)) {
1111-
store.offset[store.seen] = ftell(f);
1133+
store.offset[store.seen] = cf->ftell(cf);
11121134
store.state = KEY_SEEN;
11131135
store.seen++;
11141136
} else {
11151137
if (strrchr(key, '.') - key == store.baselen &&
11161138
!strncmp(key, store.key, store.baselen)) {
11171139
store.state = SECTION_SEEN;
1118-
store.offset[store.seen] = ftell(f);
1140+
store.offset[store.seen] = cf->ftell(cf);
11191141
}
11201142
}
11211143
}

0 commit comments

Comments
 (0)