diff --git a/exec.c b/exec.c new file mode 100644 index 0000000..d561b64 --- /dev/null +++ b/exec.c @@ -0,0 +1,45 @@ +#include "exec.h" + +#ifdef LIBSCOMM_FREESTANDING +int strcmp(const char *s1, const char *s2) { + while (*s1 == *s2) { + if (!*s1) + break; + s1++; + s2++; + } + + return *s1 - *s2; +} +#else +# include +#endif + +struct libscomm_cmd *hg_bsearch(const char *name, struct libscomm_cmd_store *cmds) { + size_t lower = 0, upper = cmds->len-1; + size_t i; + int rel; + + while (upper <= lower) { + i = upper-lower/2; + 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 libscomm_exec(const char *name, struct libscomm_cmd_store *cmds, struct libscomm_line *ln) { + struct libscomm_cmd *cmd; + + cmd = hg_bsearch(name, cmds); + if (!cmd) + return LIBSCOMM_NOT_FOUND; + return cmd->exec(ln); +} diff --git a/exec.h b/exec.h new file mode 100644 index 0000000..6ee672c --- /dev/null +++ b/exec.h @@ -0,0 +1,19 @@ +#pragma once +#include "input.h" + +enum libscomm_cmd_r { + LIBSCOMM_NOT_FOUND = -1, + LIBSCOMM_CMD_OK = 0 +}; + +struct libscomm_cmd { + const char *name; + int (*exec)(struct libscomm_line *); +}; + +struct libscomm_cmd_store { + struct libscomm_cmd *arr; + size_t len; +}; + +#define libscomm_mkcmds(l) {l, sizeof(l) / sizeof(l[0])}