dagon/libscomp_amalg.c

111 lines
2.1 KiB
C

#include "libscomp_amalg.h"
#ifdef LIBSCOMP_FREESTANDING
int strcmp(const char *s1, const char *s2) {
while (*s1 == *s2) {
if (!*s1)
break;
s1++;
s2++;
}
return *s1 - *s2;
}
#else
# include <string.h>
#endif
struct libscomp_cmd *hg_bsearch(const char *name,
const struct libscomp_cmd_store *cmds) {
size_t lower = 0, upper = cmds->len-1;
size_t i;
int rel;
while (upper >= lower) {
i = (upper - lower)/2 + lower;
rel = strcmp(name, cmds->arr[i].name);
/* x > cmds[i] */
if (rel > 0)
lower = i + 1;
/* x < cmds[i] */
else if (rel < 0)
upper = i - 1;
else
return &cmds->arr[i];
}
return NULL;
}
int libscomp_exec(const struct libscomp_cmd_store *cmds,
struct libscomp_line *ln, void *ptr) {
struct libscomp_cmd *cmd;
cmd = hg_bsearch(ln->buf[ln->name], cmds);
if (!cmd)
return LIBSCOMP_NOT_FOUND;
return cmd->exec(ln,ptr);
}
enum { LIBSCOMP_READ, LIBSCOMP_DISCARD };
void libscomp_reset(struct libscomp_input *in) {
in->state = LIBSCOMP_READ;
in->len = 0;
}
static enum libscomp_input_r libscomp_parse(
struct libscomp_input *in, struct libscomp_line *line) {
char *s = in->intbuf;
enum libscomp_input_r r = LIBSCOMP_ARG_OVERFLOW;
line->name = (*s == ':');
line->len = 0;
while (line->len < LIBSCOMP_MAXARG) {
line->buf[line->len++] = s;
for (; *s && *s != '\t'; s++);
if (!*s) {
r = LIBSCOMP_COMPLETE;
break;
} else {
*s = 0;
s++;
}
}
libscomp_reset(in);
return r;
}
enum libscomp_input_r libscomp_read(struct libscomp_input *in,
char **s,
struct libscomp_line *line) {
char c;
while ((c = **s)) {
(*s)++;
if (in->state == LIBSCOMP_DISCARD) {
if (c == '\n') {
libscomp_reset(in);
return LIBSCOMP_OVERFLOW;
}
} else {
switch (c) {
case '\n':
in->intbuf[in->len] = 0;
return libscomp_parse(in, line);
default:
in->intbuf[in->len++] = c;
if (in->len == LIBSCOMP_MAXBUF)
in->state = LIBSCOMP_DISCARD;
}
}
}
return LIBSCOMP_MORE;
}