mirror of
https://github.com/pygos/pkg-utils.git
synced 2024-11-25 14:00:43 +01:00
126 lines
2 KiB
C
126 lines
2 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;
|
|
}
|