pkg-utils/lib/util/input_file.c

127 lines
2.0 KiB
C

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "util/input_file.h"
static int prefetch_line(input_file_t *f)
{
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;
}
void cleanup_file(input_file_t *f)
{
fclose(f->f);
free(f->line);
}
int open_file(input_file_t *f, const char *filename)
{
memset(f, 0, sizeof(*f));
f->filename = filename;
f->f = fopen(filename, "r");
if (f->f == NULL) {
perror(f->filename);
return -1;
}
return 0;
}
void input_file_complain(const input_file_t *f, const char *msg)
{
fprintf(stderr, "%s: %zu: %s\n", f->filename, f->linenum, msg);
}
int process_file(input_file_t *f, const keyword_handler_t *handlers,
size_t count, void *obj)
{
size_t i, len;
char *ptr;
int ret;
for (;;) {
ret = prefetch_line(f);
if (ret < 0)
return -1;
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);
return -1;
}
if (handlers[i].handle(f, obj))
return -1;
}
return 0;
}