mirror of https://github.com/pygos/pkg-utils.git
7 changed files with 150 additions and 220 deletions
@ -1,23 +1,18 @@
|
||||
#ifndef INPUT_FILE_H |
||||
#define INPUT_FILE_H |
||||
|
||||
#include <stdio.h> |
||||
|
||||
typedef struct { |
||||
FILE *f; |
||||
char *line; |
||||
const char *filename; |
||||
size_t linenum; |
||||
} input_file_t; |
||||
#include <stddef.h> |
||||
|
||||
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 */ |
||||
|
@ -1,122 +1,58 @@
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <errno.h> |
||||
#include <stdio.h> |
||||
#include <ctype.h> |
||||
|
||||
#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'; |
||||
fprintf(stderr, "%s: %zu: %s\n", filename, linenum, msg); |
||||
} |
||||
|
||||
f->line = line; |
||||
f->linenum += 1; |
||||
struct userdata { |
||||
const keyword_handler_t *handlers; |
||||
size_t count; |
||||
void *obj; |
||||
}; |
||||
|
||||
for (ptr = f->line; isspace(*ptr); ++ptr) |
||||
; |
||||
static int handle_line(void *usr, const char *filename, |
||||
size_t linenum, char *line) |
||||
{ |
||||
struct userdata *u = usr; |
||||
size_t i, len; |
||||
|
||||
if (*ptr == '\0' || *ptr == '#') |
||||
goto retry; |
||||
while (isspace(*line)) |
||||
++line; |
||||
|
||||
if (ptr != f->line) |
||||
memmove(f->line, ptr, strlen(ptr) + 1); |
||||
if (*line == '\0' || *line == '#') |
||||
return 0; |
||||
|
||||
ptr = f->line + strlen(f->line); |
||||
for (i = 0; i < u->count; ++i) { |
||||
len = strlen(u->handlers[i].name); |
||||
|
||||
while (ptr > f->line && isspace(ptr[-1])) |
||||
--ptr; |
||||
*ptr = '\0'; |
||||
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 (f->line[0] == '\0') |
||||
goto retry; |
||||
return 0; |
||||
} |
||||
if (i == u->count) { |
||||
fprintf(stderr, "%s: %zu: unknown keyword\n", |
||||
filename, linenum); |
||||
return -1; |
||||
} |
||||
|
||||
void input_file_complain(const input_file_t *f, const char *msg) |
||||
{ |
||||
fprintf(stderr, "%s: %zu: %s\n", f->filename, f->linenum, msg); |
||||
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; |
||||
|
||||
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; |
||||
} |
||||
struct userdata u = { handlers, count, obj }; |
||||
|
||||
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); |
||||
} |
||||
|
Loading…
Reference in new issue