diff --git a/eeshow/file.c b/eeshow/file.c index 5635a0a..6abea40 100644 --- a/eeshow/file.c +++ b/eeshow/file.c @@ -21,41 +21,27 @@ #include "file.h" -bool file_cat(void *user, const char *line) +bool file_cat(const struct file *file, void *user, const char *line) { printf("%s\n", line); return 1; } -static void read_from_file(FILE *file, - bool (*parse)(void *user, const char *line), void *user) +void file_open(struct file *file, const char *name, + const struct file *related) { - char buf[1000]; - char *nl; - - while (fgets(buf, sizeof(buf), file)) { - nl = strchr(buf, '\n'); - if (nl) - *nl = 0; - if (!parse(user, buf)) - break; - } -} - - -void file_read(const char *name, bool (*parse)(void *user, const char *line), - void *user) -{ - FILE *file; char *colon, *tmp; - file = fopen(name, "r"); - if (file) { + file->name = stralloc(name); + file->lineno = 0; + file->related = related; + file->vcs = NULL; + + file->file = fopen(name, "r"); + if (file->file) { if (verbose) fprintf(stderr, "reading %s\n", name); - read_from_file(file, parse, user); - fclose(file); return; } @@ -71,6 +57,42 @@ void file_read(const char *name, bool (*parse)(void *user, const char *line), tmp = stralloc(name); tmp[colon - name] = 0; - vcs_git_read(tmp, colon + 1, parse, user); + file->vcs = vcs_git_open(tmp, colon + 1); + if (!file->vcs) { + fprintf(stderr, "could not open %s:%s\n", tmp, colon + 1); + exit(1); + } free(tmp); } + + +void file_read(struct file *file, + bool (*parse)(const struct file *file, void *user, const char *line), + void *user) +{ + char buf[1000]; + char *nl; + + if (file->vcs) { + vcs_read(file->vcs, file, parse, user); + return; + } + while (fgets(buf, sizeof(buf), file->file)) { + nl = strchr(buf, '\n'); + if (nl) + *nl = 0; + file->lineno++; + if (!parse(file, user, buf)) + break; + } +} + + +void file_close(struct file *file) +{ + if (file->file) + fclose(file->file); + if (file->vcs) + vcs_close(file->vcs); + free((char *) file->name); +} diff --git a/eeshow/file.h b/eeshow/file.h index a6cc170..43db8b7 100644 --- a/eeshow/file.h +++ b/eeshow/file.h @@ -14,9 +14,25 @@ #define FILE_H #include +#include -bool file_cat(void *user, const char *line); -void file_read(const char *name, bool (*parse)(void *user, const char *line), + +struct file { + FILE *file; /* NULL if using a version control system */ + void *vcs; /* VCS descriptor or NULL */ + const char *name; /* name/designator given to file_open */ + unsigned lineno; + const struct file *related; /* NULL if not related to anything */ +}; + + +bool file_cat(const struct file *file, void *user, const char *line); + +void file_open(struct file *file, const char *name, + const struct file *related); +void file_read(struct file *file, + bool (*parse)(const struct file *file, void *user, const char *line), void *user); +void file_close(struct file *file); #endif /* !FILE_H */ diff --git a/eeshow/git-file.c b/eeshow/git-file.c index bd66d73..261de53 100644 --- a/eeshow/git-file.c +++ b/eeshow/git-file.c @@ -22,9 +22,16 @@ #include "util.h" #include "main.h" +#include "file.h" #include "git-file.h" +struct vcs_git { + const void *data; + unsigned size; +}; + + static git_repository *select_repo(const char *path) { git_repository *repo = NULL; @@ -305,48 +312,27 @@ static const void *get_data(git_repository *repo, git_tree_entry *entry, static bool send_line(const char *s, unsigned len, - bool (*parse)(void *user, const char *line), void *user) + bool (*parse)(const struct file *file, void *user, const char *line), + void *user, const struct file *file) { char *tmp = alloc_size(len + 1); bool res; memcpy(tmp, s, len); tmp[len] = 0; - res = parse(user, tmp); + res = parse(file, user, tmp); free(tmp); return res; } -static void send_data(const char *data, unsigned size, - bool (*parse)(void *user, const char *line), void *user) -{ - const char *end = data + size; - const char *p = data; - const char *nl; - - while (p != end) { - nl = memchr(p, '\n', end - p); - if (!nl) { - send_line(p, end - p, parse, user); - return; - } - if (!send_line(p, nl - p, parse, user)) - return; - p = nl + 1; - } -} - - -void vcs_git_read(const char *revision, const char *name, - bool (*parse)(void *user, const char *line), void *user) +struct vcs_git *vcs_git_open(const char *revision, const char *name) { static bool initialized = 0; + struct vcs_git *vcs_git = alloc_type(struct vcs_git); git_repository *repo; git_tree *tree; git_tree_entry *entry; - const void *data; - unsigned size; if (!initialized) { git_libgit2_init(); @@ -366,6 +352,37 @@ void vcs_git_read(const char *revision, const char *name, entry = find_file(repo, tree, name); if (verbose) fprintf(stderr, "reading %s:%s\n", revision, name); - data = get_data(repo, entry, &size); - send_data(data, size, parse, user); + + vcs_git->data = get_data(repo, entry, &vcs_git->size); + + return vcs_git; +} + + +void vcs_git_read(void *ctx, struct file *file, + bool (*parse)(const struct file *file, void *user, const char *line), + void *user) +{ + const struct vcs_git *vcs_git = ctx; + const char *end = vcs_git->data + vcs_git->size; + const char *p = vcs_git->data; + const char *nl; + + while (p != end) { + nl = memchr(p, '\n', end - p); + file->lineno++; + if (!nl) { + send_line(p, end - p, parse, user, file); + return; + } + if (!send_line(p, nl - p, parse, user, file)) + return; + p = nl + 1; + } +} + + +void vcs_git_close(void *ctx) +{ + free(ctx); } diff --git a/eeshow/git-file.h b/eeshow/git-file.h index 503a563..9214d93 100644 --- a/eeshow/git-file.h +++ b/eeshow/git-file.h @@ -16,7 +16,23 @@ #include -void vcs_git_read(const char *revision, const char *name, - bool (*parse)(void *user, const char *line), void *user); +/* + * future-proofing: if someone wants to add back-ends for other version control + * systems, the identifiers will already be there. + */ + +#define vcs_open vcs_git_open +#define vcs_read vcs_git_read +#define vcs_close vcs_git_close + + +struct vcs_git; +struct file; + +struct vcs_git *vcs_git_open(const char *revision, const char *name); +void vcs_git_read(void *ctx, struct file *file, + bool (*parse)(const struct file *file, void *user, const char *line), + void *user); +void vcs_git_close(void *ctx); #endif /* !GIT_FILE_H */ diff --git a/eeshow/lib-parse.c b/eeshow/lib-parse.c index 21d37ff..5946d31 100644 --- a/eeshow/lib-parse.c +++ b/eeshow/lib-parse.c @@ -130,7 +130,8 @@ static bool parse_arc(struct lib_obj *obj, const char *line) /* ----- Library parser ---------------------------------------------------- */ -static bool lib_parse_line(void *user, const char *line) +static bool lib_parse_line(const struct file *file, + void *user, const char *line) { struct lib *lib = user; int n = 0; @@ -253,11 +254,15 @@ static bool lib_parse_line(void *user, const char *line) } -void lib_parse(struct lib *lib, const char *file) +void lib_parse(struct lib *lib, const char *name) { + struct file file; + lib->state = lib_skip; lib->lineno = 0; - file_read(file, lib_parse_line, lib); + file_open(&file, name, NULL); + file_read(&file, lib_parse_line, lib); + file_close(&file); } diff --git a/eeshow/lib.h b/eeshow/lib.h index 4f1e9f0..52c1746 100644 --- a/eeshow/lib.h +++ b/eeshow/lib.h @@ -118,7 +118,7 @@ const struct comp *lib_find(const struct lib *lib, const char *name); bool lib_field_visible(const struct comp *comp, int n); void lib_render(const struct comp *comp, unsigned unit, const int m[6]); -void lib_parse(struct lib *lib, const char *file); +void lib_parse(struct lib *lib, const char *name); void lib_init(struct lib *lib); #endif /* !LIB_H */ diff --git a/eeshow/main.c b/eeshow/main.c index b38761a..8b947de 100644 --- a/eeshow/main.c +++ b/eeshow/main.c @@ -109,9 +109,13 @@ int main(int argc, char *const *argv) } if (cat) { + struct file file; + if (argc != optind) usage(*argv); - file_read(cat, file_cat, NULL); + file_open(&file, cat, NULL); + file_read(&file, file_cat, NULL); + file_close(&file); return 0; } diff --git a/eeshow/sch-parse.c b/eeshow/sch-parse.c index e47ac49..7a2c8c4 100644 --- a/eeshow/sch-parse.c +++ b/eeshow/sch-parse.c @@ -293,7 +293,7 @@ static struct sheet *new_sheet(struct sch_ctx *ctx) } -static bool parse_line(void *user, const char *line); +static bool parse_line(const struct file *file, void *user, const char *line); static void recurse_sheet(struct sch_ctx *ctx) @@ -301,6 +301,7 @@ static void recurse_sheet(struct sch_ctx *ctx) struct sch_obj **saved_next_obj = ctx->next_obj; const char *parent = ctx->file->name; char *tmp = NULL; + struct file file; struct sch_file dsc = { .name = ctx->obj.u.sheet.file, .lineno = 0, @@ -326,14 +327,16 @@ static void recurse_sheet(struct sch_ctx *ctx) new_sheet(ctx); ctx->file = &dsc; ctx->state = sch_descr; - file_read(dsc.name, parse_line, ctx); + file_open(&file, dsc.name, NULL); + file_read(&file, parse_line, ctx); + file_close(&file); ctx->file = dsc.parent; ctx->next_obj = saved_next_obj; free(tmp); } -static bool parse_line(void *user, const char *line) +static bool parse_line(const struct file *file, void *user, const char *line) { struct sch_ctx *ctx = user; struct sch_obj *obj = &ctx->obj; @@ -538,17 +541,20 @@ static bool parse_line(void *user, const char *line) } -void sch_parse(struct sch_ctx *ctx, const char *file, const struct lib *lib) +void sch_parse(struct sch_ctx *ctx, const char *name, const struct lib *lib) { + struct file file; struct sch_file dsc = { - .name = file, + .name = name, .lineno = 0, .parent = NULL, }; ctx->file = &dsc; ctx->lib = lib; - file_read(file, parse_line, ctx); + file_open(&file, name, NULL); + file_read(&file, parse_line, ctx); + file_close(&file); } diff --git a/eeshow/sch.h b/eeshow/sch.h index b1e2d70..7f036ce 100644 --- a/eeshow/sch.h +++ b/eeshow/sch.h @@ -117,7 +117,7 @@ struct sch_ctx { void decode_alignment(struct text *txt, char hor, char vert); void sch_render(const struct sheet *sheet); -void sch_parse(struct sch_ctx *ctx, const char *file, const struct lib *lib); +void sch_parse(struct sch_ctx *ctx, const char *name, const struct lib *lib); void sch_init(struct sch_ctx *ctx, bool recurse); #endif /* !SCH_H */