diff --git a/include/util/input_file.h b/include/util/input_file.h index 3b762b4..03fff24 100644 --- a/include/util/input_file.h +++ b/include/util/input_file.h @@ -1,23 +1,18 @@ #ifndef INPUT_FILE_H #define INPUT_FILE_H -#include - -typedef struct { - FILE *f; - char *line; - const char *filename; - size_t linenum; -} input_file_t; +#include typedef struct { const char *name; - int (*handle)(input_file_t *f, void *obj); + int (*handle)(char *line, const char *filename, + size_t linenum, void *obj); } keyword_handler_t; int process_file(const char *filename, const keyword_handler_t *handlers, size_t count, void *obj); -void input_file_complain(const input_file_t *f, const char *msg); +void input_file_complain(const char *filename, size_t linenum, + const char *msg); #endif /* INPUT_FILE_H */ diff --git a/lib/util/input_file.c b/lib/util/input_file.c index b89565f..3954266 100644 --- a/lib/util/input_file.c +++ b/lib/util/input_file.c @@ -1,122 +1,58 @@ -#include #include -#include +#include #include #include "util/input_file.h" +#include "util/util.h" -static int prefetch_line(input_file_t *f) +void input_file_complain(const char *filename, size_t linenum, const char *msg) { - char *line, *ptr; - ssize_t ret; - size_t n; -retry: - free(f->line); - f->line = NULL; - - errno = 0; - line = NULL; - n = 0; - ret = getline(&line, &n, f->f); - - if (ret < 0) { - if (errno != 0) { - perror(f->filename); - free(line); - return -1; - } - free(line); - return 1; - } - - n = strlen(line); - while (n >0 && isspace(line[n - 1])) - --n; - line[n] = '\0'; - - f->line = line; - f->linenum += 1; - - for (ptr = f->line; isspace(*ptr); ++ptr) - ; - - if (*ptr == '\0' || *ptr == '#') - goto retry; - - if (ptr != f->line) - memmove(f->line, ptr, strlen(ptr) + 1); - - ptr = f->line + strlen(f->line); - - while (ptr > f->line && isspace(ptr[-1])) - --ptr; - *ptr = '\0'; - - if (f->line[0] == '\0') - goto retry; - return 0; + fprintf(stderr, "%s: %zu: %s\n", filename, linenum, msg); } -void input_file_complain(const input_file_t *f, const char *msg) +struct userdata { + const keyword_handler_t *handlers; + size_t count; + void *obj; +}; + +static int handle_line(void *usr, const char *filename, + size_t linenum, char *line) { - fprintf(stderr, "%s: %zu: %s\n", f->filename, f->linenum, msg); + struct userdata *u = usr; + size_t i, len; + + while (isspace(*line)) + ++line; + + if (*line == '\0' || *line == '#') + return 0; + + for (i = 0; i < u->count; ++i) { + len = strlen(u->handlers[i].name); + + if (strncmp(line, u->handlers[i].name, len) != 0) + continue; + if (!isspace(line[len]) && line[len] != '\0') + continue; + for (line += len; isspace(*line); ++line) + ; + break; + } + + if (i == u->count) { + fprintf(stderr, "%s: %zu: unknown keyword\n", + filename, linenum); + return -1; + } + + return u->handlers[i].handle(line, filename, linenum, u->obj); } int process_file(const char *filename, const keyword_handler_t *handlers, size_t count, void *obj) { - input_file_t f; - size_t i, len; - char *ptr; - int ret; + struct userdata u = { handlers, count, obj }; - memset(&f, 0, sizeof(f)); - - f.filename = filename; - f.f = fopen(filename, "r"); - - if (f.f == NULL) { - perror(f.filename); - return -1; - } - - for (;;) { - ret = prefetch_line(&f); - if (ret < 0) - goto fail; - if (ret > 0) - break; - - ptr = f.line; - - for (i = 0; i < count; ++i) { - len = strlen(handlers[i].name); - - if (strncmp(ptr, handlers[i].name, len) != 0) - continue; - if (!isspace(ptr[len]) && ptr[len] != '\0') - continue; - for (ptr += len; isspace(*ptr); ++ptr) - ; - memmove(f.line, ptr, strlen(ptr) + 1); - break; - } - - if (i == count) { - fprintf(stderr, "%s: %zu: unknown keyword\n", - f.filename, f.linenum); - goto fail; - } - - if (handlers[i].handle(&f, obj)) - goto fail; - } - - fclose(f.f); - free(f.line); - return 0; -fail: - fclose(f.f); - free(f.line); - return -1; + return foreach_line_in_file(filename, &u, handle_line); } diff --git a/main/cmd/buildstrategy/buildstrategy.c b/main/cmd/buildstrategy/buildstrategy.c index 57e0a4f..936ce28 100644 --- a/main/cmd/buildstrategy/buildstrategy.c +++ b/main/cmd/buildstrategy/buildstrategy.c @@ -1,65 +1,37 @@ #include "buildstrategy.h" -typedef int (*line_handler_t)(const char *lhs, const char *rhs); +typedef int (*line_handler_t)(const char *filename, size_t linenum, + const char *lhs, const char *rhs); + +struct userdata { + line_handler_t cb; +}; + +static int handle_line(void *usr, const char *filename, + size_t linenum, char *line) +{ + struct userdata *u = usr; + char *rhs; + + rhs = strchr(line, ','); + if (rhs == NULL) + return 0; + + *(rhs++) = '\0'; + while (isspace(*rhs)) + ++rhs; + + if (*line == '\0' || *rhs == '\0') + return 0; + + return u->cb(filename, linenum, line, rhs); +} static int foreach_line(const char *filename, line_handler_t cb) { - FILE *f = fopen(filename, "r"); + struct userdata u = { cb }; - for (;;) { - char *line = NULL, *rhs, *lhs, *ptr; - size_t n = 0; - ssize_t ret; - - errno = 0; - ret = getline(&line, &n, f); - - if (ret < 0) { - if (errno == 0) { - free(line); - break; - } - perror(filename); - free(line); - fclose(f); - return -1; - } - - rhs = strchr(line, ','); - if (rhs == NULL) { - free(line); - continue; - } - - *(rhs++) = '\0'; - while (isspace(*rhs)) - ++rhs; - - ptr = rhs; - while (*ptr != '\0' && !isspace(*ptr)) - ++ptr; - *ptr = '\0'; - - lhs = line; - while (isspace(*lhs)) - ++lhs; - - if (*lhs == '\0' || *rhs == '\0') { - free(line); - continue; - } - - if (cb(lhs, rhs)) { - free(line); - fclose(f); - return -1; - } - - free(line); - } - - fclose(f); - return 0; + return foreach_line_in_file(filename, &u, handle_line); } /*****************************************************************************/ @@ -67,7 +39,8 @@ static int foreach_line(const char *filename, line_handler_t cb) static hash_table_t tbl_provides; static hash_table_t tbl_sourcepkgs; -static int handle_depends(const char *sourcepkg, const char *binpkg) +static int handle_depends(const char *filename, size_t linenum, + const char *sourcepkg, const char *binpkg) { source_pkg_t *src, *dep; size_t count; @@ -79,8 +52,9 @@ static int handle_depends(const char *sourcepkg, const char *binpkg) dep = hash_table_lookup(&tbl_provides, binpkg); if (dep == NULL) { - fprintf(stderr, "nothing provides '%s' required by '%s'\n", - binpkg, sourcepkg); + fprintf(stderr, + "%s: %zu: nothing provides '%s' required by '%s'\n", + filename, linenum, binpkg, sourcepkg); return -1; } @@ -100,14 +74,16 @@ static int handle_depends(const char *sourcepkg, const char *binpkg) return 0; } -static int handle_provides(const char *sourcepkg, const char *binpkg) +static int handle_provides(const char *filename, size_t linenum, + const char *sourcepkg, const char *binpkg) { source_pkg_t *src = NULL; src = hash_table_lookup(&tbl_provides, binpkg); if (src != NULL) { - fprintf(stderr, "%s: package already provided by %s\n", - binpkg, src->name); + fprintf(stderr, + "%s: %zu: %s: package already provided by %s\n", + filename, linenum, binpkg, src->name); return -1; } diff --git a/main/cmd/buildstrategy/buildstrategy.h b/main/cmd/buildstrategy/buildstrategy.h index 56ad229..4293ade 100644 --- a/main/cmd/buildstrategy/buildstrategy.h +++ b/main/cmd/buildstrategy/buildstrategy.h @@ -9,6 +9,7 @@ #include #include "command.h" +#include "util/util.h" #include "util/hashtable.h" enum { diff --git a/main/cmd/pack/desc.c b/main/cmd/pack/desc.c index bde1a66..d7d2969 100644 --- a/main/cmd/pack/desc.c +++ b/main/cmd/pack/desc.c @@ -1,8 +1,9 @@ #include "pack.h" -static int handle_requires(input_file_t *f, void *obj) +static int handle_requires(char *line, const char *filename, + size_t linenum, void *obj) { - char *ptr = f->line, *end; + char *ptr = line, *end; pkg_desc_t *desc = obj; dependency_t *dep; size_t len; @@ -19,13 +20,14 @@ static int handle_requires(input_file_t *f, void *obj) break; if (len > 0xFF) { - input_file_complain(f, "dependency name too long"); + input_file_complain(filename, linenum, "dependency name too long"); return -1; } dep = calloc(1, sizeof(*dep) + len + 1); if (dep == NULL) { - input_file_complain(f, "out of memory"); + input_file_complain(filename, linenum, + "out of memory"); return -1; } @@ -40,28 +42,30 @@ static int handle_requires(input_file_t *f, void *obj) return 0; } -static int handle_toc_compressor(input_file_t *f, void *obj) +static int handle_toc_compressor(char *line, const char *filename, + size_t linenum, void *obj) { pkg_desc_t *desc = obj; - desc->toccmp = compressor_by_name(f->line); + desc->toccmp = compressor_by_name(line); if (desc->toccmp == NULL) { - input_file_complain(f, "unkown compressor"); + input_file_complain(filename, linenum, "unkown compressor"); return -1; } return 0; } -static int handle_data_compressor(input_file_t *f, void *obj) +static int handle_data_compressor(char *line, const char *filename, + size_t linenum, void *obj) { pkg_desc_t *desc = obj; - desc->datacmp = compressor_by_name(f->line); + desc->datacmp = compressor_by_name(line); if (desc->datacmp == NULL) { - input_file_complain(f, "unkown compressor"); + input_file_complain(filename, linenum, "unkown compressor"); return -1; } diff --git a/main/cmd/pack/filelist.c b/main/cmd/pack/filelist.c index 24f8952..3de5f92 100644 --- a/main/cmd/pack/filelist.c +++ b/main/cmd/pack/filelist.c @@ -7,20 +7,20 @@ static char *skipspace(char *str) return str; } -static void oom(input_file_t *f) +static void oom(const char *filename, size_t linenum) { - input_file_complain(f, "out of memory"); + input_file_complain(filename, linenum, "out of memory"); } -static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) +static image_entry_t *filelist_mkentry(char *line, const char *filename, + size_t linenum, mode_t filetype) { - char *line = f->line; image_entry_t *ent; size_t i; ent = calloc(1, sizeof(*ent)); if (ent == NULL) { - oom(f); + oom(filename, linenum); return NULL; } @@ -29,29 +29,31 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) ; if (!isspace(line[i])) { - input_file_complain(f, "expected space after file name"); + input_file_complain(filename, linenum, + "expected space after file name"); goto fail; } ent->name = calloc(1, i + 1); if (ent->name == NULL) { - oom(f); + oom(filename, linenum); goto fail; } memcpy(ent->name, line, i); if (canonicalize_name(ent->name)) { - input_file_complain(f, "invalid file name"); + input_file_complain(filename, linenum, "invalid file name"); goto fail; } if (ent->name[0] == '\0') { - input_file_complain(f, "refusing to add entry for '/'"); + input_file_complain(filename, linenum, + "refusing to add entry for '/'"); goto fail; } if (strlen(ent->name) > 0xFFFF) { - input_file_complain(f, "name too long"); + input_file_complain(filename, linenum, "name too long"); goto fail; } @@ -59,20 +61,23 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) /* mode */ if (!isdigit(*line)) { - input_file_complain(f, "expected numeric mode after file name"); + input_file_complain(filename, linenum, + "expected numeric mode after file name"); goto fail; } while (isdigit(*line)) { if (*line > '7') { - input_file_complain(f, "mode must be octal number"); + input_file_complain(filename, linenum, + "mode must be octal number"); goto fail; } ent->mode = (ent->mode << 3) | (*(line++) - '0'); } if (!isspace(*line)) { - input_file_complain(f, "expected space after file mode"); + input_file_complain(filename, linenum, + "expected space after file mode"); goto fail; } @@ -82,7 +87,8 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) /* uid */ if (!isdigit(*line)) { - input_file_complain(f, "expected numeric UID after mode"); + input_file_complain(filename, linenum, + "expected numeric UID after mode"); goto fail; } @@ -90,7 +96,8 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) ent->uid = (ent->uid * 10) + (*(line++) - '0'); if (!isspace(*line)) { - input_file_complain(f, "expected space after UID"); + input_file_complain(filename, linenum, + "expected space after UID"); goto fail; } @@ -98,7 +105,8 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) /* gid */ if (!isdigit(*line)) { - input_file_complain(f, "expected numeric GID after UID"); + input_file_complain(filename, linenum, + "expected numeric GID after UID"); goto fail; } @@ -108,7 +116,7 @@ static image_entry_t *filelist_mkentry(input_file_t *f, mode_t filetype) line = skipspace(line); /* remove processed data */ - memmove(f->line, line, strlen(line) + 1); + memmove(line, line, strlen(line) + 1); return ent; fail: free(ent->name); @@ -116,9 +124,10 @@ fail: return NULL; } -int filelist_mkdir(input_file_t *f, void *obj) +int filelist_mkdir(char *line, const char *filename, + size_t linenum, void *obj) { - image_entry_t *ent = filelist_mkentry(f, S_IFDIR); + image_entry_t *ent = filelist_mkentry(line,filename,linenum,S_IFDIR); image_entry_t **listptr = obj; if (ent == NULL) @@ -129,22 +138,24 @@ int filelist_mkdir(input_file_t *f, void *obj) return 0; } -int filelist_mkslink(input_file_t *f, void *obj) +int filelist_mkslink(char *line, const char *filename, + size_t linenum, void *obj) { - image_entry_t *ent = filelist_mkentry(f, S_IFLNK); + image_entry_t *ent = filelist_mkentry(line,filename,linenum,S_IFLNK); image_entry_t **listptr = obj; if (ent == NULL) return -1; - ent->data.symlink.target = strdup(f->line); + ent->data.symlink.target = strdup(line); if (ent->data.symlink.target == NULL) { - oom(f); + oom(filename, linenum); goto fail; } if (strlen(ent->data.symlink.target) > 0xFFFF) { - input_file_complain(f, "symlink target too long"); + input_file_complain(filename, linenum, + "symlink target too long"); goto fail; } @@ -156,9 +167,10 @@ fail: return -1; } -int filelist_mkfile(input_file_t *f, void *obj) +int filelist_mkfile(char *line, const char *filename, + size_t linenum, void *obj) { - image_entry_t *ent = filelist_mkentry(f, S_IFREG); + image_entry_t *ent = filelist_mkentry(line,filename,linenum,S_IFREG); image_entry_t **listptr = obj; const char *ptr; struct stat sb; @@ -166,22 +178,22 @@ int filelist_mkfile(input_file_t *f, void *obj) if (ent == NULL) return -1; - if (f->line[0] == '\0') { - ptr = strrchr(f->filename, '/'); + if (line[0] == '\0') { + ptr = strrchr(filename, '/'); if (ptr == NULL) { ent->data.file.location = strdup(ent->name); } else { asprintf(&ent->data.file.location, "%.*s/%s", - (int)(ptr - f->filename), f->filename, + (int)(ptr - filename), filename, ent->name); } } else { - ent->data.file.location = strdup(f->line); + ent->data.file.location = strdup(line); } if (ent->data.file.location == NULL) { - oom(f); + oom(filename, linenum); goto fail; } @@ -192,7 +204,8 @@ int filelist_mkfile(input_file_t *f, void *obj) if (sizeof(off_t) > sizeof(uint64_t) && sb.st_size > (off_t)(~((uint64_t)0))) { - input_file_complain(f, "input file is too big"); + input_file_complain(filename, linenum, + "input file is too big"); goto fail; } @@ -206,17 +219,18 @@ fail: return -1; } -static int filelist_mknod(input_file_t *f, void *obj) +static int filelist_mknod(char *line, const char *filename, + size_t linenum, void *obj) { image_entry_t **listptr = obj, *ent; unsigned int maj, min; char *ptr; - ent = filelist_mkentry(f, S_IFCHR); + ent = filelist_mkentry(line, filename, linenum, S_IFCHR); if (ent == NULL) return -1; - switch (f->line[0]) { + switch (line[0]) { case 'c': case 'C': break; @@ -228,10 +242,10 @@ static int filelist_mknod(input_file_t *f, void *obj) goto fail; } - if (!isspace(f->line[1])) + if (!isspace(line[1])) goto fail; - ptr = f->line + 1; + ptr = line + 1; while (isspace(*ptr)) ++ptr; @@ -245,7 +259,8 @@ static int filelist_mknod(input_file_t *f, void *obj) return 0; fail: image_entry_free(ent); - input_file_complain(f, "error in device specification"); + input_file_complain(filename, linenum, + "error in device specification"); return -1; } diff --git a/main/cmd/pack/pack.h b/main/cmd/pack/pack.h index ace3407..eece7f1 100644 --- a/main/cmd/pack/pack.h +++ b/main/cmd/pack/pack.h @@ -38,11 +38,14 @@ typedef struct { char *name; } pkg_desc_t; -int filelist_mkdir(input_file_t *f, void *obj); +int filelist_mkdir(char *line, const char *filename, + size_t linenum, void *obj); -int filelist_mkslink(input_file_t *f, void *obj); +int filelist_mkslink(char *line, const char *filename, + size_t linenum, void *obj); -int filelist_mkfile(input_file_t *f, void *obj); +int filelist_mkfile(char *line, const char *filename, + size_t linenum, void *obj); int filelist_read(const char *filename, image_entry_t **out);