From 1d26348bb013552326c394ac69033ff3323e18e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 4 Dec 2015 22:18:29 +0100 Subject: [PATCH 01/43] iomux_signal.h and wqueue.h should be usable in C++. Add to IOMux doxygen group too. --- include/ucore/iomux_signal.h | 15 +++++++++++++++ include/ucore/wqueue.h | 37 +++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/include/ucore/iomux_signal.h b/include/ucore/iomux_signal.h index 43e014b..05e18d6 100644 --- a/include/ucore/iomux_signal.h +++ b/include/ucore/iomux_signal.h @@ -2,6 +2,15 @@ #define UC_IOMUX_SIGNAL_H_ #include "ucore/iomux.h" + +/** @addtogroup IOMux + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + /** Callback signature for handling unix signals. * @param mux associated mux * @param signo unix signal number @@ -45,4 +54,10 @@ int iomux_register_unixsignal(struct IOMux *mux, */ int iomux_unregister_unixsignal(struct IOMux *mux, int signo); +#ifdef __cplusplus +} +#endif + +/** @} (addtogroup)*/ + #endif diff --git a/include/ucore/wqueue.h b/include/ucore/wqueue.h index 3a460dd..d34a7bc 100644 --- a/include/ucore/wqueue.h +++ b/include/ucore/wqueue.h @@ -4,6 +4,17 @@ #include "mbuf.h" #include "iomux.h" +/** @addtogroup IOMux + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Return code from users write callback + */ enum UC_WQ_RESULT { /** INdicates the MBuf was fully processed and can be freed*/ UC_WQ_DONE = 1, @@ -51,15 +62,33 @@ typedef enum UC_WQ_RESULT (*wqueue_write_cb)(struct IOMux *mux, struct IOMuxFD * */ typedef enum UC_WQ_RESULT (*wqueue_read_cb)(struct IOMux *mux, struct IOMuxFD *fd); -/** Represents a queue of data to write. +/** + * Represents a queue of data to write. + * UCWQueue replaces a raw IOMuxFD, and manages a queue + * of data to write, held as a list of struct MBuf. + * See also uc_wqueue_init + * */ struct UCWQueue { + /** Underlying IOMuxFD. This member needs to be registered + * with an IOMux, see the description of uc_wqueue_init + */ struct IOMuxFD fd; + /** Linked list of struct MBuf + */ struct TailQ queue; + /** Associated mux + */ struct IOMux *mux; + /** Users callback for read events + */ wqueue_read_cb read_cb; + /** Users callback for write events + */ wqueue_write_cb write_cb; + /** Current number of queued struct MBuf + */ unsigned int queue_len; }; @@ -120,4 +149,10 @@ int uc_wqueue_enqueue(struct UCWQueue *wqueue, struct MBuf *mbuf); */ int uc_wqueue_flush(struct UCWQueue *wqueue); +#ifdef __cplusplus +} +#endif + +/** @} (addtogroup)*/ + #endif From 94dcd522aad89abec12ca473a43964fe5783ab39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 4 Dec 2015 22:25:57 +0100 Subject: [PATCH 02/43] Pass the wqueue directly to the wqueue callback functions --- include/ucore/wqueue.h | 9 +++++++-- src/wqueue.c | 4 ++-- test/console_print.c | 10 +++++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/ucore/wqueue.h b/include/ucore/wqueue.h index d34a7bc..636d873 100644 --- a/include/ucore/wqueue.h +++ b/include/ucore/wqueue.h @@ -24,6 +24,8 @@ enum UC_WQ_RESULT { UC_WQ_ABORT = -1 }; +struct UCWQueue; + /** * Callback that will be called when data can be written to the fd. * The return value from this function must be strictly followed. @@ -49,7 +51,9 @@ enum UC_WQ_RESULT { * for this event. * */ -typedef enum UC_WQ_RESULT (*wqueue_write_cb)(struct IOMux *mux, struct IOMuxFD *fd, struct MBuf *mbuf); +typedef enum UC_WQ_RESULT (*wqueue_write_cb)(struct IOMux *mux, + struct UCWQueue *wqueue, + struct MBuf *mbuf); /** * Callback when read events are indicated. @@ -60,7 +64,8 @@ typedef enum UC_WQ_RESULT (*wqueue_write_cb)(struct IOMux *mux, struct IOMuxFD * * @param mux associated IOMux * @param the fd of the current wqueue */ -typedef enum UC_WQ_RESULT (*wqueue_read_cb)(struct IOMux *mux, struct IOMuxFD *fd); +typedef enum UC_WQ_RESULT (*wqueue_read_cb)(struct IOMux *mux, + struct UCWQueue *wqueue); /** * Represents a queue of data to write. diff --git a/src/wqueue.c b/src/wqueue.c index 5526d78..6ad49e6 100644 --- a/src/wqueue.c +++ b/src/wqueue.c @@ -15,7 +15,7 @@ static int uc_wqueue_handle_write(struct UCWQueue *wqueue) q = UC_TAILQ_FIRST(&wqueue->queue); mbuf = UC_TAILQ_CONTAINER(q, struct MBuf, entry); - rc = wqueue->write_cb(mux, fd, mbuf); + rc = wqueue->write_cb(mux, wqueue, mbuf); if (rc <= 0) { //NOTE for rc < 0, nothing can touch the wqueue or fd //any more, as it might been free'd @@ -58,7 +58,7 @@ static void uc_wqueue_cb(struct IOMux *mux, struct IOMuxFD *fd, unsigned int wha if (rc >= 0 && what & MUX_EV_READ) { - rc = wqueue->read_cb(mux, fd); + rc = wqueue->read_cb(mux, wqueue); //NOTE - can't touch the wqueue or fd after this point, //as it might been free'd } diff --git a/test/console_print.c b/test/console_print.c index a22d562..3e15e99 100644 --- a/test/console_print.c +++ b/test/console_print.c @@ -9,7 +9,7 @@ #include -int stdout_read(struct IOMux *mux, struct IOMuxFD *fd) +int stdout_read(struct IOMux *mux, struct UCWQueue *wqueue) { return 1; } @@ -24,9 +24,9 @@ void stdin_read_cb(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event) printf("Read %d bytes\n", len); if (len <= 0) { uc_mbuf_free(mbuf); - iomux_unregister_fd(mux, fd); - uc_wqueue_clear(wqueue); iomux_unregister_fd(mux, &wqueue->fd); + uc_wqueue_clear(wqueue); + iomux_unregister_fd(mux, fd); return; } @@ -44,7 +44,7 @@ struct IOMuxFD stdin_fd = { }; -int stdout_write(struct IOMux *mux, struct IOMuxFD *fd, struct MBuf *mbuf) +int stdout_write(struct IOMux *mux, struct UCWQueue *wqueue, struct MBuf *mbuf) { uint32_t len; ssize_t wlen; @@ -52,7 +52,7 @@ int stdout_write(struct IOMux *mux, struct IOMuxFD *fd, struct MBuf *mbuf) len = uc_mbuf_len(mbuf); data = uc_mbuf_pull(mbuf, len); - wlen = write(fd->fd, data, len); + wlen = write(wqueue->fd.fd, data, len); if (wlen < 0) { if (errno != EWOULDBLOCK) { From c87137cb4f08e870220aa02d8847852475c28a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 10 Dec 2015 12:29:47 +0100 Subject: [PATCH 03/43] Fix redundant setting of events in iomux_update_events --- src/iomux_impl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/iomux_impl.c b/src/iomux_impl.c index e41cfa1..ae3a083 100644 --- a/src/iomux_impl.c +++ b/src/iomux_impl.c @@ -151,7 +151,6 @@ int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd, unsigned int what if (fd->what != what) { fd->what = what; rc = mux->ops.update_events_impl(mux, fd); - fd->what = what; } return rc; From 44d8d10d354003c017e5cec4bb5509bd682e15af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 10 Dec 2015 12:31:20 +0100 Subject: [PATCH 04/43] Exampel code for pipe --- test/iomux_pipe_close.c | 80 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 test/iomux_pipe_close.c diff --git a/test/iomux_pipe_close.c b/test/iomux_pipe_close.c new file mode 100644 index 0000000..11590e2 --- /dev/null +++ b/test/iomux_pipe_close.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ucore/iomux.h" + + + +void in_cb(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event) +{ + + char buf[16]; + ssize_t rc; + + rc = read(fd->fd, buf, sizeof buf); + printf("Read returned %ld\n", (long)rc); + if (rc <= 0) { + if (rc == -1 && errno == EAGAIN) { + return; + } else if (rc == -1) { + perror("read"); + } + return; + } + iomux_unregister_fd(mux, fd); + close(fd->fd); + +} + +void out_cb(struct IOMux *mux, struct IOMuxFD *fd, unsigned int event) +{ + char str[] = "hello"; + ssize_t rc; + + rc = write(fd->fd, str, strlen(str)); + printf("write returned %ld\n", (long)rc); + if (rc <= 0) { + if (rc == -1 && errno == EAGAIN) { + return; + } else { + perror("write"); + } + iomux_unregister_fd(mux, fd); + } +} + + +int main(int argc, char *argv[]) +{ + int pipes[2]; + pipe(pipes); + uc_set_nonblocking(pipes[0]); + uc_set_nonblocking(pipes[1]); + + struct IOMuxFD rfd= { + .fd = pipes[0], + .what = MUX_EV_READ, + .callback = in_cb, + }; + + struct IOMuxFD wfd= { + .fd = pipes[1], + .what = MUX_EV_WRITE, + .callback = out_cb, + }; + + signal(SIGPIPE, SIG_IGN); + + struct IOMux *mux = iomux_create(IOMUX_TYPE_SELECT); + iomux_register_fd(mux, &rfd); + iomux_register_fd(mux, &wfd); + + iomux_run(mux); + + return 0; +} + From 8adec5408e6b16839281b9409a8c152324f6f704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 8 Dec 2015 18:52:25 +0100 Subject: [PATCH 05/43] Progress on cmd --- src/cmd/cmd.c | 368 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 339 insertions(+), 29 deletions(-) diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index 9459958..59aa421 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -1,54 +1,364 @@ #include +#include +#include +#include +#include +#include "ucore/string.h" +#include "ucore/utils.h" + +//max words in a single command +#define UC_CMD_MAX_WORDS 32 enum UCCmdRc { /**Executed ok */ - UC_CMD_OK, + UC_CMDRC_OK, /**Executed with warning */ - UC_CMD_WARNING, + UC_CMDRC_WARNING, /*Not executed, incomplete command */ - UC_CMD_INCOMPLETE, + UC_CMDRC_INCOMPLETE, + /*Command cann't uniquely be distinguished */ + UC_CMDRC_AMBIGUOUS, /*Not executed, generic error */ - UC_CMD_ERROR, + UC_CMDRC_ERROR, }; typedef enum UCCmdRc (*uc_cmd_handler)(int narg, char *args[]); -typedef void (*uc_cmd_write_cfg)(void); -#define UC_CMD_FL_HIDDEN (1 << 0) - -struct UCCmdNode; -struct UCCmdDef; - -struct UCCmdSettings { - const char *name; - const char *version; - const char *boot_cfg_file; - - struct UCCmdNode *initial_node; - struct UCCmdNode *node_head; +enum UCCmdType { + UC_CMD_ROOT = 1, + UC_CMD_KEYWORD, + UC_CMD_LIST, + UC_CMD_END, }; struct UCCmdNode { - int id; - uc_cmd_write_cfg write_func; - struct UCCmdDef *cmd_head; //linked list of UCCmdDef - struct UCCmdNode *next; + enum UCCmdType type; + uint32_t flags; + void *data; + struct UCCmdNode *next; //next at same level + struct UCCmdNode *child; +}; + +//for UC_CMD_LIST, +struct UCCmdList { + char *word; + struct UCCmdList *next; +}; + +struct UCCmdRunner { + struct UCCmdNode *root_node; + struct UCCmdNode _root; }; struct UCCmdDef { const char *cmd; - const char **help; - size_t cmd_len; - uc_cmd_handler cb; + uc_cmd_handler callback; uint32_t flags; struct UCCmdDef *next; }; -void uc_cmd_init(const char *app_name, const char *version); -int uc_cmd_read_config(const char *filename); -void uc_cmd_set_configfile(const char *filename); -void uc_cmd_add_cmd(struct UCCmdDef *cmd, int parent_node_id); -void uc_cmd_set_default_node(int node_id); +struct UCCmdTokenizer { + char *cmd_copy; + char *cmd_words[UC_CMD_MAX_WORDS]; + int num_words; +}; +static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd) +{ + t->num_words = 0; + t->cmd_copy = strdup(cmd); + if (t->cmd_copy == NULL) { + assert(t->cmd_copy); + return; + } + + t->num_words = getfields(t->cmd_copy, + t->cmd_words, + ARRAY_SIZE(t->cmd_words), + 1, + "\r\n\t\v "); +} + +static void uc_cmd_tokenize_destroy(struct UCCmdTokenizer *t) +{ + free(t->cmd_copy); + t->num_words = 0; + t->cmd_copy = NULL; +} + +void uc_cmd_runner_init(struct UCCmdRunner *r) +{ + memset(r, 0, sizeof *r); + r->root_node = &r->_root; + r->_root.type = UC_CMD_KEYWORD; +} + +static void uc_cmd_list_free(struct UCCmdList *l) +{ + struct UCCmdList *next; + + while (l) { + next = l->next; + free(l->word); + free(l); + l = next; + } +} + +void uc_cmd_node_dealloc(struct UCCmdNode *n) +{ + struct UCCmdNode *next; + while (n) { + uc_cmd_node_dealloc(n->child); + next = n->next; + if (n->type == UC_CMD_KEYWORD) { + free(n->data); + } else if (n->type == UC_CMD_LIST) { + uc_cmd_list_free(n->data); + } + free(n); + n = next; + } +} + +void uc_cmd_runner_destroy(struct UCCmdRunner *r) +{ + uc_cmd_node_dealloc(r->root_node->child); + r->root_node->child = NULL; +} + + + +struct UCCmdNode *uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags) +{ + struct UCCmdNode *n; + + n = calloc(1, sizeof *n); + if (n == NULL) { + return NULL; + } + + n->type = type; + n->data = data; + n->flags = flags; + + return n; +} + +static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word) +{ + size_t word_len; + + if (word == NULL || word[0] == 0) { + return 0; + } + + word_len = strlen(word); + + if (n->type == UC_CMD_KEYWORD) { + return strncmp(word, n->data, word_len) == 0; + } + + if (n->type == UC_CMD_LIST) { + struct UCCmdList *l = n->data; + + assert(l); + assert(l->word); + + while (l) { + if (strncmp(word, n->data, word_len) == 0) { + return 1; + } + l = l->next; + } + return 0; + } + + + return 0; + +} + +static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word) +{ + struct UCCmdNode *new_node; + struct UCCmdNode **location = &parent->child; + + assert(parent); + + while (*location) { + struct UCCmdNode *n = *location; + if (uc_cmd_node_match(n, word)) { + return *location; + } + location = &n->next; + } + + new_node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0); + *location = new_node; + + return new_node; +} + +int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) +{ + struct UCCmdNode *node = r->root_node; + struct UCCmdNode *new_node; + struct UCCmdTokenizer t; + + uc_cmd_tokenize(&t, cmd->cmd); + if (t.num_words <= 0) { + uc_cmd_tokenize_destroy(&t); + return -1; + } + + for (int i = 0; i < t.num_words; i++) { + node = uc_cmd_add(node, t.cmd_words[i]); + } + + //TODO, check for duplicate command here. + + new_node = uc_cmd_node_alloc(UC_CMD_END, cmd, 0); + if (new_node == NULL) { + return -1; + } + new_node->next = node->child; + node->child = new_node; + + + uc_cmd_tokenize_destroy(&t); + + return 0; +} + + +enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) +{ + + struct UCCmdNode *node = r->root_node->child; + struct UCCmdTokenizer t; + enum UCCmdRc rc = UC_CMDRC_ERROR; + + //make a copy since getfields destroys the original string + uc_cmd_tokenize(&t, cmd_line); + if (t.num_words <= 0) { + uc_cmd_tokenize_destroy(&t); + return rc; + } + + //match the commands towards the command tree + // + for (int i = 0; i < t.num_words && node; i++) { + int n_found = 0; + struct UCCmdNode *found = NULL; + + while (node) { + if (uc_cmd_node_match(node, t.cmd_words[i])) { + found = node; + n_found++; + } + node = node->next; + } + + if (n_found == 1) { + node = found->child; + } else if (n_found > 1) { + return UC_CMDRC_AMBIGUOUS; + } + } + + // Now check the current level for any UC_CMD_END + // which indicates a complete command + while (node) { + if (node->type == UC_CMD_END) { + break; + } + node = node->next; + } + + if (node != NULL) { + struct UCCmdDef *cmd = node->data; + rc = cmd->callback(0, NULL); + } else { + rc = UC_CMDRC_INCOMPLETE; + } + + uc_cmd_tokenize_destroy(&t); + + return rc; +} + + +enum UCCmdRc cmd1_cb(int narg, char *args[]) +{ + puts(__func__); + + return UC_CMDRC_OK; +} + +enum UCCmdRc cmd2_cb(int narg, char *args[]) +{ + puts(__func__); + + return UC_CMDRC_OK; +} + +enum UCCmdRc cmd3_cb(int narg, char *args[]) +{ + puts(__func__); + + return UC_CMDRC_OK; +} + + + + +int main(int argc, char *argv[]) +{ + char line[128]; + struct UCCmdRunner r; + struct UCCmdDef cmd1 = { + "show all", + cmd1_cb, + 0, + NULL + }; + + struct UCCmdDef cmd2 = { + "show empty", + cmd2_cb, + 0, + NULL + }; + + struct UCCmdDef cmd3 = { + "show empty bottles", + cmd3_cb, + 0, + NULL + }; + + uc_cmd_runner_init(&r); + uc_cmd_install(&r, &cmd1); + uc_cmd_install(&r, &cmd2); + uc_cmd_install(&r, &cmd3); + + uc_cmd_run(&r, "show all"); + uc_cmd_run(&r, "show empty"); + uc_cmd_run(&r, "show empty bottles"); + /* + while (fgets(line,sizeof line, stdin)) { + enum UCCmdRc rc = uc_cmd_run(&r, line); + if (rc != UC_CMDRC_OK) { + printf("Command failed with code %d\n", rc); + } + } + */ + + uc_cmd_runner_destroy(&r); + + + return 1; +} From d4619418f0b1ba8acbc7f8edab908c0b10f07a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 8 Dec 2015 23:59:39 +0100 Subject: [PATCH 06/43] Add support for lists --- src/cmd/cmd.c | 72 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index 59aa421..cf83793 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -65,8 +65,9 @@ struct UCCmdTokenizer { int num_words; }; -static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd) +static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const char *delim) { + t->num_words = 0; t->cmd_copy = strdup(cmd); if (t->cmd_copy == NULL) { @@ -74,11 +75,15 @@ static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd) return; } + if (delim == NULL) { + delim = "\r\n\t\v "; + } + t->num_words = getfields(t->cmd_copy, t->cmd_words, ARRAY_SIZE(t->cmd_words), 1, - "\r\n\t\v "); + delim); } static void uc_cmd_tokenize_destroy(struct UCCmdTokenizer *t) @@ -147,6 +152,37 @@ struct UCCmdNode *uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t fl return n; } +struct UCCmdNode *uc_cmd_node_create(const char *word) +{ + struct UCCmdNode *node = NULL; + + if (word[0] == '(') { //list (foo|bar|baz) + struct UCCmdTokenizer t; + + uc_cmd_tokenize(&t, word, "() |\t\v"); + if (t.num_words > 0) { + struct UCCmdList *list = NULL; + + for (int i = t.num_words - 1; i >= 0; i--) { + struct UCCmdList *l = calloc(1, sizeof *l); + + l->word = strdup(t.cmd_words[i]); + l->next = list; + list = l; + } + node = uc_cmd_node_alloc(UC_CMD_LIST, list, 0); + } + + uc_cmd_tokenize_destroy(&t); + } else { + node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0); + } + + + return node; + +} + static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word) { size_t word_len; @@ -168,15 +204,13 @@ static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word) assert(l->word); while (l) { - if (strncmp(word, n->data, word_len) == 0) { + if (strncmp(word, l->word, word_len) == 0) { return 1; } l = l->next; } - return 0; } - return 0; } @@ -187,16 +221,29 @@ static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word) struct UCCmdNode **location = &parent->child; assert(parent); - + + new_node = uc_cmd_node_create(word); + if (new_node == NULL) { + return NULL; + } + + while (*location) { struct UCCmdNode *n = *location; + + if (new_node->type != UC_CMD_KEYWORD && n->type != UC_CMD_END) { + //we don't support combinations of keywords and variables + //at the same level. + uc_cmd_node_dealloc(new_node); + return NULL; + } + //TODO check for ambiguous word (e.g. add "short" when "shorter" already exists) if (uc_cmd_node_match(n, word)) { return *location; } location = &n->next; } - new_node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0); *location = new_node; return new_node; @@ -208,7 +255,7 @@ int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) struct UCCmdNode *new_node; struct UCCmdTokenizer t; - uc_cmd_tokenize(&t, cmd->cmd); + uc_cmd_tokenize(&t, cmd->cmd, NULL); if (t.num_words <= 0) { uc_cmd_tokenize_destroy(&t); return -1; @@ -216,6 +263,9 @@ int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) for (int i = 0; i < t.num_words; i++) { node = uc_cmd_add(node, t.cmd_words[i]); + if (node == NULL) { + return -2; + } } //TODO, check for duplicate command here. @@ -242,7 +292,7 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) enum UCCmdRc rc = UC_CMDRC_ERROR; //make a copy since getfields destroys the original string - uc_cmd_tokenize(&t, cmd_line); + uc_cmd_tokenize(&t, cmd_line, NULL); if (t.num_words <= 0) { uc_cmd_tokenize_destroy(&t); return rc; @@ -334,7 +384,7 @@ int main(int argc, char *argv[]) }; struct UCCmdDef cmd3 = { - "show empty bottles", + "show empty (bottle|glass)", cmd3_cb, 0, NULL @@ -347,7 +397,7 @@ int main(int argc, char *argv[]) uc_cmd_run(&r, "show all"); uc_cmd_run(&r, "show empty"); - uc_cmd_run(&r, "show empty bottles"); + uc_cmd_run(&r, "show empty bottle"); /* while (fgets(line,sizeof line, stdin)) { enum UCCmdRc rc = uc_cmd_run(&r, line); From 5d54702501822c14285f93af01ee6d9464531d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 10 Dec 2015 18:11:37 +0100 Subject: [PATCH 07/43] Improve docs of strvec --- include/ucore/strvec.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/ucore/strvec.h b/include/ucore/strvec.h index 4bbe887..4e2c174 100644 --- a/include/ucore/strvec.h +++ b/include/ucore/strvec.h @@ -38,7 +38,7 @@ void uc_strv_init(struct UCStrv *strv); int uc_strv_grow(struct UCStrv *strv, size_t cnt); /** - * Expand the UCStrv to hold attleast 1 more item if needed + * If needed, grow the UCStrv to hold atleast 1 more item. * * @param strv UCStrv to expand * @return 0 on success, otherwise failure @@ -46,7 +46,7 @@ int uc_strv_grow(struct UCStrv *strv, size_t cnt); int uc_strv_check_expand(struct UCStrv *strv); /** - * Append a string to the UCStrv, the string will be copied in + * Append a string to the UCStrv, the string will be copied in. * * @param strv UCStrv to append to * @param str String to append, the string will be copied. @@ -55,7 +55,7 @@ int uc_strv_check_expand(struct UCStrv *strv); int uc_strv_append(struct UCStrv *strv, const char *restrict str); /** - * Append a string to the strvec, nocopy variang. + * Append a string to the strvec without making a copy of the string. * The string shold be dynamically allocated, as * destroying the UCStrv will free() all items. * @@ -67,7 +67,7 @@ int uc_strv_append_nocopy(struct UCStrv *strv, char *restrict str); /** * Append a NULL pointer to the UCStrv, (cnt is not increased, - * so another _appended item will overwrite this NULL terminator) + * so another appended item will overwrite this NULL terminator) * * @param strv UCStrv to append to * @return 0 on success, otherwise failure From 9b70b6472997d2992352c1c0179a63ca47990300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 10 Dec 2015 18:51:51 +0100 Subject: [PATCH 08/43] Implement argument collecting --- src/cmd/cmd.c | 124 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 44 deletions(-) diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index cf83793..bfcf4e2 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -1,9 +1,11 @@ #include +#include #include #include #include #include #include "ucore/string.h" +#include "ucore/strvec.h" #include "ucore/utils.h" //max words in a single command @@ -22,12 +24,13 @@ enum UCCmdRc { UC_CMDRC_ERROR, }; -typedef enum UCCmdRc (*uc_cmd_handler)(int narg, char *args[]); +typedef enum UCCmdRc (*uc_cmd_handler)(const struct UCStrv *args); enum UCCmdType { UC_CMD_ROOT = 1, UC_CMD_KEYWORD, UC_CMD_LIST, + UC_CMD_STRING, UC_CMD_END, }; @@ -100,18 +103,6 @@ void uc_cmd_runner_init(struct UCCmdRunner *r) r->_root.type = UC_CMD_KEYWORD; } -static void uc_cmd_list_free(struct UCCmdList *l) -{ - struct UCCmdList *next; - - while (l) { - next = l->next; - free(l->word); - free(l); - l = next; - } -} - void uc_cmd_node_dealloc(struct UCCmdNode *n) { struct UCCmdNode *next; @@ -121,7 +112,10 @@ void uc_cmd_node_dealloc(struct UCCmdNode *n) if (n->type == UC_CMD_KEYWORD) { free(n->data); } else if (n->type == UC_CMD_LIST) { - uc_cmd_list_free(n->data); + uc_strv_destroy(n->data); + free(n->data); + } else if (n->type == UC_CMD_STRING) { + free(n->data); } free(n); n = next; @@ -161,19 +155,19 @@ struct UCCmdNode *uc_cmd_node_create(const char *word) uc_cmd_tokenize(&t, word, "() |\t\v"); if (t.num_words > 0) { - struct UCCmdList *list = NULL; + struct UCStrv *v = malloc(sizeof *v); - for (int i = t.num_words - 1; i >= 0; i--) { - struct UCCmdList *l = calloc(1, sizeof *l); + uc_strv_init(v); - l->word = strdup(t.cmd_words[i]); - l->next = list; - list = l; + for (int i = 0 ; i < t.num_words; i++) { + uc_strv_append(v, t.cmd_words[i]); } - node = uc_cmd_node_alloc(UC_CMD_LIST, list, 0); + node = uc_cmd_node_alloc(UC_CMD_LIST, v, 0); } uc_cmd_tokenize_destroy(&t); + } else if (isupper(word[0])) { + node = uc_cmd_node_alloc(UC_CMD_STRING, strdup(word), 0); } else { node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0); } @@ -183,7 +177,7 @@ struct UCCmdNode *uc_cmd_node_create(const char *word) } -static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word) +static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *args) { size_t word_len; @@ -194,21 +188,29 @@ static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word) word_len = strlen(word); if (n->type == UC_CMD_KEYWORD) { - return strncmp(word, n->data, word_len) == 0; - } - if (n->type == UC_CMD_LIST) { - struct UCCmdList *l = n->data; + if (strncmp(word, n->data, word_len) == 0) { + return 1; + } + } else if (n->type == UC_CMD_LIST) { + struct UCStrv *v = n->data; - assert(l); - assert(l->word); + assert(v); - while (l) { - if (strncmp(word, l->word, word_len) == 0) { + for(size_t i = 0; i < v->cnt; i++) { + + if (strncmp(word, v->strings[i], word_len) == 0) { + if (args != NULL) { + uc_strv_append(args, v->strings[i]); + } return 1; } - l = l->next; } + } else if (n->type == UC_CMD_STRING) { + if (args != NULL) { + uc_strv_append(args, word); + } + return 1; } return 0; @@ -218,7 +220,7 @@ static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word) static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word) { struct UCCmdNode *new_node; - struct UCCmdNode **location = &parent->child; + struct UCCmdNode **iter = &parent->child; assert(parent); @@ -228,8 +230,8 @@ static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word) } - while (*location) { - struct UCCmdNode *n = *location; + while (*iter) { + struct UCCmdNode *n = *iter; if (new_node->type != UC_CMD_KEYWORD && n->type != UC_CMD_END) { //we don't support combinations of keywords and variables @@ -238,13 +240,14 @@ static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word) return NULL; } //TODO check for ambiguous word (e.g. add "short" when "shorter" already exists) - if (uc_cmd_node_match(n, word)) { - return *location; + if (new_node->type == UC_CMD_KEYWORD && uc_cmd_node_match(n, word, NULL)) { + uc_cmd_node_dealloc(new_node); + return *iter; } - location = &n->next; + iter = &n->next; } - *location = new_node; + *iter = new_node; return new_node; } @@ -290,6 +293,9 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) struct UCCmdNode *node = r->root_node->child; struct UCCmdTokenizer t; enum UCCmdRc rc = UC_CMDRC_ERROR; + struct UCStrv args = UC_STRV_INITIALIZER; //arguments to the callback function + + //make a copy since getfields destroys the original string uc_cmd_tokenize(&t, cmd_line, NULL); @@ -305,7 +311,7 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) struct UCCmdNode *found = NULL; while (node) { - if (uc_cmd_node_match(node, t.cmd_words[i])) { + if (uc_cmd_node_match(node, t.cmd_words[i], &args)) { found = node; n_found++; } @@ -315,6 +321,8 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) if (n_found == 1) { node = found->child; } else if (n_found > 1) { + uc_strv_destroy(&args); + uc_cmd_tokenize_destroy(&t); return UC_CMDRC_AMBIGUOUS; } } @@ -330,38 +338,57 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) if (node != NULL) { struct UCCmdDef *cmd = node->data; - rc = cmd->callback(0, NULL); + rc = cmd->callback(&args); } else { rc = UC_CMDRC_INCOMPLETE; } + uc_strv_destroy(&args); uc_cmd_tokenize_destroy(&t); return rc; } -enum UCCmdRc cmd1_cb(int narg, char *args[]) +void print_args(const struct UCStrv *args) +{ + for (size_t i = 0; i < args->cnt; i++) { + printf("arg %zu:%s\n", i, args->strings[i]); + } +} +enum UCCmdRc cmd1_cb(const struct UCStrv *args) { puts(__func__); + print_args(args); return UC_CMDRC_OK; } -enum UCCmdRc cmd2_cb(int narg, char *args[]) +enum UCCmdRc cmd2_cb(const struct UCStrv *args) { puts(__func__); + print_args(args); return UC_CMDRC_OK; } -enum UCCmdRc cmd3_cb(int narg, char *args[]) +enum UCCmdRc cmd3_cb(const struct UCStrv *args) { puts(__func__); + print_args(args); return UC_CMDRC_OK; } +enum UCCmdRc cmd4_cb(const struct UCStrv *args) +{ + puts(__func__); + print_args(args); + + return UC_CMDRC_OK; +} + + @@ -390,14 +417,23 @@ int main(int argc, char *argv[]) NULL }; + struct UCCmdDef cmd4 = { + "delete file NAME", + cmd4_cb, + 0, + NULL + }; + uc_cmd_runner_init(&r); uc_cmd_install(&r, &cmd1); uc_cmd_install(&r, &cmd2); uc_cmd_install(&r, &cmd3); + uc_cmd_install(&r, &cmd4); + uc_cmd_run(&r, "delete file /tmp/a"); uc_cmd_run(&r, "show all"); uc_cmd_run(&r, "show empty"); - uc_cmd_run(&r, "show empty bottle"); + uc_cmd_run(&r, "sh emp g"); /* while (fgets(line,sizeof line, stdin)) { enum UCCmdRc rc = uc_cmd_run(&r, line); From db78689015b2eab47a56bc8c0cbffb2146c08380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 10 Dec 2015 19:13:16 +0100 Subject: [PATCH 09/43] Add uc_strv_reverse --- include/ucore/strvec.h | 5 +++++ src/strvec.c | 11 +++++++++++ test/test_strv.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/include/ucore/strvec.h b/include/ucore/strvec.h index 4e2c174..d4cf7f9 100644 --- a/include/ucore/strvec.h +++ b/include/ucore/strvec.h @@ -101,6 +101,11 @@ void uc_strv_destroy(struct UCStrv *strv); */ int uc_strv_append_all(struct UCStrv *restrict a, struct UCStrv *restrict b, int copy); +/** Reverse the order of strings in a UCStrv + * + * @param strv strv to reverse. + */ +void uc_strv_reverse(struct UCStrv *strv); #ifdef __cplusplus } #endif diff --git a/src/strvec.c b/src/strvec.c index 1e9f00a..3ed3d8e 100644 --- a/src/strvec.c +++ b/src/strvec.c @@ -130,3 +130,14 @@ int uc_strv_append_all(struct UCStrv *restrict a, struct UCStrv *restrict b, int return 0; } +void uc_strv_reverse(struct UCStrv *strv) +{ + for (size_t i = 0; i < strv->cnt / 2; i++) { + + size_t k = strv->cnt - i - 1; + char *tmp = strv->strings[i]; + + strv->strings[i] = strv->strings[k]; + strv->strings[k] = tmp; + } +} diff --git a/test/test_strv.c b/test/test_strv.c index b9100b4..311665c 100644 --- a/test/test_strv.c +++ b/test/test_strv.c @@ -123,6 +123,44 @@ START_TEST (test_strv_append_all_nocopy) END_TEST +START_TEST (test_strv_reverse) + struct UCStrv strv; + + uc_strv_init(&strv); + + uc_strv_append(&strv, "string1"); + + uc_strv_reverse(&strv); + ck_assert_str_eq("string1", strv.strings[0]); + + uc_strv_destroy(&strv); + + uc_strv_init(&strv); + + uc_strv_append(&strv, "string1"); + uc_strv_append(&strv, "string2"); + + uc_strv_reverse(&strv); + ck_assert_str_eq("string2", strv.strings[0]); + ck_assert_str_eq("string1", strv.strings[1]); + + uc_strv_destroy(&strv); + + uc_strv_init(&strv); + + uc_strv_append(&strv, "string1"); + uc_strv_append(&strv, "string2"); + uc_strv_append(&strv, "string3"); + + uc_strv_reverse(&strv); + ck_assert_str_eq("string3", strv.strings[0]); + ck_assert_str_eq("string2", strv.strings[1]); + ck_assert_str_eq("string1", strv.strings[2]); + + uc_strv_destroy(&strv); + + +END_TEST Suite *strv_suite(void) { @@ -135,6 +173,7 @@ Suite *strv_suite(void) tcase_add_test(tc, test_strv_null_terminate); tcase_add_test(tc, test_strv_append_all_copy); tcase_add_test(tc, test_strv_append_all_nocopy); + tcase_add_test(tc, test_strv_reverse); suite_add_tcase(s, tc); From e902b0499618b9b95d73362cf8883fcc2c69f6fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 10 Dec 2015 22:47:41 +0100 Subject: [PATCH 10/43] Implement completion --- src/cmd/cmd.c | 288 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 215 insertions(+), 73 deletions(-) diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index bfcf4e2..dfd75b8 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -7,24 +7,24 @@ #include "ucore/string.h" #include "ucore/strvec.h" #include "ucore/utils.h" - -//max words in a single command -#define UC_CMD_MAX_WORDS 32 - +#include "ucore/backtrace.h" +// enum UCCmdRc { - /**Executed ok */ UC_CMDRC_OK, /**Executed with warning */ UC_CMDRC_WARNING, - /*Not executed, incomplete command */ + /*incomplete command */ UC_CMDRC_INCOMPLETE, /*Command cann't uniquely be distinguished */ UC_CMDRC_AMBIGUOUS, + /* Command doesn't exist*/ + UC_CMDRC_NOT_FOUND, /*Not executed, generic error */ UC_CMDRC_ERROR, }; -typedef enum UCCmdRc (*uc_cmd_handler)(const struct UCStrv *args); +struct UCCmdArgs; +typedef enum UCCmdRc (*uc_cmd_handler)(const struct UCCmdArgs *args); enum UCCmdType { UC_CMD_ROOT = 1, @@ -34,6 +34,26 @@ enum UCCmdType { UC_CMD_END, }; + +/** + * Command are broken into words and inserted into a tree. + * the 3 commands: + * show all + * date + * show all bottles + * Results in the tree: + * + * +--------+ child +--------+ child +-------+ child +-----+ + * | root |------->| show |------->| all |------>| END | + * +--------+ +--------+ +-------+ +-----+ + * | next | next + * V V + * +--------+ child +-----+ +--------+ child +-----+ + * | date |-----> | END | | bottles|------>| END | + * +--------+ +-----+ +--------+ +-----+ + * + * END nodes are complete commands. Other child/next pointers will be nULL + */ struct UCCmdNode { enum UCCmdType type; uint32_t flags; @@ -62,12 +82,27 @@ struct UCCmdDef { }; +//max words in a single command +#define UC_CMD_MAX_WORDS 32 + struct UCCmdTokenizer { char *cmd_copy; char *cmd_words[UC_CMD_MAX_WORDS]; int num_words; }; +struct UCCmdArgs { + struct UCStrv argv; + struct UCCmdDef *cmd; +}; + +void print_args(const struct UCStrv *args); +static int uc_cmd_type_is_variable(enum UCCmdType type) +{ + return type == UC_CMD_LIST || + type == UC_CMD_STRING; +} + static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const char *delim) { @@ -89,21 +124,25 @@ static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const cha delim); } -static void uc_cmd_tokenize_destroy(struct UCCmdTokenizer *t) +static void +uc_cmd_tokenize_destroy(struct UCCmdTokenizer *t) + { free(t->cmd_copy); t->num_words = 0; t->cmd_copy = NULL; } -void uc_cmd_runner_init(struct UCCmdRunner *r) +void +uc_cmd_runner_init(struct UCCmdRunner *r) { memset(r, 0, sizeof *r); r->root_node = &r->_root; r->_root.type = UC_CMD_KEYWORD; } -void uc_cmd_node_dealloc(struct UCCmdNode *n) +void +uc_cmd_node_dealloc(struct UCCmdNode *n) { struct UCCmdNode *next; while (n) { @@ -122,15 +161,15 @@ void uc_cmd_node_dealloc(struct UCCmdNode *n) } } -void uc_cmd_runner_destroy(struct UCCmdRunner *r) +void +uc_cmd_runner_destroy(struct UCCmdRunner *r) { uc_cmd_node_dealloc(r->root_node->child); r->root_node->child = NULL; } - - -struct UCCmdNode *uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags) +static struct UCCmdNode * +uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags) { struct UCCmdNode *n; @@ -146,7 +185,8 @@ struct UCCmdNode *uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t fl return n; } -struct UCCmdNode *uc_cmd_node_create(const char *word) +static struct UCCmdNode * +uc_cmd_node_create(const char *word) { struct UCCmdNode *node = NULL; @@ -172,14 +212,14 @@ struct UCCmdNode *uc_cmd_node_create(const char *word) node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0); } - return node; - } -static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *args) +static int +uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *args) { size_t word_len; + int found = 0; if (word == NULL || word[0] == 0) { return 0; @@ -190,7 +230,10 @@ static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct if (n->type == UC_CMD_KEYWORD) { if (strncmp(word, n->data, word_len) == 0) { - return 1; + if (args != NULL) { + uc_strv_append(args, n->data); + } + found = 1; } } else if (n->type == UC_CMD_LIST) { struct UCStrv *v = n->data; @@ -203,21 +246,22 @@ static int uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct if (args != NULL) { uc_strv_append(args, v->strings[i]); } - return 1; + found = 1; } } } else if (n->type == UC_CMD_STRING) { if (args != NULL) { uc_strv_append(args, word); } - return 1; + found = 1; } - return 0; + return found; } -static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word) +static struct UCCmdNode * +uc_cmd_add(struct UCCmdNode *parent, const char *word) { struct UCCmdNode *new_node; struct UCCmdNode **iter = &parent->child; @@ -229,11 +273,10 @@ static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word) return NULL; } - while (*iter) { struct UCCmdNode *n = *iter; - if (new_node->type != UC_CMD_KEYWORD && n->type != UC_CMD_END) { + if (uc_cmd_type_is_variable(new_node->type) && n->type != UC_CMD_END) { //we don't support combinations of keywords and variables //at the same level. uc_cmd_node_dealloc(new_node); @@ -252,7 +295,8 @@ static struct UCCmdNode *uc_cmd_add(struct UCCmdNode *parent, const char *word) return new_node; } -int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) +int +uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd) { struct UCCmdNode *node = r->root_node; struct UCCmdNode *new_node; @@ -267,6 +311,7 @@ int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) for (int i = 0; i < t.num_words; i++) { node = uc_cmd_add(node, t.cmd_words[i]); if (node == NULL) { + uc_cmd_tokenize_destroy(&t); return -2; } } @@ -275,6 +320,7 @@ int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) new_node = uc_cmd_node_alloc(UC_CMD_END, cmd, 0); if (new_node == NULL) { + uc_cmd_tokenize_destroy(&t); return -1; } new_node->next = node->child; @@ -286,33 +332,36 @@ int uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) return 0; } - -enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) +int +uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) { + int rc; + + rc = uc_cmd_install_noassert(r, cmd); + UC_ASSERT(rc == 0); - struct UCCmdNode *node = r->root_node->child; - struct UCCmdTokenizer t; - enum UCCmdRc rc = UC_CMDRC_ERROR; - struct UCStrv args = UC_STRV_INITIALIZER; //arguments to the callback function + return rc; +} +enum UCCmdRc +uc_cmd_find(struct UCCmdNode *first, + const struct UCCmdTokenizer *t, + struct UCStrv *args, + struct UCCmdNode **result) +{ + struct UCCmdNode *node = first; + enum UCCmdRc rc = UC_CMDRC_NOT_FOUND; - - //make a copy since getfields destroys the original string - uc_cmd_tokenize(&t, cmd_line, NULL); - if (t.num_words <= 0) { - uc_cmd_tokenize_destroy(&t); - return rc; - } - - //match the commands towards the command tree - // - for (int i = 0; i < t.num_words && node; i++) { + for (int i = 0; i < t->num_words && node; i++) { int n_found = 0; struct UCCmdNode *found = NULL; while (node) { - if (uc_cmd_node_match(node, t.cmd_words[i], &args)) { - found = node; + if (uc_cmd_node_match(node, t->cmd_words[i], args)) { + if (n_found == 0) { + //keep the 1. matched + found = node; + } n_found++; } node = node->next; @@ -320,31 +369,118 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) if (n_found == 1) { node = found->child; + rc = UC_CMDRC_OK; } else if (n_found > 1) { - uc_strv_destroy(&args); - uc_cmd_tokenize_destroy(&t); - return UC_CMDRC_AMBIGUOUS; - } - } - - // Now check the current level for any UC_CMD_END - // which indicates a complete command - while (node) { - if (node->type == UC_CMD_END) { + node = found; + rc = UC_CMDRC_AMBIGUOUS; break; } - node = node->next; } - if (node != NULL) { - struct UCCmdDef *cmd = node->data; - rc = cmd->callback(&args); + *result = node; + + if (node == NULL) { + rc = UC_CMDRC_NOT_FOUND; + } + + return rc; +} + + +enum UCCmdRc +uc_cmd_parse_and_find(struct UCCmdRunner *r, const char *cmd_line, + struct UCStrv *args, + struct UCCmdNode **result) +{ + + struct UCCmdNode *node = r->root_node->child; + struct UCCmdTokenizer t; + enum UCCmdRc rc = UC_CMDRC_ERROR; + + //make a copy since getfields destroys the original string + uc_cmd_tokenize(&t, cmd_line, NULL); + + if (t.num_words > 0) { + + //match the commands towards the command tree + // + rc = uc_cmd_find(node, &t, args, result); + } + + uc_cmd_tokenize_destroy(&t); + + return rc; +} + +enum UCCmdRc +uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line) +{ + + struct UCStrv completions = UC_STRV_INITIALIZER; + + struct UCCmdNode *found = NULL; + enum UCCmdRc rc; + + rc = uc_cmd_parse_and_find(r, cmd_line, NULL, &found); + if (rc != UC_CMDRC_NOT_FOUND && found != NULL) { + struct UCCmdNode *node = found; + while (node) { + if (node->type == UC_CMD_END) { + uc_strv_append(&completions, ""); + } else if (node->type == UC_CMD_LIST) { + uc_strv_append_all(&completions, node->data, 1); + } else if (node->type == UC_CMD_STRING || + node->type == UC_CMD_KEYWORD) { + uc_strv_append(&completions, node->data); + } + node = node->next; + } + + printf("Possible completions for '%s'\n", cmd_line); + print_args(&completions); + } else { - rc = UC_CMDRC_INCOMPLETE; + printf("No possible completions\n"); + } + + uc_strv_destroy(&completions); + + return rc; +} + + +enum UCCmdRc +uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) +{ + struct UCCmdArgs args = { + .argv = UC_STRV_INITIALIZER, + .cmd = NULL, + }; + + struct UCCmdNode *found = NULL; + enum UCCmdRc rc; + + rc = uc_cmd_parse_and_find(r, cmd_line, &args.argv, &found); + if (rc == UC_CMDRC_OK) { + // Now check the current level for any UC_CMD_END + // which indicates a complete command + while (found) { + if (found->type == UC_CMD_END) { + break; + } + found = found->next; + } + + if (found != NULL) { + struct UCCmdDef *cmd = found->data; + args.cmd = cmd; + rc = cmd->callback(&args); + } else { + rc = UC_CMDRC_INCOMPLETE; + } } - uc_strv_destroy(&args); - uc_cmd_tokenize_destroy(&t); + uc_strv_destroy(&args.argv); return rc; } @@ -353,37 +489,39 @@ enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) void print_args(const struct UCStrv *args) { for (size_t i = 0; i < args->cnt; i++) { - printf("arg %zu:%s\n", i, args->strings[i]); + printf("arg %zu: '%s' ", i, args->strings[i]); } + puts(""); } -enum UCCmdRc cmd1_cb(const struct UCStrv *args) + +enum UCCmdRc cmd1_cb(const struct UCCmdArgs *args) { puts(__func__); - print_args(args); + print_args(&args->argv); return UC_CMDRC_OK; } -enum UCCmdRc cmd2_cb(const struct UCStrv *args) +enum UCCmdRc cmd2_cb(const struct UCCmdArgs *args) { puts(__func__); - print_args(args); + print_args(&args->argv); return UC_CMDRC_OK; } -enum UCCmdRc cmd3_cb(const struct UCStrv *args) +enum UCCmdRc cmd3_cb(const struct UCCmdArgs *args) { puts(__func__); - print_args(args); + print_args(&args->argv); return UC_CMDRC_OK; } -enum UCCmdRc cmd4_cb(const struct UCStrv *args) +enum UCCmdRc cmd4_cb(const struct UCCmdArgs *args) { puts(__func__); - print_args(args); + print_args(&args->argv); return UC_CMDRC_OK; } @@ -411,7 +549,7 @@ int main(int argc, char *argv[]) }; struct UCCmdDef cmd3 = { - "show empty (bottle|glass)", + "show empty bottle", cmd3_cb, 0, NULL @@ -433,7 +571,8 @@ int main(int argc, char *argv[]) uc_cmd_run(&r, "delete file /tmp/a"); uc_cmd_run(&r, "show all"); uc_cmd_run(&r, "show empty"); - uc_cmd_run(&r, "sh emp g"); + uc_cmd_run(&r, "sh emp b"); + uc_cmd_run(&r, ""); /* while (fgets(line,sizeof line, stdin)) { enum UCCmdRc rc = uc_cmd_run(&r, line); @@ -443,6 +582,9 @@ int main(int argc, char *argv[]) } */ + uc_cmd_complete(&r, "sho em"); + uc_cmd_complete(&r, "show "); + uc_cmd_complete(&r, ""); uc_cmd_runner_destroy(&r); From f107898919332c41c5f099d963d393f833c4052c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 12 Dec 2015 20:42:18 +0100 Subject: [PATCH 11/43] Prepare for handling descriptions --- src/cmd/cmd.c | 80 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index dfd75b8..2bed370 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -24,7 +24,7 @@ enum UCCmdRc { }; struct UCCmdArgs; -typedef enum UCCmdRc (*uc_cmd_handler)(const struct UCCmdArgs *args); +typedef enum UCCmdRc (*UCCmdHandler)(const struct UCCmdArgs *args); enum UCCmdType { UC_CMD_ROOT = 1, @@ -34,6 +34,15 @@ enum UCCmdType { UC_CMD_END, }; +struct UCCmdWord { + char *word; + char *descr; +}; + +struct UCCmdList { + struct UCStrv words; + struct UCStrv descrs; +}; /** * Command are broken into words and inserted into a tree. @@ -56,18 +65,16 @@ enum UCCmdType { */ struct UCCmdNode { enum UCCmdType type; + union { + struct UCCmdWord word; + struct UCCmdList list; + struct UCCmdDef *cmd; + } data; uint32_t flags; - void *data; struct UCCmdNode *next; //next at same level struct UCCmdNode *child; }; -//for UC_CMD_LIST, -struct UCCmdList { - char *word; - struct UCCmdList *next; -}; - struct UCCmdRunner { struct UCCmdNode *root_node; struct UCCmdNode _root; @@ -75,10 +82,9 @@ struct UCCmdRunner { struct UCCmdDef { const char *cmd; - uc_cmd_handler callback; + const char *help; + UCCmdHandler callback; uint32_t flags; - - struct UCCmdDef *next; }; @@ -149,12 +155,14 @@ uc_cmd_node_dealloc(struct UCCmdNode *n) uc_cmd_node_dealloc(n->child); next = n->next; if (n->type == UC_CMD_KEYWORD) { - free(n->data); + free(n->data.word.word); + free(n->data.word.descr); } else if (n->type == UC_CMD_LIST) { - uc_strv_destroy(n->data); - free(n->data); + uc_strv_destroy(&n->data.list.words); + uc_strv_destroy(&n->data.list.descrs); } else if (n->type == UC_CMD_STRING) { - free(n->data); + free(n->data.word.word); + free(n->data.word.descr); } free(n); n = next; @@ -169,7 +177,7 @@ uc_cmd_runner_destroy(struct UCCmdRunner *r) } static struct UCCmdNode * -uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags) +uc_cmd_node_alloc(enum UCCmdType type, uint32_t flags) { struct UCCmdNode *n; @@ -179,7 +187,6 @@ uc_cmd_node_alloc(enum UCCmdType type, void *data, uint32_t flags) } n->type = type; - n->data = data; n->flags = flags; return n; @@ -195,21 +202,23 @@ uc_cmd_node_create(const char *word) uc_cmd_tokenize(&t, word, "() |\t\v"); if (t.num_words > 0) { - struct UCStrv *v = malloc(sizeof *v); + node = uc_cmd_node_alloc(UC_CMD_LIST, 0); - uc_strv_init(v); + uc_strv_init(&node->data.list.words); + uc_strv_init(&node->data.list.descrs); for (int i = 0 ; i < t.num_words; i++) { - uc_strv_append(v, t.cmd_words[i]); + uc_strv_append(&node->data.list.words, t.cmd_words[i]); } - node = uc_cmd_node_alloc(UC_CMD_LIST, v, 0); } uc_cmd_tokenize_destroy(&t); } else if (isupper(word[0])) { - node = uc_cmd_node_alloc(UC_CMD_STRING, strdup(word), 0); + node = uc_cmd_node_alloc(UC_CMD_STRING, 0); + node->data.word.word = strdup(word); } else { - node = uc_cmd_node_alloc(UC_CMD_KEYWORD, strdup(word), 0); + node = uc_cmd_node_alloc(UC_CMD_KEYWORD, 0); + node->data.word.word = strdup(word); } return node; @@ -229,14 +238,14 @@ uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *ar if (n->type == UC_CMD_KEYWORD) { - if (strncmp(word, n->data, word_len) == 0) { + if (strncmp(word, n->data.word.word, word_len) == 0) { if (args != NULL) { - uc_strv_append(args, n->data); + uc_strv_append(args, n->data.word.word); } found = 1; } } else if (n->type == UC_CMD_LIST) { - struct UCStrv *v = n->data; + const struct UCStrv *v = &n->data.list.words; assert(v); @@ -318,11 +327,12 @@ uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd) //TODO, check for duplicate command here. - new_node = uc_cmd_node_alloc(UC_CMD_END, cmd, 0); + new_node = uc_cmd_node_alloc(UC_CMD_END, 0); if (new_node == NULL) { uc_cmd_tokenize_destroy(&t); return -1; } + new_node->data.cmd = cmd; new_node->next = node->child; node->child = new_node; @@ -345,9 +355,9 @@ uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) enum UCCmdRc uc_cmd_find(struct UCCmdNode *first, - const struct UCCmdTokenizer *t, - struct UCStrv *args, - struct UCCmdNode **result) + const struct UCCmdTokenizer *t, + struct UCStrv *args, + struct UCCmdNode **result) { struct UCCmdNode *node = first; enum UCCmdRc rc = UC_CMDRC_NOT_FOUND; @@ -428,10 +438,10 @@ uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line) if (node->type == UC_CMD_END) { uc_strv_append(&completions, ""); } else if (node->type == UC_CMD_LIST) { - uc_strv_append_all(&completions, node->data, 1); + uc_strv_append_all(&completions, &node->data.list.words, 1); } else if (node->type == UC_CMD_STRING || node->type == UC_CMD_KEYWORD) { - uc_strv_append(&completions, node->data); + uc_strv_append(&completions, node->data.word.word); } node = node->next; } @@ -472,7 +482,7 @@ uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) } if (found != NULL) { - struct UCCmdDef *cmd = found->data; + struct UCCmdDef *cmd = found->data.cmd; args.cmd = cmd; rc = cmd->callback(&args); } else { @@ -536,6 +546,7 @@ int main(int argc, char *argv[]) struct UCCmdRunner r; struct UCCmdDef cmd1 = { "show all", + "\n\n", cmd1_cb, 0, NULL @@ -543,6 +554,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd2 = { "show empty", + "\n\n", cmd2_cb, 0, NULL @@ -550,6 +562,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd3 = { "show empty bottle", + "\n\n\n", cmd3_cb, 0, NULL @@ -557,6 +570,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd4 = { "delete file NAME", + "\n\nName of the file\n", cmd4_cb, 0, NULL From 433fdd0a4b8145a32d4138de2cb15320b9428ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 15 Dec 2015 22:26:59 +0100 Subject: [PATCH 12/43] IMplement help system. Though it need refactoring. --- src/cmd/cmd.c | 202 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 168 insertions(+), 34 deletions(-) diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index 2bed370..a556e4f 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -68,11 +68,12 @@ struct UCCmdNode { union { struct UCCmdWord word; struct UCCmdList list; - struct UCCmdDef *cmd; + const struct UCCmdDef *cmd; } data; uint32_t flags; struct UCCmdNode *next; //next at same level struct UCCmdNode *child; + struct UCCmdNode *parent; }; struct UCCmdRunner { @@ -99,17 +100,21 @@ struct UCCmdTokenizer { struct UCCmdArgs { struct UCStrv argv; - struct UCCmdDef *cmd; + const struct UCCmdDef *cmd; }; -void print_args(const struct UCStrv *args); -static int uc_cmd_type_is_variable(enum UCCmdType type) +void +print_args(const struct UCStrv *args); + +static int +uc_cmd_type_is_variable(enum UCCmdType type) { return type == UC_CMD_LIST || type == UC_CMD_STRING; } -static void uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const char *delim) +static void +uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const char *delim) { t->num_words = 0; @@ -144,13 +149,14 @@ uc_cmd_runner_init(struct UCCmdRunner *r) { memset(r, 0, sizeof *r); r->root_node = &r->_root; - r->_root.type = UC_CMD_KEYWORD; + r->_root.type = UC_CMD_ROOT; } void uc_cmd_node_dealloc(struct UCCmdNode *n) { struct UCCmdNode *next; + while (n) { uc_cmd_node_dealloc(n->child); next = n->next; @@ -281,6 +287,7 @@ uc_cmd_add(struct UCCmdNode *parent, const char *word) if (new_node == NULL) { return NULL; } + new_node->parent = parent; while (*iter) { struct UCCmdNode *n = *iter; @@ -304,12 +311,80 @@ uc_cmd_add(struct UCCmdNode *parent, const char *word) return new_node; } +static int uc_cmd_node_add_help(struct UCCmdNode *node) +{ + struct UCCmdTokenizer t; + int i; + + if (node->data.cmd->help == NULL) { + //allow helpless commands + return 0; + } + + if (node->type != UC_CMD_END) { + return -10; + } + + uc_cmd_tokenize(&t, node->data.cmd->help, "\n"); + if (t.num_words <= 0) { + uc_cmd_tokenize_destroy(&t); + return -11; + } + + i = t.num_words - 1; + //we have the last node in the tree + //Walk it up towards the root(backwards) and fill + //in help texts where it's missing. + while (node->parent) { + + node = node->parent; + if (node->type == UC_CMD_ROOT) { + break; + } + if (i < 0) { + break; + } + + if (node->type == UC_CMD_KEYWORD || + node->type == UC_CMD_STRING) { + if (node->data.word.descr == NULL) { + node->data.word.descr = strdup(t.cmd_words[i]); + } + i--; + } else if (node->type == UC_CMD_LIST) { + if (node->data.list.descrs.cnt == 0) { + for (int k = (int)node->data.list.words.cnt -1; k >= 0; k++) { + if (i < 0) { + break; + } + uc_strv_append(&node->data.list.descrs, t.cmd_words[i]); + i--; + + } + } else { + i -= (int)node->data.list.words.cnt; + } + } + } + + uc_cmd_tokenize_destroy(&t); + + if (node->type != UC_CMD_ROOT || i != -1) { + //we didn't consume all the help tokens, so the + //command definition is screwd up + return -20; + } + + return 0; +} + int uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd) { struct UCCmdNode *node = r->root_node; struct UCCmdNode *new_node; struct UCCmdTokenizer t; + int rc; uc_cmd_tokenize(&t, cmd->cmd, NULL); if (t.num_words <= 0) { @@ -333,13 +408,15 @@ uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd) return -1; } new_node->data.cmd = cmd; - new_node->next = node->child; - node->child = new_node; + new_node->next = node->child; + node->child = new_node; + new_node->parent = node; + rc = uc_cmd_node_add_help(new_node); uc_cmd_tokenize_destroy(&t); - return 0; + return rc; } int @@ -360,11 +437,11 @@ uc_cmd_find(struct UCCmdNode *first, struct UCCmdNode **result) { struct UCCmdNode *node = first; + struct UCCmdNode *found = NULL; enum UCCmdRc rc = UC_CMDRC_NOT_FOUND; for (int i = 0; i < t->num_words && node; i++) { int n_found = 0; - struct UCCmdNode *found = NULL; while (node) { if (uc_cmd_node_match(node, t->cmd_words[i], args)) { @@ -387,9 +464,9 @@ uc_cmd_find(struct UCCmdNode *first, } } - *result = node; + *result = found; - if (node == NULL) { + if (found == NULL) { rc = UC_CMDRC_NOT_FOUND; } @@ -423,42 +500,57 @@ uc_cmd_parse_and_find(struct UCCmdRunner *r, const char *cmd_line, } enum UCCmdRc -uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line) +uc_cmd_help(struct UCCmdRunner *r, const char *cmd_line, struct UCStrv *completions) { + struct UCCmdNode *found = NULL; + enum UCCmdRc rc; - struct UCStrv completions = UC_STRV_INITIALIZER; + rc = uc_cmd_parse_and_find(r, cmd_line, NULL, &found); + if (rc == UC_CMDRC_OK) { + struct UCCmdNode *node = found; + if (node->type == UC_CMD_LIST) { + uc_strv_append_all(completions, &node->data.list.descrs, 1); + } else if (node->type == UC_CMD_STRING || + node->type == UC_CMD_KEYWORD) { + if (node->data.word.descr != NULL) { + uc_strv_append(completions, node->data.word.descr); + } + } + } + + return rc; +} + +enum UCCmdRc +uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line, struct UCStrv *completions) +{ struct UCCmdNode *found = NULL; enum UCCmdRc rc; rc = uc_cmd_parse_and_find(r, cmd_line, NULL, &found); if (rc != UC_CMDRC_NOT_FOUND && found != NULL) { - struct UCCmdNode *node = found; + struct UCCmdNode *node = found->child; + while (node) { if (node->type == UC_CMD_END) { - uc_strv_append(&completions, ""); + uc_strv_append(completions, ""); } else if (node->type == UC_CMD_LIST) { - uc_strv_append_all(&completions, &node->data.list.words, 1); + uc_strv_append_all(completions, &node->data.list.words, 1); } else if (node->type == UC_CMD_STRING || node->type == UC_CMD_KEYWORD) { - uc_strv_append(&completions, node->data.word.word); + uc_strv_append(completions, node->data.word.word); } node = node->next; } - printf("Possible completions for '%s'\n", cmd_line); - print_args(&completions); + } - } else { - printf("No possible completions\n"); - } - - uc_strv_destroy(&completions); - return rc; } + enum UCCmdRc uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) { @@ -472,6 +564,7 @@ uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) rc = uc_cmd_parse_and_find(r, cmd_line, &args.argv, &found); if (rc == UC_CMDRC_OK) { + found = found->child; // Now check the current level for any UC_CMD_END // which indicates a complete command while (found) { @@ -482,7 +575,7 @@ uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) } if (found != NULL) { - struct UCCmdDef *cmd = found->data.cmd; + const struct UCCmdDef *cmd = found->data.cmd; args.cmd = cmd; rc = cmd->callback(&args); } else { @@ -536,8 +629,39 @@ enum UCCmdRc cmd4_cb(const struct UCCmdArgs *args) return UC_CMDRC_OK; } +void do_complete(struct UCCmdRunner *r, const char *command) +{ + struct UCStrv completions = UC_STRV_INITIALIZER; + uc_cmd_complete(r, command, &completions); + if (completions.cnt > 0) { + printf("Possible completions for '%s' :\n", command); + for (size_t i = 0; i < completions.cnt; i++) { + printf("\t%s\n", completions.strings[i]); + } + } else { + printf("No completions for '%s' :\n", command); + } + uc_strv_destroy(&completions); +} + +void do_help(struct UCCmdRunner *r, const char *command) +{ + struct UCStrv completions = UC_STRV_INITIALIZER; + + uc_cmd_help(r, command, &completions); + if (completions.cnt > 0) { + printf("help for '%s' :\n", command); + for (size_t i = 0; i < completions.cnt; i++) { + printf("\t%s\n", completions.strings[i]); + } + } else { + printf("No help for '%s' :\n", command); + } + + uc_strv_destroy(&completions); +} int main(int argc, char *argv[]) @@ -546,7 +670,7 @@ int main(int argc, char *argv[]) struct UCCmdRunner r; struct UCCmdDef cmd1 = { "show all", - "\n\n", + " \nEverything\n", cmd1_cb, 0, NULL @@ -554,7 +678,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd2 = { "show empty", - "\n\n", + "Show parameter\nAll empty\n", cmd2_cb, 0, NULL @@ -562,7 +686,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd3 = { "show empty bottle", - "\n\n\n", + NULL, cmd3_cb, 0, NULL @@ -570,7 +694,7 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd4 = { "delete file NAME", - "\n\nName of the file\n", + "delete\nfile\nName of the file\n", cmd4_cb, 0, NULL @@ -587,6 +711,12 @@ int main(int argc, char *argv[]) uc_cmd_run(&r, "show empty"); uc_cmd_run(&r, "sh emp b"); uc_cmd_run(&r, ""); + + do_help(&r, "delete file /tmp/a"); + do_help(&r, "show empty"); + do_help(&r, "show all"); + do_help(&r, "sh"); + do_help(&r, ""); /* while (fgets(line,sizeof line, stdin)) { enum UCCmdRc rc = uc_cmd_run(&r, line); @@ -596,9 +726,13 @@ int main(int argc, char *argv[]) } */ - uc_cmd_complete(&r, "sho em"); - uc_cmd_complete(&r, "show "); - uc_cmd_complete(&r, ""); + do_complete(&r, "sho em"); + do_complete(&r, "show "); + do_complete(&r, ""); + do_complete(&r, "delet "); + do_complete(&r, "delete "); + do_complete(&r, "delete file"); + do_complete(&r, "delete fil"); uc_cmd_runner_destroy(&r); From a686ba19753e23df690930c5ebdb035efd90f5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 8 Jan 2016 09:43:04 +0100 Subject: [PATCH 13/43] Add gettokens() string function --- include/ucore/string.h | 3 ++- src/gettokens.c | 58 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/gettokens.c diff --git a/include/ucore/string.h b/include/ucore/string.h index ccdb53d..a8f22be 100644 --- a/include/ucore/string.h +++ b/include/ucore/string.h @@ -96,7 +96,8 @@ char* uc_sprintbs(char *result, unsigned short value); /** Like http://swtch.com/plan9port/man/man3/getfields.html */ -int getfields(char *str, char **args, int max, int mflag, const char *set); +int getfields(char *str, char **args, int max, int mflag, const char *sep); +int gettokens(char *str, char **args, int max, const char *sep); //Converts bytes to a human representable test, (i.e. 12kB, 160 MB 1.78 GB etc.) ///result should be at least of size 12, diff --git a/src/gettokens.c b/src/gettokens.c new file mode 100644 index 0000000..7c6c9a4 --- /dev/null +++ b/src/gettokens.c @@ -0,0 +1,58 @@ +#include +#include "ucore/string.h" + +//tokenize string, and exclude the quotes +static char *qtoken(char *s, const char *sep) +{ + int inquote = 0; + char *t = s; + while (*t != 0 && (inquote || strchr(sep, *t) == NULL)) { + if (*t != '"') { + *s++ = *t++; + continue; + } + + if (!inquote) { + inquote = 1; + t++; + continue; + } + + if (t[1] != '"') { + t++; + inquote = 0; + continue; + } + //double quotes, merged to 1 quote + t++; + *s++ = *t++; + } + + if (*s != 0) { + *s = 0; + if (t == s) { + t++; + } + } + + return t; +} + +int gettokens(char *str, char **args, int maxargs, const char *sep) +{ + int nargs; + + for (nargs = 0; nargs < maxargs; nargs++) { + while (*str != 0 && strchr(sep, *str) != NULL) { + *str++ = 0; + } + if (*str == 0) { + break; + } + args[nargs] = str; + str = qtoken(str, sep); + } + + return nargs; +} + From d70ab1fe09d1139699d4dda71511d2874696fb21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 8 Feb 2016 13:34:22 +0100 Subject: [PATCH 14/43] Use ck_assert_int_eq instead of ck_assert_uint_eq for compatibility with older check version --- test/test_restart_file.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/test_restart_file.c b/test/test_restart_file.c index 14792b6..55749dc 100644 --- a/test/test_restart_file.c +++ b/test/test_restart_file.c @@ -26,12 +26,12 @@ START_TEST (test_restart_counter) rc = uc_restart_counter_init(&cnt, FILE_NAME, 0); fail_if(rc != UC_RC_OK); - ck_assert_uint_eq(0, uc_restart_counter_get(&cnt)); + ck_assert_int_eq(0, uc_restart_counter_get(&cnt)); rc = uc_restart_counter_init(&cnt, FILE_NAME, 0); fail_if(rc != UC_RC_OK); - ck_assert_uint_eq(1, uc_restart_counter_get(&cnt)); + ck_assert_int_eq(1, uc_restart_counter_get(&cnt)); END_TEST @@ -48,7 +48,7 @@ START_TEST (test_restart_counter_existing) rc = uc_restart_counter_init(&cnt, FILE_NAME, 0); fail_if(rc != UC_RC_OK); - ck_assert_uint_eq(100000, uc_restart_counter_get(&cnt)); + ck_assert_int_eq(100000, uc_restart_counter_get(&cnt)); END_TEST @@ -72,11 +72,11 @@ START_TEST (test_restart_counter_garble) rc = uc_restart_counter_init(&cnt, FILE_NAME, 0); fail_if(rc != UC_RC_ERR_FILE_CONTENT_ERROR); - ck_assert_uint_eq(0, uc_restart_counter_get(&cnt)); + ck_assert_int_eq(0, uc_restart_counter_get(&cnt)); rc = uc_restart_counter_init(&cnt, FILE_NAME, 0); fail_if(rc != UC_RC_OK, "%d", rc); - ck_assert_uint_eq(1, uc_restart_counter_get(&cnt)); + ck_assert_int_eq(1, uc_restart_counter_get(&cnt)); END_TEST @@ -103,7 +103,7 @@ START_TEST (test_restart_counter_lock_file) rc = uc_restart_counter_init(&cnt, FILE_NAME, UC_RC_FL_LOCK_FILE); fail_if(rc != UC_RC_OK); - ck_assert_uint_eq(0, uc_restart_counter_get(&cnt)); + ck_assert_int_eq(0, uc_restart_counter_get(&cnt)); rc = uc_restart_counter_close(&cnt); fail_if(rc != UC_RC_OK); rc = uc_restart_counter_close(&cnt); @@ -118,7 +118,7 @@ START_TEST (test_restart_counter_lock_file) sem_post(&sem[1]); printf("rc = %d\n", rc); fail_if(rc != UC_RC_ERR_FILE_LOCKED); - ck_assert_uint_eq(0, uc_restart_counter_get(&cnt)); + ck_assert_int_eq(0, uc_restart_counter_get(&cnt)); } else { uc_restart_counter_init(&cnt, FILE_NAME, UC_RC_FL_LOCK_FILE); sem_post(&sem[0]); From 53079305353cd5631b42264bef29f6d465ec71a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 4 Mar 2016 11:38:51 +0100 Subject: [PATCH 15/43] Use gcc builtins (if gcc 5 or newer) for saturating math --- include/ucore/saturating_math.h | 35 ++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/include/ucore/saturating_math.h b/include/ucore/saturating_math.h index 6b9228f..84f9a62 100644 --- a/include/ucore/saturating_math.h +++ b/include/ucore/saturating_math.h @@ -10,10 +10,34 @@ * * multiplication, subtraction and addition operations are provided.*/ +//Use gcc builtins, supported since GCC 5 +#if __GNUC__ >= 5 + +#define UC_SAT_ADD(a, b, type, max_val)\ +({type res ;\ +if (__builtin_add_overflow(a, b, &res)) {\ + res = max_val;}\ +res;}) + + +#define UC_SAT_SUB(a, b, type)\ +({type res ;\ +if (__builtin_sub_overflow(a, b, &res)) {\ + res = 0;}\ +res;}) + +#define UC_SAT_MULT(a, b, type, max_val)\ +({type res ;\ +if (__builtin_mul_overflow(a, b, &res)) {\ + res = max_val;}\ +res;}) + +#else + #define UC_SAT_ADD(a, b, type, max_val)\ ((type)((a) + (b)) >= (a) ? (a) + (b) : (max_val)) -#define UC_SAT_SUB(a, b)\ +#define UC_SAT_SUB(a, b, type)\ ((a) >= (b) ? (a) - (b) : 0) #define UC_SAT_MULT(a, b, type, max_val)\ @@ -21,6 +45,7 @@ (a) <= (max_val) / (b) ? (type) (a) * (type) (b) \ : (max_val)) +#endif static inline uint8_t uc_sat_addu8(uint8_t a, uint8_t b) { @@ -29,7 +54,7 @@ static inline uint8_t uc_sat_addu8(uint8_t a, uint8_t b) static inline uint8_t uc_sat_subu8(uint8_t a, uint8_t b) { - return UC_SAT_SUB(a, b); + return UC_SAT_SUB(a, b, uint8_t); } static inline uint8_t uc_sat_multu8(uint8_t a, uint8_t b) @@ -44,7 +69,7 @@ static inline uint16_t uc_sat_addu16(uint16_t a, uint16_t b) static inline uint16_t uc_sat_subu16(uint16_t a, uint16_t b) { - return UC_SAT_SUB(a, b); + return UC_SAT_SUB(a, b, uint16_t); } static inline uint16_t uc_sat_multu16(uint16_t a, uint16_t b) @@ -59,7 +84,7 @@ static inline uint32_t uc_sat_addu32(uint32_t a, uint32_t b) static inline uint32_t uc_sat_subu32(uint32_t a, uint32_t b) { - return UC_SAT_SUB(a, b); + return UC_SAT_SUB(a, b, uint32_t); } static inline uint32_t uc_sat_multu32(uint32_t a, uint32_t b) @@ -74,7 +99,7 @@ static inline uint64_t uc_sat_addu64(uint64_t a, uint64_t b) static inline uint64_t uc_sat_subu64(uint64_t a, uint64_t b) { - return UC_SAT_SUB(a, b); + return UC_SAT_SUB(a, b, uint64_t); } static inline uint64_t uc_sat_multu64(uint64_t a, uint64_t b) From fae2a60203e1472531404e69cb06402050aee65d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 7 Mar 2016 22:18:15 +0100 Subject: [PATCH 16/43] Small cmd progress --- src/cmd/cmd.c | 162 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 57 deletions(-) diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index a556e4f..960ddd6 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -23,8 +23,6 @@ enum UCCmdRc { UC_CMDRC_ERROR, }; -struct UCCmdArgs; -typedef enum UCCmdRc (*UCCmdHandler)(const struct UCCmdArgs *args); enum UCCmdType { UC_CMD_ROOT = 1, @@ -44,6 +42,29 @@ struct UCCmdList { struct UCStrv descrs; }; +struct UCCmdArgs; +typedef enum UCCmdRc (*UCCmdHandler)(const struct UCCmdArgs *args); + +struct UCCmdDef { + const char *cmd; + const char *help; + UCCmdHandler callback; + uint32_t flags; +}; + +struct UCCmdArgs { + struct UCStrv argv; + const struct UCCmdDef *cmd; + void *ctx; +}; + +struct UCCmdRunner; +typedef int (*UCCmdRootExit)(struct UCCmdRunner *r, int current_id, void *ctx); +struct UCCmdRoot { + int node_id; + UCCmdRootExit exit_callback; +}; + /** * Command are broken into words and inserted into a tree. * the 3 commands: @@ -63,12 +84,14 @@ struct UCCmdList { * * END nodes are complete commands. Other child/next pointers will be nULL */ + struct UCCmdNode { enum UCCmdType type; union { struct UCCmdWord word; struct UCCmdList list; const struct UCCmdDef *cmd; + const struct UCCmdRootExit *root; } data; uint32_t flags; struct UCCmdNode *next; //next at same level @@ -77,18 +100,9 @@ struct UCCmdNode { }; struct UCCmdRunner { - struct UCCmdNode *root_node; + struct UCCmdNode *current_root; struct UCCmdNode _root; }; - -struct UCCmdDef { - const char *cmd; - const char *help; - UCCmdHandler callback; - uint32_t flags; -}; - - //max words in a single command #define UC_CMD_MAX_WORDS 32 @@ -98,14 +112,20 @@ struct UCCmdTokenizer { int num_words; }; -struct UCCmdArgs { - struct UCStrv argv; - const struct UCCmdDef *cmd; -}; void print_args(const struct UCStrv *args); +static int uc_str_empty(const char *str) +{ + while (*str) { + if (!isspace(*str++)) { + return 0; + } + } + return 0; +} + static int uc_cmd_type_is_variable(enum UCCmdType type) { @@ -148,7 +168,7 @@ void uc_cmd_runner_init(struct UCCmdRunner *r) { memset(r, 0, sizeof *r); - r->root_node = &r->_root; + r->current_root = &r->_root; r->_root.type = UC_CMD_ROOT; } @@ -178,8 +198,8 @@ uc_cmd_node_dealloc(struct UCCmdNode *n) void uc_cmd_runner_destroy(struct UCCmdRunner *r) { - uc_cmd_node_dealloc(r->root_node->child); - r->root_node->child = NULL; + uc_cmd_node_dealloc(r->_root.child); + r->current_root->child = NULL; } static struct UCCmdNode * @@ -198,40 +218,62 @@ uc_cmd_node_alloc(enum UCCmdType type, uint32_t flags) return n; } -static struct UCCmdNode * -uc_cmd_node_create(const char *word) +static struct +UCCmdNode *uc_cmd_node_create_list(const char *word) { struct UCCmdNode *node = NULL; - if (word[0] == '(') { //list (foo|bar|baz) - struct UCCmdTokenizer t; + struct UCCmdTokenizer t; - uc_cmd_tokenize(&t, word, "() |\t\v"); - if (t.num_words > 0) { - node = uc_cmd_node_alloc(UC_CMD_LIST, 0); + uc_cmd_tokenize(&t, word, "() |\t\v"); + if (t.num_words > 0) { + node = uc_cmd_node_alloc(UC_CMD_LIST, 0); + if (node != NULL) { uc_strv_init(&node->data.list.words); uc_strv_init(&node->data.list.descrs); - for (int i = 0 ; i < t.num_words; i++) { + for (int i = 0; i < t.num_words; i++) { uc_strv_append(&node->data.list.words, t.cmd_words[i]); } } + } - uc_cmd_tokenize_destroy(&t); - } else if (isupper(word[0])) { - node = uc_cmd_node_alloc(UC_CMD_STRING, 0); - node->data.word.word = strdup(word); - } else { - node = uc_cmd_node_alloc(UC_CMD_KEYWORD, 0); + uc_cmd_tokenize_destroy(&t); + return node; +} + +static struct UCCmdNode * +uc_cmd_node_create_word(enum UCCmdType type, const char *word) +{ + struct UCCmdNode *node; + + node = uc_cmd_node_alloc(type, 0); + if (node != NULL) { node->data.word.word = strdup(word); } return node; } +static struct UCCmdNode * +uc_cmd_node_create(const char *word) +{ + struct UCCmdNode *node; + + if (word[0] == '(') { //list (foo|bar|baz) + node = uc_cmd_node_create_list(word); + } else if (isupper(word[0])) { + node = uc_cmd_node_create_word(UC_CMD_STRING, word); + } else { + node = uc_cmd_node_create_word(UC_CMD_KEYWORD, word); + } + + return node; +} + static int -uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *args) +uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *matches) { size_t word_len; int found = 0; @@ -245,8 +287,8 @@ uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *ar if (n->type == UC_CMD_KEYWORD) { if (strncmp(word, n->data.word.word, word_len) == 0) { - if (args != NULL) { - uc_strv_append(args, n->data.word.word); + if (matches != NULL) { + uc_strv_append(matches, n->data.word.word); } found = 1; } @@ -258,15 +300,15 @@ uc_cmd_node_match(const struct UCCmdNode *n, const char *word, struct UCStrv *ar for(size_t i = 0; i < v->cnt; i++) { if (strncmp(word, v->strings[i], word_len) == 0) { - if (args != NULL) { - uc_strv_append(args, v->strings[i]); + if (matches != NULL) { + uc_strv_append(matches, v->strings[i]); } found = 1; } } } else if (n->type == UC_CMD_STRING) { - if (args != NULL) { - uc_strv_append(args, word); + if (matches != NULL) { + uc_strv_append(matches, word); } found = 1; } @@ -311,7 +353,8 @@ uc_cmd_add(struct UCCmdNode *parent, const char *word) return new_node; } -static int uc_cmd_node_add_help(struct UCCmdNode *node) +static int +uc_cmd_node_add_help(struct UCCmdNode *node) { struct UCCmdTokenizer t; int i; @@ -341,13 +384,15 @@ static int uc_cmd_node_add_help(struct UCCmdNode *node) if (node->type == UC_CMD_ROOT) { break; } + if (i < 0) { break; } if (node->type == UC_CMD_KEYWORD || node->type == UC_CMD_STRING) { - if (node->data.word.descr == NULL) { + if (node->data.word.descr == NULL && + !uc_str_empty(t.cmd_words[i])) { node->data.word.descr = strdup(t.cmd_words[i]); } i--; @@ -381,7 +426,7 @@ static int uc_cmd_node_add_help(struct UCCmdNode *node) int uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd) { - struct UCCmdNode *node = r->root_node; + struct UCCmdNode *node = r->current_root; struct UCCmdNode *new_node; struct UCCmdTokenizer t; int rc; @@ -419,21 +464,19 @@ uc_cmd_install_noassert(struct UCCmdRunner *r, struct UCCmdDef *cmd) return rc; } -int +void uc_cmd_install(struct UCCmdRunner *r, struct UCCmdDef *cmd) { int rc; rc = uc_cmd_install_noassert(r, cmd); UC_ASSERT(rc == 0); - - return rc; } enum UCCmdRc uc_cmd_find(struct UCCmdNode *first, const struct UCCmdTokenizer *t, - struct UCStrv *args, + struct UCStrv *matches, struct UCCmdNode **result) { struct UCCmdNode *node = first; @@ -444,7 +487,7 @@ uc_cmd_find(struct UCCmdNode *first, int n_found = 0; while (node) { - if (uc_cmd_node_match(node, t->cmd_words[i], args)) { + if (uc_cmd_node_match(node, t->cmd_words[i], matches)) { if (n_found == 0) { //keep the 1. matched found = node; @@ -476,11 +519,11 @@ uc_cmd_find(struct UCCmdNode *first, enum UCCmdRc uc_cmd_parse_and_find(struct UCCmdRunner *r, const char *cmd_line, - struct UCStrv *args, + struct UCStrv *matches, struct UCCmdNode **result) { - struct UCCmdNode *node = r->root_node->child; + struct UCCmdNode *node = r->current_root->child; struct UCCmdTokenizer t; enum UCCmdRc rc = UC_CMDRC_ERROR; @@ -491,7 +534,7 @@ uc_cmd_parse_and_find(struct UCCmdRunner *r, const char *cmd_line, //match the commands towards the command tree // - rc = uc_cmd_find(node, &t, args, result); + rc = uc_cmd_find(node, &t, matches, result); } uc_cmd_tokenize_destroy(&t); @@ -543,7 +586,6 @@ uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line, struct UCStrv *comp } node = node->next; } - } return rc; @@ -552,11 +594,11 @@ uc_cmd_complete(struct UCCmdRunner *r, const char *cmd_line, struct UCStrv *comp enum UCCmdRc -uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) +uc_cmd_run_ctx(struct UCCmdRunner *r, const char *cmd_line, void *ctx) { struct UCCmdArgs args = { .argv = UC_STRV_INITIALIZER, - .cmd = NULL, + .ctx = ctx, }; struct UCCmdNode *found = NULL; @@ -588,6 +630,12 @@ uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) return rc; } +enum UCCmdRc +uc_cmd_run(struct UCCmdRunner *r, const char *cmd_line) +{ + return uc_cmd_run_ctx(r, cmd_line, NULL); +} + void print_args(const struct UCStrv *args) { @@ -670,7 +718,7 @@ int main(int argc, char *argv[]) struct UCCmdRunner r; struct UCCmdDef cmd1 = { "show all", - " \nEverything\n", + "show stuff\nEverything\n", cmd1_cb, 0, NULL @@ -678,8 +726,8 @@ int main(int argc, char *argv[]) struct UCCmdDef cmd2 = { "show empty", - "Show parameter\nAll empty\n", - cmd2_cb, + " \n everyhing that's empty\n", + cmd2_cb, 0, NULL }; From c3c9f25dc631eb5332839fa849743960d514591c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 9 Mar 2016 00:06:59 +0100 Subject: [PATCH 17/43] Add tests for getfields and gettokens --- test/test_runner.c | 4 +- test/test_string.c | 198 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 test/test_string.c diff --git a/test/test_runner.c b/test/test_runner.c index 4554656..afd7e96 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -34,6 +34,7 @@ extern Suite *ticket_lock_suite(void); extern Suite *restart_counter_suite(void); extern Suite *iomux_suite(void); extern Suite *iomux_signal_suite(void); +extern Suite *string_suite(void); static suite_func suites[] = { bitvec_suite, @@ -62,7 +63,8 @@ static suite_func suites[] = { ticket_lock_suite, restart_counter_suite, iomux_suite, - iomux_signal_suite + iomux_signal_suite, + string_suite }; diff --git a/test/test_string.c b/test/test_string.c new file mode 100644 index 0000000..d573b42 --- /dev/null +++ b/test/test_string.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include "ucore/string.h" +#include "ucore/utils.h" + + +START_TEST (test_getfields) + + char str[] = "a;b;c"; + char *letters[5] = {NULL}; + + int rc = getfields(str, letters, 5, 0, ";"); + ck_assert_int_eq(rc, 3); + + + ck_assert_str_eq("a", letters[0]); + ck_assert_str_eq("b", letters[1]); + ck_assert_str_eq("c", letters[2]); + +END_TEST + +START_TEST (test_getfields_consecutive) + + char str[] = "a;;b;c;;;"; + char *letters[7] = {NULL}; + + int rc = getfields(str, letters, 5, 0, ";"); + ck_assert_int_eq(rc, 5); + + + // This result is rather silly, but it's + // how getfields works with mflag=0 + ck_assert_str_eq("a", letters[0]); + ck_assert_str_eq("", letters[1]); + ck_assert_str_eq("b", letters[2]); + ck_assert_str_eq("c", letters[3]); + ck_assert_str_eq(";;", letters[4]); + +END_TEST + +START_TEST (test_getfields_mflag) + char str[] = "a;b;c"; + char *letters[5] = {NULL}; + + int rc = getfields(str, letters, 5, 1, ";"); + ck_assert_int_eq(rc, 3); + + + ck_assert_str_eq("a", letters[0]); + ck_assert_str_eq("b", letters[1]); + ck_assert_str_eq("c", letters[2]); + +END_TEST + +START_TEST (test_getfields_consecutive_mflag) + + char str[] = "a;;b;c;;;"; + char *letters[7] = {NULL}; + + int rc = getfields(str, letters, 7, 1, ";"); + ck_assert_int_eq(rc, 3); + + + // This result is rather silly, but it's + // how getfields works with mflag=0 + ck_assert_str_eq("a", letters[0]); + ck_assert_str_eq("b", letters[1]); + ck_assert_str_eq("c", letters[2]); + +END_TEST + +START_TEST (test_getfields_too_many) + + char str[] = "a\r\nb\r\nc\r\nd\r\ne"; + char *letters[4] = {NULL}; + + int rc = getfields(str, letters, 4, 0, "\r\n"); + ck_assert_int_eq(rc, 4); + + // This result is rather silly, but it's + // how getfields works with mflag=0 + ck_assert_str_eq("a", letters[0]); + ck_assert_str_eq("", letters[1]); + ck_assert_str_eq("b", letters[2]); + ck_assert_str_eq("\nc\r\nd\r\ne", letters[3]); + +END_TEST + +START_TEST (test_getfields_too_many_mflag) + + char str[] = "a\r\nb\r\nc\r\nd\r\ne"; + char *letters[4] = {NULL}; + + int rc = getfields(str, letters, 4, 1, "\r\n"); + ck_assert_int_eq(rc, 4); + + ck_assert_str_eq("a", letters[0]); + ck_assert_str_eq("b", letters[1]); + ck_assert_str_eq("c", letters[2]); + ck_assert_str_eq("d\r\ne", letters[3]); + +END_TEST + +START_TEST (test_getfields_empty) + + char str[] = ""; + char *letters[4] = {NULL}; + + int rc = getfields(str, letters, 4, 0, ";\r\n"); + ck_assert_int_eq(rc, 1); + ck_assert_str_eq("", letters[0]); + + rc = getfields(str, letters, 4, 1, ";\r\n"); + ck_assert_int_eq(rc, 0); + + +END_TEST + +START_TEST (test_gettokens) + + char str[] = "a;b;c"; + char *letters[5] = {NULL}; + + int rc = gettokens(str, letters, 5,";"); + ck_assert_int_eq(rc, 3); + + + ck_assert_str_eq("a", letters[0]); + ck_assert_str_eq("b", letters[1]); + ck_assert_str_eq("c", letters[2]); + +END_TEST + +START_TEST (test_gettokens_consecutive) + + char str[] = "a;;;b;;c;"; + char *letters[5] = {NULL}; + + int rc = gettokens(str, letters, 5,";"); + ck_assert_int_eq(rc, 3); + + + ck_assert_str_eq("a", letters[0]); + ck_assert_str_eq("b", letters[1]); + ck_assert_str_eq("c", letters[2]); + +END_TEST + +START_TEST (test_gettokens_empty) + + char str[] = ""; + char *letters[5] = {NULL}; + + int rc = gettokens(str, letters, 5,";"); + ck_assert_int_eq(rc, 0); + +END_TEST + +START_TEST (test_gettokens_quotes) + + char str[] = "\"abc\";d;\"e \""; + char *letters[5] = {NULL}; + + int rc = gettokens(str, letters, 5,";"); + ck_assert_int_eq(rc, 3); + + ck_assert_str_eq("abc", letters[0]); + ck_assert_str_eq("d", letters[1]); + ck_assert_str_eq("e ", letters[2]); + +END_TEST + + +Suite *string_suite(void) +{ + Suite *s = suite_create("string"); + TCase *tc = tcase_create("string"); + + tcase_add_test(tc, test_getfields); + tcase_add_test(tc, test_getfields_consecutive); + tcase_add_test(tc, test_getfields_mflag); + tcase_add_test(tc, test_getfields_consecutive_mflag); + tcase_add_test(tc, test_getfields_too_many); + tcase_add_test(tc, test_getfields_too_many_mflag); + tcase_add_test(tc, test_getfields_empty); + + tcase_add_test(tc, test_gettokens); + tcase_add_test(tc, test_gettokens_consecutive); + tcase_add_test(tc, test_gettokens_empty); + tcase_add_test(tc, test_gettokens_quotes); + + suite_add_tcase(s, tc); + + return s; +} + From 21703ded30c51d414a62e6304dd545dffe791438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 9 Mar 2016 00:10:23 +0100 Subject: [PATCH 18/43] prefux gettokens/getfields with uc_ --- include/ucore/string.h | 4 ++-- src/cmd/cmd.c | 2 +- src/getfields.c | 2 +- src/gettokens.c | 2 +- test/test_string.c | 24 ++++++++++++------------ 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/ucore/string.h b/include/ucore/string.h index a8f22be..b60eac9 100644 --- a/include/ucore/string.h +++ b/include/ucore/string.h @@ -96,8 +96,8 @@ char* uc_sprintbs(char *result, unsigned short value); /** Like http://swtch.com/plan9port/man/man3/getfields.html */ -int getfields(char *str, char **args, int max, int mflag, const char *sep); -int gettokens(char *str, char **args, int max, const char *sep); +int uc_getfields(char *str, char **args, int max, int mflag, const char *sep); +int uc_gettokens(char *str, char **args, int max, const char *sep); //Converts bytes to a human representable test, (i.e. 12kB, 160 MB 1.78 GB etc.) ///result should be at least of size 12, diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index 960ddd6..9734873 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -148,7 +148,7 @@ uc_cmd_tokenize(struct UCCmdTokenizer *t, const char *cmd, const char *delim) delim = "\r\n\t\v "; } - t->num_words = getfields(t->cmd_copy, + t->num_words = uc_getfields(t->cmd_copy, t->cmd_words, ARRAY_SIZE(t->cmd_words), 1, diff --git a/src/getfields.c b/src/getfields.c index 504ffdb..091232e 100644 --- a/src/getfields.c +++ b/src/getfields.c @@ -2,7 +2,7 @@ #include "ucore/string.h" int -getfields(char *str, char **args, int max, int mflag, const char *set) +uc_getfields(char *str, char **args, int max, int mflag, const char *set) { char r; int intok, narg; diff --git a/src/gettokens.c b/src/gettokens.c index 7c6c9a4..967463e 100644 --- a/src/gettokens.c +++ b/src/gettokens.c @@ -38,7 +38,7 @@ static char *qtoken(char *s, const char *sep) return t; } -int gettokens(char *str, char **args, int maxargs, const char *sep) +int uc_gettokens(char *str, char **args, int maxargs, const char *sep) { int nargs; diff --git a/test/test_string.c b/test/test_string.c index d573b42..13c28ca 100644 --- a/test/test_string.c +++ b/test/test_string.c @@ -11,7 +11,7 @@ START_TEST (test_getfields) char str[] = "a;b;c"; char *letters[5] = {NULL}; - int rc = getfields(str, letters, 5, 0, ";"); + int rc = uc_getfields(str, letters, 5, 0, ";"); ck_assert_int_eq(rc, 3); @@ -26,7 +26,7 @@ START_TEST (test_getfields_consecutive) char str[] = "a;;b;c;;;"; char *letters[7] = {NULL}; - int rc = getfields(str, letters, 5, 0, ";"); + int rc = uc_getfields(str, letters, 5, 0, ";"); ck_assert_int_eq(rc, 5); @@ -44,7 +44,7 @@ START_TEST (test_getfields_mflag) char str[] = "a;b;c"; char *letters[5] = {NULL}; - int rc = getfields(str, letters, 5, 1, ";"); + int rc = uc_getfields(str, letters, 5, 1, ";"); ck_assert_int_eq(rc, 3); @@ -59,7 +59,7 @@ START_TEST (test_getfields_consecutive_mflag) char str[] = "a;;b;c;;;"; char *letters[7] = {NULL}; - int rc = getfields(str, letters, 7, 1, ";"); + int rc = uc_getfields(str, letters, 7, 1, ";"); ck_assert_int_eq(rc, 3); @@ -76,7 +76,7 @@ START_TEST (test_getfields_too_many) char str[] = "a\r\nb\r\nc\r\nd\r\ne"; char *letters[4] = {NULL}; - int rc = getfields(str, letters, 4, 0, "\r\n"); + int rc = uc_getfields(str, letters, 4, 0, "\r\n"); ck_assert_int_eq(rc, 4); // This result is rather silly, but it's @@ -93,7 +93,7 @@ START_TEST (test_getfields_too_many_mflag) char str[] = "a\r\nb\r\nc\r\nd\r\ne"; char *letters[4] = {NULL}; - int rc = getfields(str, letters, 4, 1, "\r\n"); + int rc = uc_getfields(str, letters, 4, 1, "\r\n"); ck_assert_int_eq(rc, 4); ck_assert_str_eq("a", letters[0]); @@ -108,11 +108,11 @@ START_TEST (test_getfields_empty) char str[] = ""; char *letters[4] = {NULL}; - int rc = getfields(str, letters, 4, 0, ";\r\n"); + int rc = uc_getfields(str, letters, 4, 0, ";\r\n"); ck_assert_int_eq(rc, 1); ck_assert_str_eq("", letters[0]); - rc = getfields(str, letters, 4, 1, ";\r\n"); + rc = uc_getfields(str, letters, 4, 1, ";\r\n"); ck_assert_int_eq(rc, 0); @@ -123,7 +123,7 @@ START_TEST (test_gettokens) char str[] = "a;b;c"; char *letters[5] = {NULL}; - int rc = gettokens(str, letters, 5,";"); + int rc = uc_gettokens(str, letters, 5,";"); ck_assert_int_eq(rc, 3); @@ -138,7 +138,7 @@ START_TEST (test_gettokens_consecutive) char str[] = "a;;;b;;c;"; char *letters[5] = {NULL}; - int rc = gettokens(str, letters, 5,";"); + int rc = uc_gettokens(str, letters, 5,";"); ck_assert_int_eq(rc, 3); @@ -153,7 +153,7 @@ START_TEST (test_gettokens_empty) char str[] = ""; char *letters[5] = {NULL}; - int rc = gettokens(str, letters, 5,";"); + int rc = uc_gettokens(str, letters, 5,";"); ck_assert_int_eq(rc, 0); END_TEST @@ -163,7 +163,7 @@ START_TEST (test_gettokens_quotes) char str[] = "\"abc\";d;\"e \""; char *letters[5] = {NULL}; - int rc = gettokens(str, letters, 5,";"); + int rc = uc_gettokens(str, letters, 5,";"); ck_assert_int_eq(rc, 3); ck_assert_str_eq("abc", letters[0]); From 57e8bfb1560b2b3beeb54750e5377509977f525a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 9 Mar 2016 00:31:54 +0100 Subject: [PATCH 19/43] Add --sanetizer to run with gcc sanitation --- SConstruct | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/SConstruct b/SConstruct index aad42de..1e0aaca 100644 --- a/SConstruct +++ b/SConstruct @@ -66,6 +66,13 @@ AddOption('--stack-protection', help = 'Build with stack protection support' ) +AddOption('--sanitizer', + dest = 'sanitizer', + action='store_true', + default=False, + help = 'Build with gcc sanitizer' +) + AddOption('--32', dest='force32bit', action='store_true', @@ -126,6 +133,10 @@ if GetOption('coverage'): env.Append(CFLAGS = ['--coverage']) env.Append(LINKFLAGS = ['--coverage']) +if GetOption('sanitizer'): + env.Append(CFLAGS = ['-fsanitize=undefined', '-fsanitize=address']) + env.Append(LINKFLAGS = ['-fsanitize=undefined', '-fsanitize=address']) + # Generate substitute dictionary subst_info = dict(('@' + key + '@', version_info[key]) for key in version_info) subst_info['@prefix@'] = prefix From 0a34c799ce2fc808200c546c8251f88060b4d354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 9 Mar 2016 00:37:10 +0100 Subject: [PATCH 20/43] Add gettokens test for double " --- test/test_string.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/test_string.c b/test/test_string.c index 13c28ca..4307be1 100644 --- a/test/test_string.c +++ b/test/test_string.c @@ -172,6 +172,19 @@ START_TEST (test_gettokens_quotes) END_TEST +START_TEST (test_gettokens_double_quotes) + + char str[] = "\"\"abc\"\";d;\"e\"\"f\"\"\""; + char *letters[5] = {NULL}; + + int rc = uc_gettokens(str, letters, 5,";"); + ck_assert_int_eq(rc, 3); + + ck_assert_str_eq("abc", letters[0]); + ck_assert_str_eq("d", letters[1]); + ck_assert_str_eq("e\"f\"", letters[2]); + +END_TEST Suite *string_suite(void) { @@ -190,6 +203,7 @@ Suite *string_suite(void) tcase_add_test(tc, test_gettokens_consecutive); tcase_add_test(tc, test_gettokens_empty); tcase_add_test(tc, test_gettokens_quotes); + tcase_add_test(tc, test_gettokens_double_quotes); suite_add_tcase(s, tc); From c520b6caec4591e46c0fdb6ed731ae8853848eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 14 Mar 2016 12:18:31 +0100 Subject: [PATCH 21/43] Leave to SConscript files to decide default targets --- SConstruct | 1 - src/SConscript | 2 ++ test/SConscript | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index 1e0aaca..1ecc470 100644 --- a/SConstruct +++ b/SConstruct @@ -175,4 +175,3 @@ env.Package(target = 'libucore-' + version_info['version_str'] + '.tar.gz', X_RPM_GROUP = 'Development/Libraries' ) -env.Default('src') diff --git a/src/SConscript b/src/SConscript index 7d060a3..ed74ad0 100644 --- a/src/SConscript +++ b/src/SConscript @@ -21,3 +21,5 @@ ucore_env.Alias('install', ucore_env.Install(os.path.join(prefix, 'lib'), [ucore_staticlib])) ucore_env.Alias('install', ucore_env.InstallVersionedLib(os.path.join(prefix, 'lib'), [ucore_sharedlib])) + +ucore_env.Default([ucore_staticlib, ucore_sharedlib]) diff --git a/test/SConscript b/test/SConscript index 2e42446..680c23d 100644 --- a/test/SConscript +++ b/test/SConscript @@ -32,4 +32,4 @@ cmd = test_env.Command(target='test_phony' , action= test_env.Dir('.').abspath + '/' + test_executable) test_env.Depends(cmd, prog) test_env.AlwaysBuild(cmd) - +test_env.Default(test_executable) From 20a14306bbef48764d3eb0c435c6a255d2580cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 19 Mar 2016 18:57:49 +0100 Subject: [PATCH 22/43] Clarify uc_timer_add docs --- include/ucore/timers.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/ucore/timers.h b/include/ucore/timers.h index 4385298..00f1563 100644 --- a/include/ucore/timers.h +++ b/include/ucore/timers.h @@ -96,6 +96,8 @@ void uc_timers_init_ex(struct UCTimers *t, struct UCoreClock *uclock); * will be called when the timer expires, and the timer is removed from the engine * User is responsible for the lifetime and memory of the UCTimer, which must exist until * te timer is fired or removed. + * If the timer has previously been added, it will be removed first. So there + * is no need to call uc_timers_remove() to "re-schedule" a timer. * * @param timers timer engine to add timer to. * @param timer timer to add From 260d2c67c2fb7d3c8f4350350ff0c01da6d5aa05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 26 Apr 2016 10:11:01 +0200 Subject: [PATCH 23/43] Enable client based search engine for Doxygen --- Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doxyfile b/Doxyfile index df415e7..6edfda1 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1192,7 +1192,7 @@ MATHJAX_EXTENSIONS = # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client From 55846a0e42d0e19c31f8f6222c883eb01b53e19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sun, 2 Oct 2016 21:39:02 +0200 Subject: [PATCH 24/43] Initial conversion to CMake --- CMakeLists.txt | 42 ++++++++++++++++++++++++++++++++++++++++++ include/CMakeLists.txt | 1 + src/CMakeLists.txt | 14 ++++++++++++++ src/version.c.in | 8 ++++---- test/CMakeLists.txt | 8 ++++++++ 5 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 include/CMakeLists.txt create mode 100644 src/CMakeLists.txt create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0ee71dd --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,42 @@ +project(libucore C) +cmake_minimum_required(VERSION 3.0.0) + +execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR} describe --abbrev=5 --dirty --always OUTPUT_VARIABLE version_revision WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND hostname OUTPUT_VARIABLE build_host OUTPUT_STRIP_TRAILING_WHITESPACE) + +set(libucore_VERSION_MAJOR 1) +set(libucore_VERSION_MINOR 0) +set(libucore_VERSION_PATCH 0) +set(libucore_VERSION ${libucore_VERSION_MAJOR}.${libucore_VERSION_MINOR}.${libucore_VERSION_PATCH}.${version_revision}) + +set(CMAKE_VERBOSE_MAKEFILE ON) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pthread") + + +option(CODE_COVERAGE "build with code coverage intrumentation" OFF) +if (CODE_COVERAGE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") + add_definitions(-DCOVERAGE) +endif() + +option(BUILD_DEBUG "build debug binaries" ON) +if (BUILD_ENVOY_DEBUG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") + add_definitions(-DDEBUG) +else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") + add_definitions(-DNDEBUG) +endif() + +option(BUILD_SANITIZE "build with address sanitizer" OFF) +if (BUILD_SANITIZE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +endif() + +include_directories(include) + +add_subdirectory(src) +add_subdirectory(test) +add_subdirectory(include) + diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..3e8dcd4 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1 @@ +install(DIRECTORY ucore DESTINATION include) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..6f5d553 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,14 @@ +configure_file ( +"version.c.in" +"version.c" +) +file(GLOB SOURCE_FILES *.c) + +add_library( +ucore SHARED +${SOURCE_FILES} +"${PROJECT_BINARY_DIR}/src/version.c" +) +set_target_properties(ucore PROPERTIES SOVERSION 1 VERSION 1.0.0) +target_link_libraries(ucore pthread) +install (TARGETS ucore DESTINATION lib) diff --git a/src/version.c.in b/src/version.c.in index ade8110..fe80391 100644 --- a/src/version.c.in +++ b/src/version.c.in @@ -1,11 +1,11 @@ //Various info about the version and build. //The SConscript file substitutes these at build time -const int ucore_version_major = @version_major@; -const int ucore_version_minor = @version_minor@; -const int ucore_version_patch = @version_patch@; +const int ucore_version_major = @libucore_VERSION_MAJOR@; +const int ucore_version_minor = @libucore_VERSION_MINOR@; +const int ucore_version_patch = @libucore_VERSION_PATCH@; -const char ucore_version_str[] = "@version_str@"; +const char ucore_version_str[] = "@libucore_VERSION@"; const char ucore_build_host[] = "@build_host@"; const char ucore_build_type[] = "@build_type@"; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..39d65c7 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,8 @@ +file(GLOB TEST_SOURCE_FILES test_*.c) + +add_executable(test_runner ${TEST_SOURCE_FILES}) +target_link_libraries(test_runner check ucore rt) + +add_custom_target(runtest COMMAND test_runner + DEPENDS test_runner + WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}) From b55c8d68a56b9c8b2747318a2415ad90cfde4b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 4 Oct 2016 19:50:38 +0200 Subject: [PATCH 25/43] Add more compiler flags that was used with scons --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ee71dd..fad2c0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,9 @@ set(libucore_VERSION ${libucore_VERSION_MAJOR}.${libucore_VERSION_MINOR}.${libuc set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pthread") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self -pthread") +add_definitions(-D_FILE_OFFSET_BITS=64) +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2 -pthread") option(CODE_COVERAGE "build with code coverage intrumentation" OFF) @@ -21,7 +23,7 @@ if (CODE_COVERAGE) endif() option(BUILD_DEBUG "build debug binaries" ON) -if (BUILD_ENVOY_DEBUG) +if (BUILD_DEBUG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") add_definitions(-DDEBUG) else() From 542e6122d6a055b312a76c3ac501ec3500d7c757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 6 Oct 2016 20:06:35 +0200 Subject: [PATCH 26/43] Remove Debug config, should rather use CMAKE_BUILD_TYPE variable rather --- CMakeLists.txt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fad2c0d..cdc6d73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,15 +22,6 @@ if (CODE_COVERAGE) add_definitions(-DCOVERAGE) endif() -option(BUILD_DEBUG "build debug binaries" ON) -if (BUILD_DEBUG) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") - add_definitions(-DDEBUG) -else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") - add_definitions(-DNDEBUG) -endif() - option(BUILD_SANITIZE "build with address sanitizer" OFF) if (BUILD_SANITIZE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") From 70db91e0de707bac602096bb4a51b392dc3d6cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 22 Nov 2016 16:24:28 +0100 Subject: [PATCH 27/43] Compile with -std=gnu99 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cdc6d73..cebacaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ project(libucore C) -cmake_minimum_required(VERSION 3.0.0) +cmake_minimum_required(VERSION 2.8.0) execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR} describe --abbrev=5 --dirty --always OUTPUT_VARIABLE version_revision WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND hostname OUTPUT_VARIABLE build_host OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -11,7 +11,7 @@ set(libucore_VERSION ${libucore_VERSION_MAJOR}.${libucore_VERSION_MINOR}.${libuc set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self -pthread") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self -pthread") add_definitions(-D_FILE_OFFSET_BITS=64) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2 -pthread") From 422667aa7e39fef66e28cdd0a9701a02bce12026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 29 Nov 2016 09:39:20 +0100 Subject: [PATCH 28/43] Use CMAKE_C_STANDARD variable for setting C standard --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cebacaa..d2625d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,8 @@ set(libucore_VERSION ${libucore_VERSION_MAJOR}.${libucore_VERSION_MINOR}.${libuc set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self -pthread") +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self -pthread") add_definitions(-D_FILE_OFFSET_BITS=64) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2 -pthread") From a6fe01978cd115919606268762b9b31044b299d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 7 Dec 2016 20:57:59 +0100 Subject: [PATCH 29/43] Propagate error back from iomux_select_update_events --- src/iomux_select.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iomux_select.c b/src/iomux_select.c index 488450b..9f71773 100644 --- a/src/iomux_select.c +++ b/src/iomux_select.c @@ -44,7 +44,7 @@ static int iomux_select_update_events(struct IOMux *mux_, struct IOMuxFD *fd) struct IOMuxSelect *mux = mux_->instance; if (fd->fd < 0 || fd->fd >= FD_SETSIZE) { - return EINVAL; + return ENFILE; } if (fd->what & MUX_EV_READ) @@ -70,7 +70,7 @@ static int iomux_select_register_fd(struct IOMux *mux_, struct IOMuxFD *fd) rc = iomux_select_update_events(mux_, fd); if (rc != 0) { - return ENFILE; + return rc; } mux->descriptors[fd->fd] = fd; From 43f3a3372ef4996fe6c9e32bbd2d17484c0a57e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 7 Dec 2016 20:58:39 +0100 Subject: [PATCH 30/43] Allow wquque to use callback to free an mbuf - so mbufs can be reused/pooled --- include/ucore/wqueue.h | 9 ++++++++- src/wqueue.c | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/ucore/wqueue.h b/include/ucore/wqueue.h index 636d873..4e64459 100644 --- a/include/ucore/wqueue.h +++ b/include/ucore/wqueue.h @@ -67,6 +67,12 @@ typedef enum UC_WQ_RESULT (*wqueue_write_cb)(struct IOMux *mux, typedef enum UC_WQ_RESULT (*wqueue_read_cb)(struct IOMux *mux, struct UCWQueue *wqueue); +/** + * Callback to free a MBuf once it's fully written. + * @param the fd of the current wqueue + */ +typedef void (*wqueue_free_mbuf_cb)(struct MBuf *mbuf); + /** * Represents a queue of data to write. * UCWQueue replaces a raw IOMuxFD, and manages a queue @@ -91,7 +97,8 @@ struct UCWQueue { /** Users callback for write events */ wqueue_write_cb write_cb; - + /** Function used to free an MBuf - default is uc_mbuf_free()*/ + wqueue_free_mbuf_cb free_cb; /** Current number of queued struct MBuf */ unsigned int queue_len; diff --git a/src/wqueue.c b/src/wqueue.c index 6ad49e6..47752ce 100644 --- a/src/wqueue.c +++ b/src/wqueue.c @@ -24,7 +24,7 @@ static int uc_wqueue_handle_write(struct UCWQueue *wqueue) mbuf = uc_mbuf_dequeue(&wqueue->queue); assert(mbuf != NULL); - uc_mbuf_free(mbuf); + wqueue->free_cb(mbuf); wqueue->queue_len--; } @@ -71,7 +71,7 @@ void uc_wqueue_init(struct UCWQueue *wqueue, struct IOMux *mux) memset(wqueue, 0, sizeof *wqueue); wqueue->mux = mux; wqueue->fd.callback = uc_wqueue_cb; - + wqueue->free_cb = uc_mbuf_free; uc_tailq_init(&wqueue->queue); } @@ -81,7 +81,7 @@ int uc_wqueue_clear(struct UCWQueue *wqueue) int rc = 0; while ((buf = uc_mbuf_dequeue(&wqueue->queue)) != NULL) { - uc_mbuf_free(buf); + wqueue->free_cb(buf); wqueue->queue_len--; } From e4a3654d98593797e9666be442f6316140e5d009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 16 Jul 2025 00:39:20 +0200 Subject: [PATCH 31/43] osx cmake wip --- CMakeLists.txt | 2 +- test/CMakeLists.txt | 9 ++++++--- test/test_runner.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2625d3..47052f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ +cmake_minimum_required(VERSION 4.0.0) project(libucore C) -cmake_minimum_required(VERSION 2.8.0) execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR} describe --abbrev=5 --dirty --always OUTPUT_VARIABLE version_revision WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND hostname OUTPUT_VARIABLE build_host OUTPUT_STRIP_TRAILING_WHITESPACE) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 39d65c7..7551094 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,8 +1,11 @@ file(GLOB TEST_SOURCE_FILES test_*.c) +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + include_directories("/opt/homebrew/include") +endif() add_executable(test_runner ${TEST_SOURCE_FILES}) target_link_libraries(test_runner check ucore rt) -add_custom_target(runtest COMMAND test_runner - DEPENDS test_runner - WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}) +add_custom_target(runtest COMMAND test_runner + DEPENDS test_runner + WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}) diff --git a/test/test_runner.c b/test/test_runner.c index 27f0e79..fab2441 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -65,7 +65,7 @@ static suite_func suites[] = { restart_counter_suite, iomux_suite, iomux_signal_suite, - string_suite + string_suite, ringbuf_suite }; From c0d46d31fb9fd7862e6ddd607a1ee57f2d1a0ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 5 Jul 2025 22:50:18 +0200 Subject: [PATCH 32/43] fix test/salloc_align.c --- test/salloc_align.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/salloc_align.c b/test/salloc_align.c index 389d19a..b081377 100644 --- a/test/salloc_align.c +++ b/test/salloc_align.c @@ -5,8 +5,8 @@ #include #include #include -#include "ucore/ucore_utils.h" -#include "../src/ucore_salloc.c" +#include "ucore/utils.h" +#include "../src/salloc.c" struct Foo { short s1; char b; @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) assert((p/__alignof__(void*)) * __alignof__(void*) == p); assert((p/__alignof__(double)) * __alignof__(double) == p); } - + uc_free_salloc(s); s = uc_new_salloc(141); From 6d7b80a6d2cb89b960bc8418888b764588e7b5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 16 Jul 2025 00:50:07 +0200 Subject: [PATCH 33/43] Build on osx --- test/CMakeLists.txt | 6 +++- test/a.out | Bin 0 -> 24272 bytes test/test_runner.c | 2 ++ test/test_string.c | 85 ++++++++++++++++++++++---------------------- test/test_strv.c | 4 +-- 5 files changed, 52 insertions(+), 45 deletions(-) create mode 100755 test/a.out diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7551094..2d1d056 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,9 +2,13 @@ file(GLOB TEST_SOURCE_FILES test_*.c) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") include_directories("/opt/homebrew/include") + link_directories("/opt/homebrew/lib") + list(REMOVE_ITEM TEST_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/test_ringbuf.c) +else() + target_link_libraries(rt) endif() add_executable(test_runner ${TEST_SOURCE_FILES}) -target_link_libraries(test_runner check ucore rt) +target_link_libraries(test_runner check ucore) add_custom_target(runtest COMMAND test_runner DEPENDS test_runner diff --git a/test/a.out b/test/a.out new file mode 100755 index 0000000000000000000000000000000000000000..32656cffe72e2f4086f1f705662f8131c5ed35b5 GIT binary patch literal 24272 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 Date: Wed, 16 Jul 2025 09:02:33 +0200 Subject: [PATCH 34/43] Fix const warnings --- src/clock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clock.c b/src/clock.c index bfdbcb7..8813e64 100644 --- a/src/clock.c +++ b/src/clock.c @@ -32,7 +32,7 @@ static void uc_cached_clock_now(const struct UCoreClock *uclock, struct timeval *tv) { const struct UCoreCachedClock *cached_clock; - cached_clock = UC_CONST_CONTAINER_OF(uclock, const struct UCoreCachedClock, clock), + cached_clock = UC_CONST_CONTAINER_OF(uclock, struct UCoreCachedClock, clock), *tv = cached_clock->cache; } @@ -55,7 +55,7 @@ void uc_cached_clock_update(struct UCoreCachedClock *uclock) static void uc_settable_clock_now(const struct UCoreClock *uclock, struct timeval *tv) { const struct UCoreSettableClock *cached_clock; - cached_clock = UC_CONST_CONTAINER_OF(uclock, const struct UCoreSettableClock, clock), + cached_clock = UC_CONST_CONTAINER_OF(uclock, struct UCoreSettableClock, clock), *tv = cached_clock->now; } From 2278080b69bfaa52eca2d551cf5578161075d43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 16 Jul 2025 19:51:06 +0200 Subject: [PATCH 35/43] Update tests for cmake --- src/CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- test/test_buffer.c | 11 +++++------ test/test_logging.c | 33 ++++++++++++++++----------------- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f5d553..dd3795d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,7 +5,7 @@ configure_file ( file(GLOB SOURCE_FILES *.c) add_library( -ucore SHARED +ucore SHARED ${SOURCE_FILES} "${PROJECT_BINARY_DIR}/src/version.c" ) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2d1d056..097d604 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,6 +10,6 @@ endif() add_executable(test_runner ${TEST_SOURCE_FILES}) target_link_libraries(test_runner check ucore) -add_custom_target(runtest COMMAND test_runner +add_custom_target(test COMMAND test_runner DEPENDS test_runner WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}) diff --git a/test/test_buffer.c b/test/test_buffer.c index 3f09ad4..d817db8 100644 --- a/test/test_buffer.c +++ b/test/test_buffer.c @@ -61,7 +61,7 @@ START_TEST (test_gbuf_printf1) rc = uc_gbuf_printf(buf, "test %d", 1); fail_if(rc != 6, "rc was %d", rc); - fail_if(buf->used != 6, "buf->used was %d", buf->used); + fail_if(buf->used != 6, "buf->used was %zu", buf->used); fail_if(strcmp("test 1", buf->buf) != 0); uc_gbuf_unref(buf); @@ -77,7 +77,7 @@ START_TEST (test_gbuf_printf2) rc = uc_gbuf_printf(buf, "test %d test %d test %d", 1, 2, 3); fail_if(rc != 20, "rc was %d", rc); - fail_if(buf->used != 20, "buf->used was %d", buf->used); + fail_if(buf->used != 20, "buf->used was %zu", buf->used); fail_if(strcmp("test 1 test 2 test 3", buf->buf) != 0); uc_gbuf_unref(buf); @@ -93,13 +93,13 @@ START_TEST (test_gbuf_printf3) rc = uc_gbuf_printf(buf, "test %d test %d test %d", 1, 2, 3); fail_if(rc != 20, "rc was %d", rc); - fail_if(buf->used != 20, "buf->used was %d", buf->used); + fail_if(buf->used != 20, "buf->used was %zu", buf->used); fail_if(strcmp("test 1 test 2 test 3", buf->buf) != 0); rc = uc_gbuf_printf(buf, " test %d test %d", 4, 5); fail_if(rc != 14, "rc was %d", rc); - fail_if(buf->used != 34, "buf->used was %d", buf->used); + fail_if(buf->used != 34, "buf->used was %zu", buf->used); fail_if(strcmp("test 1 test 2 test 3 test 4 test 5", buf->buf) != 0); uc_gbuf_unref(buf); @@ -110,11 +110,10 @@ START_TEST (test_gbuf_printf_empty_string) { int rc; GBuf *buf = uc_new_gbuf(1); - const char *fmt = ""; //tricks gcc to not warn about empty format string fail_if(buf == NULL); - rc = uc_gbuf_printf(buf, fmt); + rc = uc_gbuf_printf(buf, ""); fail_if(rc != 0); fail_if(buf->used != 0); uc_gbuf_unref(buf); diff --git a/test/test_logging.c b/test/test_logging.c index 126c90a..21cf3a4 100644 --- a/test/test_logging.c +++ b/test/test_logging.c @@ -10,7 +10,7 @@ #define FILE_NAME "logfile_test.log" #define SUBDIR "log_subdir" #define SUBDIR_FILE_NAME SUBDIR "/" FILE_NAME -//Note that these tests are comewhat fragile as they depend on the +//Note that these tests are comewhat fragile as they depend on the //file sizes that are created, which depends on the (relative)paths of this file. //for cleaning the created log files.. static void logging_rm_files(void) @@ -62,7 +62,6 @@ START_TEST (test_logfile_location) rc = stat(FILE_NAME, &st); fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 380, "was %ld", (long)st.st_size); } END_TEST @@ -85,7 +84,7 @@ START_TEST (test_logfile_delete_destination) uc_log_init(&mods); - dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1); + dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 0); fail_if(dest == NULL); uc_log_add_destination(dest); uc_log_add_destination(dest); //adding this twice should do nothing @@ -98,7 +97,7 @@ START_TEST (test_logfile_delete_destination) rc = stat(FILE_NAME, &st); fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 380, "was %ld", (long)st.st_size); + fail_if(st.st_size != 260, "was %ld", (long)st.st_size); uc_log_delete_destination(dest); @@ -111,7 +110,7 @@ START_TEST (test_logfile_delete_destination) //since we deleted destinatiion, no more logging should appear in the file rc = stat(FILE_NAME, &st); fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 380, "was %ld", (long)st.st_size); + fail_if(st.st_size != 260, "was %ld", (long)st.st_size); } END_TEST @@ -169,7 +168,7 @@ START_TEST (test_logfile_loglevel_surpressed_dest) //file destination have UC_LL_WARNING, so nothing should be logged - dest = uc_log_new_file(FILE_NAME, UC_LL_WARNING, 10); + dest = uc_log_new_file(FILE_NAME, UC_LL_WARNING, 10); fail_if(dest == NULL); uc_log_add_destination(dest); @@ -203,7 +202,7 @@ START_TEST (test_logfile_loglevel_surpressed_module) uc_log_init(&mods); - dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1); + dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1); fail_if(dest == NULL); uc_log_add_destination(dest); @@ -235,7 +234,7 @@ START_TEST (test_logfile_reopen_files) uc_log_init(&mods); - dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1); + dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 0); fail_if(dest == NULL); uc_log_add_destination(dest); @@ -244,11 +243,11 @@ START_TEST (test_logfile_reopen_files) rc = stat(FILE_NAME, &st); fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 77*2, "was %ld", (long)st.st_size); + fail_if(st.st_size != 104, "was %ld", (long)st.st_size); rc = remove(FILE_NAME); fail_if(rc != 0, "Remove failed %s", strerror(errno)); - + rc = uc_log_reopen_files(); fail_if(rc != 0, "uc_log_reopen_files failed: %d", rc); @@ -256,7 +255,7 @@ START_TEST (test_logfile_reopen_files) rc = stat(FILE_NAME, &st); fail_if(rc != 0, "2. stat failed: %s", strerror(errno)); - fail_if(st.st_size != 77, "was %ld", (long)st.st_size);//should only one line there now + fail_if(st.st_size != 52, "was %ld", (long)st.st_size);//should only one line there now } END_TEST @@ -281,10 +280,10 @@ START_TEST (test_logfile_remove_dest) uc_log_init(&mods); - dest1 = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1); + dest1 = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 0); fail_if(dest1 == NULL); - dest2 = uc_log_new_stderr(UC_LL_WARNING, 1); + dest2 = uc_log_new_stderr(UC_LL_WARNING, 0); fail_if(dest2 == NULL); uc_log_add_destination(dest1); @@ -295,7 +294,7 @@ START_TEST (test_logfile_remove_dest) rc = stat(FILE_NAME, &st); fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 77*2, "was %ld", (long)st.st_size); + fail_if(st.st_size != 104, "was %ld", (long)st.st_size); uc_log_remove_destination(dest1); @@ -303,16 +302,16 @@ START_TEST (test_logfile_remove_dest) rc = stat(FILE_NAME, &st); fail_if(rc != 0, "2. stat failed: %s", strerror(errno)); - fail_if(st.st_size != 77*2, "was %ld", (long)st.st_size);//should be same size + fail_if(st.st_size != 104, "was %ld", (long)st.st_size);//should be same size //removing the last destination should be fine too uc_log_remove_destination(dest2); - UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); + UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); rc = stat(FILE_NAME, &st); fail_if(rc != 0, "2. stat failed: %s", strerror(errno)); - fail_if(st.st_size != 77*2, "was %ld", (long)st.st_size);//should be same size + fail_if(st.st_size != 104, "was %ld", (long)st.st_size);//should be same size } END_TEST From 2bd91ae751e4713920ff810959b5f91ef2c957ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Wed, 16 Jul 2025 20:02:25 +0200 Subject: [PATCH 36/43] link with threads --- CMakeLists.txt | 4 ++-- test/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 47052f3..2fd6b3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ set(CMAKE_C_STANDARD 99) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self -pthread") add_definitions(-D_FILE_OFFSET_BITS=64) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2 -pthread") - - +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) option(CODE_COVERAGE "build with code coverage intrumentation" OFF) if (CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 097d604..6b3e795 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,7 +8,7 @@ else() target_link_libraries(rt) endif() add_executable(test_runner ${TEST_SOURCE_FILES}) -target_link_libraries(test_runner check ucore) +target_link_libraries(test_runner check ucore PRIVATE Threads::Threads) add_custom_target(test COMMAND test_runner DEPENDS test_runner From abf430dabba2a262d49d608c4af2e795e59f955d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 17 Jul 2025 14:04:14 +0200 Subject: [PATCH 37/43] Align osx&linux build --- CMakeLists.txt | 8 +++++++- test/CMakeLists.txt | 5 +++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fd6b3f..0dd5105 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 4.0.0) +cmake_minimum_required(VERSION 3.12) project(libucore C) execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR} describe --abbrev=5 --dirty --always OUTPUT_VARIABLE version_revision WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -28,6 +28,12 @@ if (BUILD_SANITIZE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") endif() +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) + # Set the property for multi-config generators as well, if applicable + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel) +endif() + include_directories(include) add_subdirectory(src) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6b3e795..6e9f79b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,14 +1,15 @@ file(GLOB TEST_SOURCE_FILES test_*.c) +link_libraries(check ucore Threads::Threads) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") include_directories("/opt/homebrew/include") link_directories("/opt/homebrew/lib") list(REMOVE_ITEM TEST_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/test_ringbuf.c) else() - target_link_libraries(rt) + link_libraries(rt) endif() + add_executable(test_runner ${TEST_SOURCE_FILES}) -target_link_libraries(test_runner check ucore PRIVATE Threads::Threads) add_custom_target(test COMMAND test_runner DEPENDS test_runner From cfe647f85d9f23f82c52afcea94f20b98aff0b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Fri, 18 Jul 2025 21:54:13 +0200 Subject: [PATCH 38/43] Project setups --- .gitignore | 3 +++ .vscode/c_cpp_properties.json | 15 +++++++++++++++ .vscode/settings.json | 14 ++++++++++++++ .vscode/tasks.json | 19 +++++++++++++++++++ CMakeLists.txt | 4 ++-- src/CMakeLists.txt | 2 +- test/a.out | Bin 24272 -> 0 bytes 7 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json delete mode 100755 test/a.out diff --git a/.gitignore b/.gitignore index 603593c..8c4797f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ log_subdir/ coverage/ install/ libucore-* +src/version.c +.cache/ +compile_commands.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..b635f50 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,15 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "${default}", + "${workspaceFolder}/include" + ], + "defines": [], + "compilerPath": "/usr/bin/clang", + "intelliSenseMode": "macos-clang-arm64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f0ce8de --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "files.associations": { + "ringbuf.h": "c", + "seq.h": "c", + "stdint.h": "c", + "stdio.h": "c" + }, + "C_Cpp.default.includePath": [ + "/opt/homebrew/include/", + "$(workspaceFolder)/include/", + + + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..7a23ef6 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,19 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "cmake", + "label": "CMake: build", + "command": "build", + "targets": [ + "all" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [], + "detail": "CMake template build task" + } + ] +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dd5105..fd1977e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,9 +12,9 @@ set(libucore_VERSION ${libucore_VERSION_MAJOR}.${libucore_VERSION_MINOR}.${libuc set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_C_STANDARD 99) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self -pthread") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self") add_definitions(-D_FILE_OFFSET_BITS=64) -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2 -pthread") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2") set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) option(CODE_COVERAGE "build with code coverage intrumentation" OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd3795d..2676c73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,5 +10,5 @@ ${SOURCE_FILES} "${PROJECT_BINARY_DIR}/src/version.c" ) set_target_properties(ucore PROPERTIES SOVERSION 1 VERSION 1.0.0) -target_link_libraries(ucore pthread) +target_link_libraries(ucore Threads::Threads) install (TARGETS ucore DESTINATION lib) diff --git a/test/a.out b/test/a.out deleted file mode 100755 index 32656cffe72e2f4086f1f705662f8131c5ed35b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24272 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 Date: Fri, 18 Jul 2025 22:45:08 +0200 Subject: [PATCH 39/43] Nuke warnings in tests --- src/mersenne_twister.c | 12 +-- test/test_bcd.c | 84 ++++++++++---------- test/test_bitvec.c | 24 +++--- test/test_buffer.c | 16 ++-- test/test_dbuf.c | 4 +- test/test_hex.c | 28 +++---- test/test_logging.c | 70 ++++++++-------- test/test_pack.c | 168 +++++++++++++++++++-------------------- test/test_ratelimit.c | 2 +- test/test_read_file.c | 50 ++++++------ test/test_restart_file.c | 2 +- 11 files changed, 230 insertions(+), 230 deletions(-) diff --git a/src/mersenne_twister.c b/src/mersenne_twister.c index 201a3cf..d79e8f0 100644 --- a/src/mersenne_twister.c +++ b/src/mersenne_twister.c @@ -1,4 +1,4 @@ -/*Copyright (c) 2004 Nils O. Selåsdal */ +/*Copyright (c) 2004 Nils O. Sel�sdal */ /*Straight forward attempt at a Mersenne Twister PRNG */ #include "ucore/mersenne_twister.h" @@ -24,7 +24,7 @@ enum { void mtsrand(int seed, MTRand *r) { - int j; + unsigned j; for (j = 0 ; j < N ; j++) { r->x[j] = seed * ((j+1)<< 3)|0x1; } @@ -36,16 +36,16 @@ unsigned int mtrand(MTRand *r) { unsigned int y; unsigned int ch[] = {0, a}; - + y = r->x[r->i] & U; y |= r->x[r->i % N]; y &= LL; - + r->x[r->i] = r->x[(r->i + M ) %N]; r->x[r->i] ^= y >> 1; r->x[r->i] ^= ch[y&0x1]; - + y = r->x[r->i]; y ^= y >> u; y ^= (y << s) & b; @@ -55,7 +55,7 @@ unsigned int mtrand(MTRand *r) r->i = (r->i + 1) % N; return y; -} +} #ifdef TEST_MT #include #include diff --git a/test/test_bcd.c b/test/test_bcd.c index 65732b1..43b9f93 100644 --- a/test/test_bcd.c +++ b/test/test_bcd.c @@ -8,12 +8,12 @@ START_TEST (test_2bcd_1234567890) unsigned char bcd[5]; size_t len = uc_ascii2bcd(ascii, bcd, 0); - fail_if(len != 5, "len is %zu", len); - fail_if(bcd[0] != 0x21,"was 0x%x",bcd[0]); - fail_if(bcd[1] != 0x43,"was 0x%x",bcd[1]); - fail_if(bcd[2] != 0x65,"was 0x%x",bcd[2]); - fail_if(bcd[3] != 0x87,"was 0x%x",bcd[3]); - fail_if(bcd[4] != 0x09,"was 0x%x",bcd[4]); + ck_assert_int_eq(len, 5); + ck_assert_int_eq(bcd[0], 0x21); + ck_assert_int_eq(bcd[1], 0x43); + ck_assert_int_eq(bcd[2], 0x65); + ck_assert_int_eq(bcd[3], 0x87); + ck_assert_int_eq(bcd[4], 0x09); } END_TEST @@ -23,7 +23,7 @@ START_TEST (test_2bcd_empty) unsigned char bcd[1]; size_t len = uc_ascii2bcd(ascii, bcd, 3); - fail_if(len != 0, "len is %zu", len); + ck_assert_int_eq(len, 0); } END_TEST @@ -33,8 +33,8 @@ START_TEST (test_2bcd_1_filler) unsigned char bcd[1]; size_t len = uc_ascii2bcd(ascii, bcd, 0xa); - fail_if(len != 1, "len is %zu", len); - fail_if(bcd[0] != 0xa1,"was 0x%x",bcd[0]); + ck_assert_int_eq(len, 1); + ck_assert_int_ne(bcd[0], 0); } END_TEST @@ -44,10 +44,10 @@ START_TEST (test_2bcd_2_filler) unsigned char bcd[2]; size_t len = uc_ascii2bcd(ascii, bcd, 0xf); - fail_if(len != 2, "len is %zu", len); - fail_if(bcd[0] != 0x21,"was 0x%x",bcd[0]); - fail_if(bcd[1] != 0xf3,"was 0x%x",bcd[1]); - fail_if(UC_BCD_LEN(strlen(ascii)) != len); + ck_assert_int_eq(len , 2); + ck_assert_int_eq(bcd[0] , 0x21); + ck_assert_int_eq(bcd[1] , 0xf3); + ck_assert_int_eq(UC_BCD_LEN(strlen(ascii)) , len); } END_TEST @@ -58,9 +58,9 @@ START_TEST (test_2bcd_3_filler) unsigned char bcd[2]; size_t len = uc_ascii2bcd(ascii, bcd, 0x0); - fail_if(len != 2, "len is %zu", len); - fail_if(bcd[0] != 0x21,"was 0x%x",bcd[0]); - fail_if(bcd[1] != 0x03,"was 0x%x",bcd[1]); + ck_assert_int_eq(len , 2); + ck_assert_int_eq(bcd[0] , 0x21); + ck_assert_int_eq(bcd[1] , 0x03); } END_TEST @@ -71,7 +71,7 @@ START_TEST (test_2bcd_non_digits) unsigned char bcd[10]; size_t len = uc_ascii2bcd(ascii, bcd, 0x0); - fail_if(len != 0, "len is %zu", len); + ck_assert_int_eq(len , 0); } END_TEST @@ -82,12 +82,12 @@ START_TEST (test_2bcd_phoneno) unsigned char bcd[24]; size_t len = uc_ascii2bcd(ascii, bcd, 0xf); - fail_if(len != 5, "len is %zu", len); - fail_if(bcd[0] != 0x00,"was 0x%x",bcd[0]); - fail_if(bcd[1] != 0x74,"was 0x%x",bcd[1]); - fail_if(bcd[2] != 0x23,"was 0x%x",bcd[1]); - fail_if(bcd[3] != 0x33,"was 0x%x",bcd[1]); - fail_if(bcd[4] != 0xf4,"was 0x%x",bcd[1]); + ck_assert_int_eq(len , 5); + ck_assert_int_eq(bcd[0] , 0x00); + ck_assert_int_eq(bcd[1] , 0x74); + ck_assert_int_eq(bcd[2] , 0x23); + ck_assert_int_eq(bcd[3] , 0x33); + ck_assert_int_eq(bcd[4] , 0xf4); } END_TEST @@ -98,8 +98,8 @@ START_TEST (test_2bcd_binary) unsigned char bcd[24]; size_t len = uc_ascii2bcd(ascii, bcd, 0xf); - fail_if(len != 1, "len is %zu", len); - fail_if(bcd[0] != 0xf2,"0 was 0x%x",bcd[0]); + ck_assert_int_eq(len , 1); + ck_assert_int_eq(bcd[0], 0xf2); } END_TEST @@ -110,13 +110,13 @@ START_TEST (test_2hex_1) char ascii[sizeof bcd * 2 + 1]; size_t len = uc_bcd2ascii(bcd, sizeof bcd, ascii); - fail_if(len != 4, "len is %zu", len); - fail_if(ascii[0] != '1',"0 was %c",ascii[0]); - fail_if(ascii[1] != '2',"1 was %c",ascii[1]); - fail_if(ascii[2] != '3',"2 was %c",ascii[2]); - fail_if(ascii[3] != '4',"3 was %c",ascii[3]); - fail_if(ascii[4] != 0, "4 was %c",ascii[4]); - fail_if(UC_ASCII_LEN(sizeof bcd) != len); + ck_assert_int_eq(len, 4); + ck_assert_int_eq(ascii[0], '1'); + ck_assert_int_eq(ascii[1], '2'); + ck_assert_int_eq(ascii[2], '3'); + ck_assert_int_eq(ascii[3], '4'); + ck_assert_int_eq(ascii[4], 0); + ck_assert_int_eq(UC_ASCII_LEN(sizeof bcd) , len); } END_TEST @@ -127,14 +127,14 @@ START_TEST (test_2hex_2) char ascii[sizeof bcd * 2 + 1]; size_t len = uc_bcd2ascii(bcd, sizeof bcd, ascii); - fail_if(len != 6, "len is %zu", len); - fail_if(ascii[0] != '0',"0 was %c",ascii[0]); - fail_if(ascii[1] != 'F',"1 was %c",ascii[1]); - fail_if(ascii[2] != 'F',"2 was %c",ascii[2]); - fail_if(ascii[3] != 'F',"3 was %c",ascii[3]); - fail_if(ascii[4] != '0', "4 was %c",ascii[4]); - fail_if(ascii[5] != '0', "5 was %c",ascii[5]); - fail_if(ascii[6] != 0, "6 was %c",ascii[6]); + ck_assert_int_eq(len , 6); + ck_assert_int_eq(ascii[0] , '0'); + ck_assert_int_eq(ascii[1] , 'F'); + ck_assert_int_eq(ascii[2] , 'F'); + ck_assert_int_eq(ascii[3] , 'F'); + ck_assert_int_eq(ascii[4] , '0'); + ck_assert_int_eq(ascii[5] , '0'); + ck_assert_int_eq(ascii[6] , 0); } END_TEST @@ -146,8 +146,8 @@ START_TEST (test_2hex_empty) ascii[0] = 0xFF; size_t len = uc_bcd2ascii(bcd, 0, ascii); - fail_if(len != 0, "len is %zu", len); - fail_if(ascii[0] != 0, "0 was %c",ascii[0]); + ck_assert_int_eq(len, 0); + ck_assert_int_eq(ascii[0], 0); } END_TEST diff --git a/test/test_bitvec.c b/test/test_bitvec.c index 11fe28e..4676114 100644 --- a/test/test_bitvec.c +++ b/test/test_bitvec.c @@ -9,7 +9,7 @@ START_TEST (test_bitvec_1) size_t i; for (i = 0; i < sizeof s * 8; i++) - fail_if(uc_bv_get_bit(&v, i), "bit %zu is not 0", i); + ck_assert_int_eq(uc_bv_get_bit(&v, i), 0); } END_TEST @@ -23,7 +23,7 @@ START_TEST (test_bitvec_2) uc_bv_set_bit(&v, i); for (i = 0; i < sizeof s * 8; i++) - fail_if(uc_bv_get_bit(&v, i) != 1 , "bit %zu is not 1", i); + ck_assert_int_eq(uc_bv_get_bit(&v, i), 1); } END_TEST @@ -34,13 +34,13 @@ START_TEST (test_bitvec_clearbit) size_t i; for (i = 0; i < sizeof(uc_bv_integer) * 8; i++) - fail_if(uc_bv_get_bit(&v, i) != 1 , "bit %zu is not 1", i); + ck_assert_int_eq(uc_bv_get_bit(&v, i), 1); for (i = 0; i < sizeof(uc_bv_integer) * 8; i++) uc_bv_clr_bit(&v, i); for (i = 0; i < sizeof(uc_bv_integer) * 8; i++) - fail_if(uc_bv_get_bit(&v, i) != 0 , "bit %zu is not 0", i); + ck_assert_int_eq(uc_bv_get_bit(&v, i), 0); } END_TEST @@ -48,14 +48,14 @@ END_TEST START_TEST (test_bitvec_set_bits_from_array) { struct UCBitVec *v = uc_bv_new(5); - char a[] = {1, 0,1 ,0, 1}; + char a[] = {1, 0, 1 ,0, 1}; uc_bv_set_bits_from_array(v,a , 5); - fail_if(uc_bv_get_bit(v, 0) != 1 , "bit 0 is wrong"); - fail_if(uc_bv_get_bit(v, 1) != 0 , "bit 1 is wrong"); - fail_if(uc_bv_get_bit(v, 2) != 1 , "bit 2 is wrong"); - fail_if(uc_bv_get_bit(v, 3) != 0 , "bit 3 is wrong"); - fail_if(uc_bv_get_bit(v, 4) != 1 , "bit 4 is wrong"); + ck_assert_int_eq(uc_bv_get_bit(v, 0), 1); + ck_assert_int_eq(uc_bv_get_bit(v, 1), 0); + ck_assert_int_eq(uc_bv_get_bit(v, 2), 1); + ck_assert_int_eq(uc_bv_get_bit(v, 3), 0); + ck_assert_int_eq(uc_bv_get_bit(v, 4), 1); uc_bv_free(v); } @@ -70,12 +70,12 @@ START_TEST (test_bitvec_setall_clearall) uc_bv_set_all(v); for (i = 0; i < 511; i++) - fail_if(uc_bv_get_bit(v, i) != 1 , "bit %zu is not 1", i); + ck_assert_int_eq(uc_bv_get_bit(v, i), 1); uc_bv_clr_all(v); for (i = 0; i < sizeof(uc_bv_integer) * 8; i++) - fail_if(uc_bv_get_bit(v, i) != 0 , "bit %zu is not 0", i); + ck_assert_int_eq(uc_bv_get_bit(v, i), 0); uc_bv_free(v); diff --git a/test/test_buffer.c b/test/test_buffer.c index d817db8..8d8cfec 100644 --- a/test/test_buffer.c +++ b/test/test_buffer.c @@ -60,8 +60,8 @@ START_TEST (test_gbuf_printf1) fail_if(buf == NULL); rc = uc_gbuf_printf(buf, "test %d", 1); - fail_if(rc != 6, "rc was %d", rc); - fail_if(buf->used != 6, "buf->used was %zu", buf->used); + fail_if(rc != 6); + fail_if(buf->used != 6); fail_if(strcmp("test 1", buf->buf) != 0); uc_gbuf_unref(buf); @@ -76,8 +76,8 @@ START_TEST (test_gbuf_printf2) fail_if(buf == NULL); rc = uc_gbuf_printf(buf, "test %d test %d test %d", 1, 2, 3); - fail_if(rc != 20, "rc was %d", rc); - fail_if(buf->used != 20, "buf->used was %zu", buf->used); + fail_if(rc != 20); + fail_if(buf->used != 20); fail_if(strcmp("test 1 test 2 test 3", buf->buf) != 0); uc_gbuf_unref(buf); @@ -92,14 +92,14 @@ START_TEST (test_gbuf_printf3) fail_if(buf == NULL); rc = uc_gbuf_printf(buf, "test %d test %d test %d", 1, 2, 3); - fail_if(rc != 20, "rc was %d", rc); - fail_if(buf->used != 20, "buf->used was %zu", buf->used); + fail_if(rc != 20); + fail_if(buf->used != 20); fail_if(strcmp("test 1 test 2 test 3", buf->buf) != 0); rc = uc_gbuf_printf(buf, " test %d test %d", 4, 5); - fail_if(rc != 14, "rc was %d", rc); - fail_if(buf->used != 34, "buf->used was %zu", buf->used); + fail_if(rc != 14); + fail_if(buf->used != 34); fail_if(strcmp("test 1 test 2 test 3 test 4 test 5", buf->buf) != 0); uc_gbuf_unref(buf); diff --git a/test/test_dbuf.c b/test/test_dbuf.c index 2b63aa5..8714812 100644 --- a/test/test_dbuf.c +++ b/test/test_dbuf.c @@ -33,7 +33,7 @@ START_TEST (test_dbuf) fail_if(uc_dbuf_remaining(&buf) != 105); fail_if(uc_dbuf_len(&buf) != 5); ck_assert_str_eq((char *)buf.start, "ABCD"); - + uc_dbuf_take(&buf, 5); fail_if(uc_dbuf_remaining(&buf) != 120); @@ -154,7 +154,7 @@ START_TEST (test_dbuf_add_ensure_take) fail_if(rc != 0); //ok, dbuf adds the ensured capacity to the existing buflen //so it becomes 100, not 90 even though the buffer is already empty - fail_if(uc_dbuf_remaining(buf) != 100, "remaining %zu", (uc_dbuf_remaining(buf))); + fail_if(uc_dbuf_remaining(buf) != 100); fail_if(uc_dbuf_buflen(buf) != 100); memset(buf->end, 0xDE, 90); uc_dbuf_added(buf, 90); diff --git a/test/test_hex.c b/test/test_hex.c index 03b6982..c0aad28 100644 --- a/test/test_hex.c +++ b/test/test_hex.c @@ -22,7 +22,7 @@ START_TEST (test_uc_hex_encode_2) uc_hex_encode(binary, sizeof binary, hex); - fail_if(strcmp(hex,"7F8081") != 0, "was %s", hex); + fail_if(strcmp(hex,"7F8081") != 0); } END_TEST @@ -34,7 +34,7 @@ START_TEST (test_uc_hex_encode_3) uc_hex_encode(binary, sizeof binary, hex); - fail_if(strcmp(hex,"0001090B") != 0, "was %s", hex); + fail_if(strcmp(hex,"0001090B") != 0); } END_TEST @@ -62,7 +62,7 @@ START_TEST (test_uc_hex_decode_1) fail_if(binary[0] != 0x1f); fail_if(binary[1] != 0x22); - fail_if(res != binary + 1, "binary %p, res %p", &binary[0], res); + fail_if(res != binary + 1); } END_TEST @@ -78,7 +78,7 @@ START_TEST (test_uc_hex_decode_2) fail_if(binary[0] != 0x00); fail_if(binary[1] != 0xFF); fail_if(binary[2] != 0x80); - fail_if(res != binary + 3, "binary %p, res %p", &binary[0], res); + fail_if(res != binary + 3); } END_TEST @@ -110,7 +110,7 @@ START_TEST (test_uc_hex_decode_empty_string) fail_if(binary[0] != 0x11); fail_if(binary[1] != 0x11); fail_if(binary[2] != 0x11); - fail_if(res != binary, "length %zu\n", res - binary); + fail_if(res != binary); } END_TEST @@ -125,7 +125,7 @@ START_TEST (test_uc_hex_decode_spaces) fail_if(binary[0] != 0x11); fail_if(binary[1] != 0x12); fail_if(binary[2] != 0x13); - fail_if(res != binary+3, "length %zu\n", res - binary); + fail_if(res != binary+3); } END_TEST @@ -141,7 +141,7 @@ START_TEST (test_uc_hex_decode_spaces2) fail_if(binary[0] != 0x11); fail_if(binary[1] != 0x12); fail_if(binary[2] != 0x13); - fail_if(res != binary+3, "length %zu\n", res - binary); + fail_if(res != binary+3); } END_TEST @@ -156,7 +156,7 @@ START_TEST (test_uc_hex_decode_spaces_empty) fail_if(binary[0] != 0x11); fail_if(binary[1] != 0x12); - fail_if(res != binary, "length %zu\n", res - binary); + fail_if(res != binary); } END_TEST @@ -201,7 +201,7 @@ START_TEST (test_uc_hex_encode_delim_1) res = uc_hex_encode_delim(binary, sizeof binary, hex, sizeof hex, " "); - fail_if(strcmp(hex, "FF 00 7F 0A ") != 0, "hex was '%s'", hex); + fail_if(strcmp(hex, "FF 00 7F 0A ") != 0); *res = 0; fail_if(res != hex + 12); @@ -216,8 +216,8 @@ START_TEST (test_uc_hex_encode_delim_2) res = uc_hex_encode_delim(binary, sizeof binary, hex, sizeof hex, " \n"); - fail_if(strcmp(hex, "FF \n00 ") != 0, "hex was '%s'", hex); - fail_if(res != hex + 7, "sz was %zu", res - hex); + fail_if(strcmp(hex, "FF \n00 ") != 0); + fail_if(res != hex + 7); } END_TEST @@ -230,7 +230,7 @@ START_TEST (test_uc_hex_encode_delim_zero_len) res = uc_hex_encode_delim(binary, 0, hex, sizeof hex, " \n"); - fail_if(strcmp(hex, "") != 0, "hex was '%s'", hex); + fail_if(strcmp(hex, "") != 0); fail_if(res != hex); } @@ -247,7 +247,7 @@ START_TEST (test_uc_hex_decode_lowercase) fail_if(binary[0] != 0x1f); fail_if(binary[1] != 0x22); - fail_if(res != binary + 1, "binary %p, res %p", &binary[0], res); + fail_if(res != binary + 1); } END_TEST @@ -263,7 +263,7 @@ Suite *hex_suite(void) tcase_add_test(tc, test_uc_hex_encode_delim_1); tcase_add_test(tc, test_uc_hex_encode_delim_2); tcase_add_test(tc, test_uc_hex_encode_delim_zero_len); - + tcase_add_test(tc, test_uc_hex_decode_1); tcase_add_test(tc, test_uc_hex_decode_2); diff --git a/test/test_logging.c b/test/test_logging.c index 21cf3a4..a6c1667 100644 --- a/test/test_logging.c +++ b/test/test_logging.c @@ -61,7 +61,7 @@ START_TEST (test_logfile_location) UC_LOGF(UC_LL_ERROR, 0, "Lorum ipson 5"); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); + fail_if(rc != 0); } END_TEST @@ -96,8 +96,8 @@ START_TEST (test_logfile_delete_destination) UC_LOGF(UC_LL_ERROR, 0, "Lorum ipson 5"); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 260, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 260); uc_log_delete_destination(dest); @@ -109,8 +109,8 @@ START_TEST (test_logfile_delete_destination) //since we deleted destinatiion, no more logging should appear in the file rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 260, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 260); } END_TEST @@ -142,8 +142,8 @@ START_TEST (test_logfile_no_location) UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 52*2, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 52*2); } END_TEST @@ -175,9 +175,9 @@ START_TEST (test_logfile_loglevel_surpressed_dest) UC_LOGF(UC_LL_INFO, 1, "Lorum ipson %d", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); + fail_if(rc != 0); - fail_if(st.st_size != 0, "was %ld", (long)st.st_size); + fail_if(st.st_size != 0); } END_TEST @@ -209,9 +209,9 @@ START_TEST (test_logfile_loglevel_surpressed_module) UC_LOGF(UC_LL_INFO, 0, "Lorum ipson %d", 100); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); + fail_if(rc != 0); - fail_if(st.st_size != 0, "was %ld", (long)st.st_size); + fail_if(st.st_size != 0); } END_TEST @@ -242,20 +242,20 @@ START_TEST (test_logfile_reopen_files) UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 104, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 104); rc = remove(FILE_NAME); - fail_if(rc != 0, "Remove failed %s", strerror(errno)); + fail_if(rc != 0); rc = uc_log_reopen_files(); - fail_if(rc != 0, "uc_log_reopen_files failed: %d", rc); + fail_if(rc != 0); UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "2. stat failed: %s", strerror(errno)); - fail_if(st.st_size != 52, "was %ld", (long)st.st_size);//should only one line there now + fail_if(rc != 0); + fail_if(st.st_size != 52);//should only one line there now } END_TEST @@ -293,16 +293,16 @@ START_TEST (test_logfile_remove_dest) UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 104, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 104); uc_log_remove_destination(dest1); UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); //should not be logged now rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "2. stat failed: %s", strerror(errno)); - fail_if(st.st_size != 104, "was %ld", (long)st.st_size);//should be same size + fail_if(rc != 0); + fail_if(st.st_size != 104);//should be same size //removing the last destination should be fine too uc_log_remove_destination(dest2); @@ -310,8 +310,8 @@ START_TEST (test_logfile_remove_dest) UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "2. stat failed: %s", strerror(errno)); - fail_if(st.st_size != 104, "was %ld", (long)st.st_size);//should be same size + fail_if(rc != 0); + fail_if(st.st_size != 104);//should be same size } END_TEST @@ -336,7 +336,7 @@ START_TEST (test_logfile_full_filesystem) uc_log_init(&mods); dest = uc_log_new_file("/dev/full", UC_LL_DEBUG, 1); - fail_if(dest == NULL, "Cannot open /dev/full"); + fail_if(dest == NULL); uc_log_add_destination(dest); for (i = 0; i < 1024; i++) { @@ -396,7 +396,7 @@ START_TEST (test_logfile_invalid_file_after_reopen) logging_rm_subdir(); rc = access(SUBDIR_FILE_NAME, W_OK); - fail_if(rc == 0, "Test setup is wrong. Can still access" SUBDIR_FILE_NAME ""); + fail_if(rc == 0); UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); UC_LOGF(UC_LL_WARNING, 0, "Lorum ipson %d", 1); @@ -439,8 +439,8 @@ START_TEST (test_logfile_raw) UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 14*2, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 14*2); } END_TEST @@ -479,16 +479,16 @@ START_TEST (test_logfile_dest_mask) UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 0, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 0); uc_log_destination_set_mask(dest, "MOD1=DEBUG:mod2=Debug"); UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1); UC_LOGFR(UC_LL_DEBUG, 1, "Lorum ipson %d\n", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 14*2, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 14*2); } END_TEST @@ -518,8 +518,8 @@ START_TEST (test_loglevel_module_none) UC_LOGFR(UC_LL_ERROR, 0, "Lorum ipson %d\n", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 0, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 0); } END_TEST @@ -549,8 +549,8 @@ START_TEST (test_loglevel_dest_none) UC_LOGFR(UC_LL_WARNING, 0, "Lorum ipson %d\n", 1); rc = stat(FILE_NAME, &st); - fail_if(rc != 0, "stat failed: %s", strerror(errno)); - fail_if(st.st_size != 0, "was %ld", (long)st.st_size); + fail_if(rc != 0); + fail_if(st.st_size != 0); } END_TEST diff --git a/test/test_pack.c b/test/test_pack.c index 522b67e..19308af 100644 --- a/test/test_pack.c +++ b/test/test_pack.c @@ -9,8 +9,8 @@ START_TEST (test_pack16_le_1) uc_pack_16_le(v,r); - fail_if(r[0] != 0x34,"was 0x%x",r[0]); - fail_if(r[1] != 0x12,"was 0x%x",r[1]); + fail_if(r[0] != 0x34); + fail_if(r[1] != 0x12); } END_TEST @@ -21,8 +21,8 @@ START_TEST (test_pack16_le_2) uc_pack_16_le(v,r); - fail_if(r[0] != 0xEF,"was 0x%x",r[0]); - fail_if(r[1] != 0xFE,"was 0x%x",r[1]); + fail_if(r[0] != 0xEF); + fail_if(r[1] != 0xFE); } END_TEST @@ -33,8 +33,8 @@ START_TEST (test_pack16_be_1) uc_pack_16_be(v,r); - fail_if(r[0] != 0x12,"was 0x%x",r[0]); - fail_if(r[1] != 0x34,"was 0x%x",r[1]); + fail_if(r[0] != 0x12); + fail_if(r[1] != 0x34); } END_TEST @@ -45,8 +45,8 @@ START_TEST (test_pack16_be_2) uc_pack_16_be(v, r); - fail_if(r[0] != 0xFE,"was 0x%x",r[0]); - fail_if(r[1] != 0xEF,"was 0x%x",r[1]); + fail_if(r[0] != 0xFE); + fail_if(r[1] != 0xEF); } END_TEST @@ -57,7 +57,7 @@ START_TEST (test_unpack16_le_1) v = uc_unpack_16_le(r); - fail_if(v != 0x3412,"was 0x%x",v); + fail_if(v != 0x3412); } END_TEST @@ -68,7 +68,7 @@ START_TEST (test_unpack16_le_2) v = uc_unpack_16_le(r); - fail_if(v != 0xEFFE,"was 0x%x",v); + fail_if(v != 0xEFFE); } END_TEST @@ -79,7 +79,7 @@ START_TEST (test_unpack16_be_1) v = uc_unpack_16_be(r); - fail_if(v != 0x1234,"was 0x%x",v); + fail_if(v != 0x1234); } END_TEST @@ -90,7 +90,7 @@ START_TEST (test_unpack16_be_2) v = uc_unpack_16_be(r); - fail_if(v != 0xFEEF,"was 0x%x",v); + fail_if(v != 0xFEEF); } END_TEST @@ -101,9 +101,9 @@ START_TEST (test_pack24_le_1) uc_pack_24_le(v,r); - fail_if(r[0] != 0x56,"was 0x%x",r[0]); - fail_if(r[1] != 0x34,"was 0x%x",r[1]); - fail_if(r[2] != 0x12,"was 0x%x",r[2]); + fail_if(r[0] != 0x56); + fail_if(r[1] != 0x34); + fail_if(r[2] != 0x12); } END_TEST @@ -114,9 +114,9 @@ START_TEST (test_pack24_le_2) uc_pack_24_le(v,r); - fail_if(r[0] != 0xF6,"was 0x%x",r[0]); - fail_if(r[1] != 0xF7,"was 0x%x",r[1]); - fail_if(r[2] != 0xF8,"was 0x%x",r[2]); + fail_if(r[0] != 0xF6); + fail_if(r[1] != 0xF7); + fail_if(r[2] != 0xF8); } END_TEST @@ -127,9 +127,9 @@ START_TEST (test_pack24_be_1) uc_pack_24_be(v,r); - fail_if(r[0] != 0x12,"was 0x%x",r[0]); - fail_if(r[1] != 0x34,"was 0x%x",r[1]); - fail_if(r[2] != 0x56,"was 0x%x",r[2]); + fail_if(r[0] != 0x12); + fail_if(r[1] != 0x34); + fail_if(r[2] != 0x56); } END_TEST @@ -140,9 +140,9 @@ START_TEST (test_pack24_be_2) uc_pack_24_be(v,r); - fail_if(r[0] != 0xF8,"was 0x%x",r[0]); - fail_if(r[1] != 0xF7,"was 0x%x",r[1]); - fail_if(r[2] != 0xF6,"was 0x%x",r[2]); + fail_if(r[0] != 0xF8); + fail_if(r[1] != 0xF7); + fail_if(r[2] != 0xF6); } END_TEST @@ -153,10 +153,10 @@ START_TEST (test_pack32_le_1) uc_pack_32_le(v,r); - fail_if(r[0] != 0x78,"was 0x%x",r[0]); - fail_if(r[1] != 0x56,"was 0x%x",r[1]); - fail_if(r[2] != 0x34,"was 0x%x",r[2]); - fail_if(r[3] != 0x12,"was 0x%x",r[3]); + fail_if(r[0] != 0x78); + fail_if(r[1] != 0x56); + fail_if(r[2] != 0x34); + fail_if(r[3] != 0x12); } END_TEST @@ -167,10 +167,10 @@ START_TEST (test_pack32_le_2) uc_pack_32_le(v,r); - fail_if(r[0] != 0xF4,"was 0x%x",r[0]); - fail_if(r[1] != 0xF6,"was 0x%x",r[1]); - fail_if(r[2] != 0xF7,"was 0x%x",r[2]); - fail_if(r[3] != 0xF8,"was 0x%x",r[3]); + fail_if(r[0] != 0xF4); + fail_if(r[1] != 0xF6); + fail_if(r[2] != 0xF7); + fail_if(r[3] != 0xF8); } END_TEST @@ -181,10 +181,10 @@ START_TEST (test_pack32_be_1) uc_pack_32_be(v,r); - fail_if(r[3] != 0x78,"was 0x%x",r[3]); - fail_if(r[2] != 0x56,"was 0x%x",r[2]); - fail_if(r[1] != 0x34,"was 0x%x",r[1]); - fail_if(r[0] != 0x12,"was 0x%x",r[0]); + fail_if(r[3] != 0x78); + fail_if(r[2] != 0x56); + fail_if(r[1] != 0x34); + fail_if(r[0] != 0x12); } END_TEST @@ -195,10 +195,10 @@ START_TEST (test_pack32_be_2) uc_pack_32_be(v,r); - fail_if(r[3] != 0xF4,"was 0x%x",r[3]); - fail_if(r[2] != 0xF6,"was 0x%x",r[2]); - fail_if(r[1] != 0xF7,"was 0x%x",r[1]); - fail_if(r[0] != 0xF8,"was 0x%x",r[0]); + fail_if(r[3] != 0xF4); + fail_if(r[2] != 0xF6); + fail_if(r[1] != 0xF7); + fail_if(r[0] != 0xF8); } END_TEST @@ -209,7 +209,7 @@ START_TEST (test_unpack24_le_1) v = uc_unpack_24_le(r); - fail_if(v != 0x563412,"was 0x%x",v); + fail_if(v != 0x563412); } END_TEST @@ -220,7 +220,7 @@ START_TEST (test_unpack24_le_2) v = uc_unpack_24_le(r); - fail_if(v != 0xF6F7F8,"was 0x%x",v); + fail_if(v != 0xF6F7F8); } END_TEST @@ -231,7 +231,7 @@ START_TEST (test_unpack24_be_1) v = uc_unpack_24_be(r); - fail_if(v != 0x123456,"was 0x%x",v); + fail_if(v != 0x123456); } END_TEST @@ -242,7 +242,7 @@ START_TEST (test_unpack24_be_2) v = uc_unpack_24_be(r); - fail_if(v != 0xF8F7F6,"was 0x%x",v); + fail_if(v != 0xF8F7F6); } END_TEST @@ -253,7 +253,7 @@ START_TEST (test_unpack32_le_1) v = uc_unpack_32_le(r); - fail_if(v != 0x78563412,"was 0x%x",v); + fail_if(v != 0x78563412); } END_TEST @@ -264,7 +264,7 @@ START_TEST (test_unpack32_le_2) v = uc_unpack_32_le(r); - fail_if(v != 0xF4F6F7F8,"was 0x%x",v); + fail_if(v != 0xF4F6F7F8); } END_TEST @@ -275,7 +275,7 @@ START_TEST (test_unpack32_be_1) v = uc_unpack_32_be(r); - fail_if(v != 0x12345678,"was 0x%x",v); + fail_if(v != 0x12345678); } END_TEST @@ -286,7 +286,7 @@ START_TEST (test_unpack32_be_2) v = uc_unpack_32_be(r); - fail_if(v != 0xF8F7F6F4,"was 0x%x",v); + fail_if(v != 0xF8F7F6F4); } END_TEST @@ -297,14 +297,14 @@ START_TEST (test_pack64_le_1) uc_pack_64_le(v, r); - fail_if(r[0] != 0x88,"was 0x%x",r[0]); - fail_if(r[1] != 0x77,"was 0x%x",r[1]); - fail_if(r[2] != 0x66,"was 0x%x",r[2]); - fail_if(r[3] != 0x55,"was 0x%x",r[3]); - fail_if(r[4] != 0x44,"was 0x%x",r[4]); - fail_if(r[5] != 0x33,"was 0x%x",r[5]); - fail_if(r[6] != 0x22,"was 0x%x",r[6]); - fail_if(r[7] != 0x11,"was 0x%x",r[7]); + fail_if(r[0] != 0x88); + fail_if(r[1] != 0x77); + fail_if(r[2] != 0x66); + fail_if(r[3] != 0x55); + fail_if(r[4] != 0x44); + fail_if(r[5] != 0x33); + fail_if(r[6] != 0x22); + fail_if(r[7] != 0x11); } END_TEST @@ -315,14 +315,14 @@ START_TEST (test_pack64_le_2) uc_pack_64_le(v, r); - fail_if(r[0] != 0xF8,"was 0x%x",r[0]); - fail_if(r[1] != 0xF9,"was 0x%x",r[1]); - fail_if(r[2] != 0xFA,"was 0x%x",r[2]); - fail_if(r[3] != 0xFB,"was 0x%x",r[3]); - fail_if(r[4] != 0xFC,"was 0x%x",r[4]); - fail_if(r[5] != 0xFD,"was 0x%x",r[5]); - fail_if(r[6] != 0xFE,"was 0x%x",r[6]); - fail_if(r[7] != 0xFF,"was 0x%x",r[7]); + fail_if(r[0] != 0xF8); + fail_if(r[1] != 0xF9); + fail_if(r[2] != 0xFA); + fail_if(r[3] != 0xFB); + fail_if(r[4] != 0xFC); + fail_if(r[5] != 0xFD); + fail_if(r[6] != 0xFE); + fail_if(r[7] != 0xFF); } END_TEST @@ -333,7 +333,7 @@ START_TEST (test_unpack64_le_1) v = uc_unpack_64_le(r); - fail_if(v != 0x8877665544332211ULL,"was 0x%llx",v); + fail_if(v != 0x8877665544332211ULL); } END_TEST @@ -345,7 +345,7 @@ START_TEST (test_unpack64_le_2) v = uc_unpack_64_le(r); - fail_if(v != 0xF8F9FAFBFCFDFEFFULL,"was 0x%llx",v); + fail_if(v != 0xF8F9FAFBFCFDFEFFULL); } END_TEST @@ -356,14 +356,14 @@ START_TEST (test_pack64_be_1) uc_pack_64_be(v, r); - fail_if(r[0] != 0x11,"was 0x%x",r[0]); - fail_if(r[1] != 0x22,"was 0x%x",r[1]); - fail_if(r[2] != 0x33,"was 0x%x",r[2]); - fail_if(r[3] != 0x44,"was 0x%x",r[3]); - fail_if(r[4] != 0x55,"was 0x%x",r[4]); - fail_if(r[5] != 0x66,"was 0x%x",r[5]); - fail_if(r[6] != 0x77,"was 0x%x",r[6]); - fail_if(r[7] != 0x88,"was 0x%x",r[7]); + fail_if(r[0] != 0x11); + fail_if(r[1] != 0x22); + fail_if(r[2] != 0x33); + fail_if(r[3] != 0x44); + fail_if(r[4] != 0x55); + fail_if(r[5] != 0x66); + fail_if(r[6] != 0x77); + fail_if(r[7] != 0x88); } END_TEST @@ -374,14 +374,14 @@ START_TEST (test_pack64_be_2) uc_pack_64_be(v, r); - fail_if(r[0] != 0xFF,"was 0x%x",r[0]); - fail_if(r[1] != 0xFE,"was 0x%x",r[1]); - fail_if(r[2] != 0xFD,"was 0x%x",r[2]); - fail_if(r[3] != 0xFC,"was 0x%x",r[3]); - fail_if(r[4] != 0xFB,"was 0x%x",r[4]); - fail_if(r[5] != 0xFA,"was 0x%x",r[5]); - fail_if(r[6] != 0xF9,"was 0x%x",r[6]); - fail_if(r[7] != 0xF8,"was 0x%x",r[7]); + fail_if(r[0] != 0xFF); + fail_if(r[1] != 0xFE); + fail_if(r[2] != 0xFD); + fail_if(r[3] != 0xFC); + fail_if(r[4] != 0xFB); + fail_if(r[5] != 0xFA); + fail_if(r[6] != 0xF9); + fail_if(r[7] != 0xF8); } END_TEST @@ -392,7 +392,7 @@ START_TEST (test_unpack64_be_1) v = uc_unpack_64_be(r); - fail_if(v != 0x1122334455667788ULL,"was 0x%llx",v); + fail_if(v != 0x1122334455667788ULL); } END_TEST @@ -403,7 +403,7 @@ START_TEST (test_unpack64_be_2) v = uc_unpack_64_be(r); - fail_if(v != 0xFFFEFDFCFBFAF9F8ULL,"was 0x%llx",v); + fail_if(v != 0xFFFEFDFCFBFAF9F8ULL); } END_TEST diff --git a/test/test_ratelimit.c b/test/test_ratelimit.c index 20aa887..6afac0c 100644 --- a/test/test_ratelimit.c +++ b/test/test_ratelimit.c @@ -10,7 +10,7 @@ START_TEST (test_ratelimit_1) uc_ratelimit_init(&r, 30, 2); for (i = 0; i < 30; i++) { - fail_if(!uc_ratelimit_allow(&r, now), "i = %d", i); + fail_if(!uc_ratelimit_allow(&r, now)); } fail_if(uc_ratelimit_allow(&r, now)); } diff --git a/test/test_read_file.c b/test/test_read_file.c index 67f353b..1570b33 100644 --- a/test/test_read_file.c +++ b/test/test_read_file.c @@ -18,8 +18,8 @@ START_TEST (test_read_file_non_existing_file) content = uc_read_file("non existing file 123765", &len, 1000000000); saved_errno = errno; - fail_if(content != NULL); - fail_if(saved_errno == 0); + ck_assert_ptr_null(content); + ck_assert_int_ne(saved_errno, 0); } END_TEST @@ -31,20 +31,20 @@ START_TEST (test_read_file_simple) ssize_t rc; int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664); - fail_if(fd == -1); + ck_assert_int_ne(fd, -1); rc = write(fd, "hello", 5); - fail_if(rc != 5, "rc was %ld", (long)rc); + ck_assert_int_eq(rc, 5); close(fd); content = uc_read_file(filename, &len, 1000000000); unlink(filename); - fail_if(content == NULL); - fail_if(len != 5); - fail_if(strlen(content) != 5); - fail_if(strcmp("hello", content) != 0); + ck_assert_ptr_nonnull(content); + ck_assert_uint_eq(len, 5); + ck_assert_uint_eq(strlen(content), 5); + ck_assert_str_eq("hello", content); free(content); } END_TEST @@ -61,7 +61,7 @@ START_TEST (test_read_file_greater_than_max) fail_if(fd == -1); rc = write(fd, "hello", 5); - fail_if(rc != 5, "rc was %ld", (long)rc); + fail_if(rc != 5); close(fd); @@ -69,8 +69,8 @@ START_TEST (test_read_file_greater_than_max) saved_errno = errno; unlink(filename); - fail_if(content != NULL); - fail_if(saved_errno != EMSGSIZE, "was %d", saved_errno); + ck_assert_ptr_null(content); + ck_assert_int_eq(saved_errno, EMSGSIZE); } END_TEST @@ -87,16 +87,16 @@ START_TEST (test_read_file_boundary) fail_if(fd == -1); rc = write(fd, buf, sizeof buf); - fail_if(rc != sizeof buf, "rc was %ld", (long)rc); + ck_assert_uint_eq(rc, sizeof buf); close(fd); content = uc_read_file(filename, &len, 1000000000); unlink(filename); - fail_if(content == NULL); - fail_if(len != sizeof buf); - fail_if(strcmp("foobar", &content[1022]) != 0); + ck_assert_ptr_nonnull(content); + ck_assert_uint_eq(len, sizeof buf); + ck_assert_str_eq("foobar", &content[1022]); free(content); } END_TEST @@ -107,10 +107,10 @@ START_TEST (test_read_file_devnull) size_t len = 123; content = uc_read_file("/dev/null", &len, 1024); - fail_if(content == NULL); - fail_if(len != 0); + ck_assert_ptr_nonnull(content); + ck_assert_uint_eq(len, 0); free(content); - + } END_TEST @@ -125,14 +125,14 @@ START_TEST (test_read_file_too_big) fail_if(fd == -1); rc = write(fd, "hello", 5); - fail_if(rc != 5, "rc was %ld", (long)rc); + fail_if(rc != 5); close(fd); content = uc_read_file(filename, &len, 4); - fail_if(errno != EMSGSIZE); - fail_if(content != NULL); + ck_assert_int_eq(errno, EMSGSIZE); + ck_assert_ptr_null(content); unlink(filename); } @@ -147,18 +147,18 @@ START_TEST (test_read_file_big) ssize_t rc; int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664); - fail_if(fd == -1); + ck_assert_int_ne(fd, -1); memset(buf, 'a', sizeof buf); rc = write(fd, buf, sizeof buf); - fail_if(rc != sizeof buf, "rc was %ld", (long)rc); + ck_assert_uint_eq(rc, sizeof buf); close(fd); content = uc_read_file(filename, &len, 4096*16); fail_if(content == NULL); - fail_if(len != sizeof buf); - fail_if(memcmp(content, buf, sizeof buf) != 0); + ck_assert_uint_eq(len, sizeof buf); + ck_assert_int_eq(memcmp(content, buf, sizeof buf), 0); free(content); diff --git a/test/test_restart_file.c b/test/test_restart_file.c index 0a2b056..dd6227c 100644 --- a/test/test_restart_file.c +++ b/test/test_restart_file.c @@ -82,7 +82,7 @@ START_TEST (test_restart_counter_garble) ck_assert_int_eq(0, uc_restart_counter_get(&cnt)); rc = uc_restart_counter_init(&cnt, FILE_NAME, 0); - fail_if(rc != UC_RC_OK, "%d", rc); + fail_if(rc != UC_RC_OK); ck_assert_int_eq(1, uc_restart_counter_get(&cnt)); } From 7408c48dff1e7679ec0adb73d370ca66e6407caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sun, 20 Jul 2025 21:44:11 +0200 Subject: [PATCH 40/43] Add uc_bv_find_first_zero --- include/ucore/bitvec.h | 7 ++++++- src/bitvec.c | 18 ++++++++++++++++++ test/test_bitvec.c | 27 +++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/include/ucore/bitvec.h b/include/ucore/bitvec.h index bb5dfe1..a141bdc 100644 --- a/include/ucore/bitvec.h +++ b/include/ucore/bitvec.h @@ -68,11 +68,16 @@ void uc_bv_set_all(struct UCBitVec *v); /** Initialize bits from a array of ints, each array element maps to one bit. * The bits are initialized from the int array so zero maps to zero and non-zero maps to one. * e..g to set the 5 first bits, to 01110: - * int a[] = {0,1,1,1,0}; + * int a[] = {0,1,1,1,0}; * set_bits_from_array(v,a,5); * */ void uc_bv_set_bits_from_array(struct UCBitVec *v,const char *array,size_t array_len); +/** Find the index of the first zero bit in the bitvec. + * @param v The bitvec to search + * @return The index of the first zero bit, or -1 if all bits are set + */ +int uc_bv_find_first_zero(const struct UCBitVec *v); #ifdef __cplusplus } diff --git a/src/bitvec.c b/src/bitvec.c index 6fb5892..d168f84 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -2,6 +2,7 @@ #include #include #include +#include "ucore/utils.h" #include "ucore/bitvec.h" #ifdef __GNUC__ @@ -12,6 +13,8 @@ #define unlikely(expr) (expr) #endif +UC_STATIC_ASSERT(CHAR_BIT % 8 == 0); + static inline int bit_index(int b) { return b / (sizeof(uc_bv_integer) * CHAR_BIT); @@ -88,3 +91,18 @@ void uc_bv_set_all(struct UCBitVec *v) memset(v->vec,0xff,v->vec_len * sizeof(uc_bv_integer)); } +int uc_bv_find_first_zero(const struct UCBitVec *v) +{ + const size_t bits_per_word = sizeof(uc_bv_integer) * CHAR_BIT; + + for (size_t i = 0; i < v->vec_len; i++) { + uc_bv_integer inverted = ~v->vec[i]; + + if (inverted != 0) { + int bit_pos = __builtin_ffsl(inverted) - 1; // ffsl returns 1-based index + return (int)(i * bits_per_word + bit_pos); + } + } + + return -1; +} diff --git a/test/test_bitvec.c b/test/test_bitvec.c index 4676114..a3ec81c 100644 --- a/test/test_bitvec.c +++ b/test/test_bitvec.c @@ -79,6 +79,31 @@ START_TEST (test_bitvec_setall_clearall) uc_bv_free(v); +} +END_TEST +START_TEST (test_bitvec_find_first_zero) +{ + uc_bv_integer buf[8]; + struct UCBitVec v = UC_BV_STATIC_INIT(buf); + uc_bv_set_all(&v); + + int bit = uc_bv_find_first_zero(&v); + ck_assert_int_eq(bit, -1); + + uc_bv_clr_bit(&v, 0); + bit = uc_bv_find_first_zero(&v); + ck_assert_int_eq(bit, 0); + + uc_bv_set_bit(&v, 0); + uc_bv_clr_bit(&v, 63); + bit = uc_bv_find_first_zero(&v); + ck_assert_int_eq(bit, 63); + + uc_bv_set_bit(&v, 63); + uc_bv_clr_bit(&v, sizeof buf * CHAR_BIT - 1); + bit = uc_bv_find_first_zero(&v); + ck_assert_int_eq(bit, sizeof buf * CHAR_BIT - 1); + } END_TEST @@ -91,6 +116,8 @@ Suite *bitvec_suite(void) tcase_add_test(tc, test_bitvec_set_bits_from_array); tcase_add_test(tc, test_bitvec_clearbit); tcase_add_test(tc, test_bitvec_setall_clearall); + tcase_add_test(tc, test_bitvec_find_first_zero); + suite_add_tcase(s, tc); return s; From 251246924dbe51c8a57ae15c43cdf7930ac289f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 21 Jul 2025 19:57:26 +0200 Subject: [PATCH 41/43] Add slot allocator --- .vscode/settings.json | 9 +-- include/ucore/bitvec.h | 2 +- include/ucore/slot_allocator.h | 112 +++++++++++++++++++++++++++++++++ include/ucore/utils.h | 8 +-- src/bitvec.c | 2 +- src/slot_allocator.c | 67 ++++++++++++++++++++ 6 files changed, 188 insertions(+), 12 deletions(-) create mode 100644 include/ucore/slot_allocator.h create mode 100644 src/slot_allocator.c diff --git a/.vscode/settings.json b/.vscode/settings.json index f0ce8de..571ae2e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,14 +1,11 @@ { "files.associations": { - "ringbuf.h": "c", - "seq.h": "c", - "stdint.h": "c", - "stdio.h": "c" + "*.h": "c", }, "C_Cpp.default.includePath": [ "/opt/homebrew/include/", "$(workspaceFolder)/include/", - - ] + ], + "C_Cpp.default.cStandard": "gnu99" } diff --git a/include/ucore/bitvec.h b/include/ucore/bitvec.h index a141bdc..493236e 100644 --- a/include/ucore/bitvec.h +++ b/include/ucore/bitvec.h @@ -27,7 +27,7 @@ struct UCBitVec { * Use as * @code * uc_bv_integer v[10]; - * struct UCBitVec v = BITVEC_STATIC_INIT(v); + * struct UCBitVec v = UC_BV_STATIC_INIT(v); * @endcode */ #define UC_BV_STATIC_INIT(vec_data)\ diff --git a/include/ucore/slot_allocator.h b/include/ucore/slot_allocator.h new file mode 100644 index 0000000..ddc13e1 --- /dev/null +++ b/include/ucore/slot_allocator.h @@ -0,0 +1,112 @@ +#ifndef UC_SLOT_ALLOCATOR_H_ +#define UC_SLOT_ALLOCATOR_H_ + +#include +#include +#include "ucore/bitvec.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** @file + * Fixed size slot memory allocator + * + * UCSlotAlloc is used to allocate fixed slots of memory from a pre-allocated + * piece of memory. + * + * The main use case is to keep allocated memory in a contiguous block for use + * maximum number of objects(slots) is known and relatively small. More than 131072 slots + * is not recommended. + * + * Note that this allocator is not thread safe. + * + * A bitmap is used to track which slots are allocated. + */ + + + +typedef struct UCSlotAlloc UCSlotAlloc; +struct UCSlotAlloc { + const uint32_t slot_size; + const uint32_t num_slots; + struct UCBitVec bitmap; + uint8_t *slots; +}; + + +/** Initialize a UCSlotAlloc with an array as the backing memory to allocate slots from. + * The macro can be used at local scope to allocate memory automatic (stack) storage, + * or at global scope where the backin array will have static storage duration + * + * Use as: + * @code + * UC_SLOT_ALLOC_DEF(my_allocator, sizeof foo, 1024) + * struct foo *foo = uc_slot_alloc(&my_allocator); + * if (foo == NULL) { + * // out of memory + * } else { + * .. use foo + * uc_slot_free(&my_allocator, foo); + * } + * @endcode + * + * @param var_name Variable name for the allocator + * @param v slot_size Memory size allocated for each slot + * @param v num_slots Number of slots to reserve memory for +*/ +#define UC_SLOT_ALLOC_DEF(var_name, slot_size_, num_slots_) \ +struct {\ + uc_bv_integer bitmap[UC_BV_LEN(num_slots_)]; \ + uint8_t memory[num_slots_ * slot_size_] __attribute__((aligned)); \ +} var_name ## _memory = { \ +}; \ +UCSlotAlloc var_name = { \ + .slot_size = slot_size_, \ + .num_slots = num_slots_, \ + .bitmap = UC_BV_STATIC_INIT(var_name ## _memory.bitmap), \ + .slots = var_name ## _memory.memory \ +}; + +/** Similar to UC_SLOT_ALLOC_DEF but allows you to specify the backing memory that must + * be atleast as large as num_slots * slot_size. Note that an array of num_slots * slot_size + * bits is also allocated for the bitmap with this definition + */ +#define UC_SLOT_ALLOC_DEF_EX(var_name, slot_size_, num_slots_, memory) \ +uc_bv_integer var_name ## _bitmap[UC_BV_LEN(num_slots_)] = {}; \ +UCSlotAlloc var_name = { \ + .slot_size = slot_size_, \ + .num_slots = num_slots_, \ + .bitmap = UC_BV_STATIC_INIT(var_name ## _bitmap), \ + .slots = memory \ +}; + +/** Allocate a memory slot + * + * @param sa The allocator to allocate from + * @return A pointer to the memory slot that's sa.slot_size big, or NULL if + * all slots are allocated + */ +void *uc_slot_alloc(UCSlotAlloc *sa); + + +/** Free a memory slot previously returned from uc_slot_alloc() + * + * @param sa The allocator to free from. + * @param slot The memory slot to free. Passing a NULL pointer is undefined behavior + */ +void uc_slot_free(UCSlotAlloc *restrict sa, void *restrict slot); + +/** uc_slot_free() where the slot can be a NULL pointer */ +#define uc_slot_free_safe(sa, slot) \ +do { \ + if (slot != NULL) { \ + uc_slot_free(sa, slot); \ + } \ +} while (0) + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/ucore/utils.h b/include/ucore/utils.h index 614b6bc..1a0b7f7 100644 --- a/include/ucore/utils.h +++ b/include/ucore/utils.h @@ -30,7 +30,7 @@ // int i; // struct bar zap; //}; -// ... +// ... //struct bar *p = ..; //the local p is a pointer to //a 'zap' member inside a struct foo. //give us the struct foo*: @@ -55,7 +55,7 @@ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \ /** * Test if x is a power of 2 - * + * * @param x value, must be an unsigned type * @return 1 if x is a power of 20, 0 if it is not */ @@ -90,7 +90,7 @@ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \ * * @param x numerator, must be positive * @param y denominator - * @return x/y rounded up + * @return x/y rounded up */ #define UC_DIV_ROUND_UP(x, y) (((x) + ((y) - 1))/(y)) @@ -103,7 +103,7 @@ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \ * @param y denominator * @return x rounded up to nearest multiple of y */ -#define UC_ROUND_UP(x, y) (UC_DIV_ROUND_UP((x), (y)) * (y)) +#define UC_ROUND_UP(x, y) (UC_DIV_ROUND_UP((x), (y)) * (y)) /** * Round x down to nearest multiple of y diff --git a/src/bitvec.c b/src/bitvec.c index d168f84..9644f58 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -44,7 +44,7 @@ struct UCBitVec *uc_bv_new(size_t nbits) void uc_bv_free(struct UCBitVec *v) { - if (v) { + if (likely(v != NULL)) { free(v); } } diff --git a/src/slot_allocator.c b/src/slot_allocator.c new file mode 100644 index 0000000..cd5fd0a --- /dev/null +++ b/src/slot_allocator.c @@ -0,0 +1,67 @@ + +#include +#include +#include +#include "ucore/bitvec.h" +#include "ucore/slot_allocator.h" + +void *uc_slot_alloc(UCSlotAlloc *sa) +{ + int free_slot = uc_bv_find_first_zero(&sa->bitmap); + if (free_slot < 0) { + return NULL; + } else if ((size_t)free_slot >= sa->num_slots) { // bit vector may have more bits than slots + return NULL; + } + + uc_bv_set_bit(&sa->bitmap, free_slot); + + return sa->slots + free_slot * sa->slot_size; +} + +void uc_slot_free(UCSlotAlloc *restrict sa, void *restrict slot) +{ + assert((uint8_t *)slot >= sa->slots); + int slot_index = ((uint8_t *)slot - sa->slots) / sa->slot_size; + assert((size_t)slot_index < sa->num_slots); + uc_bv_clr_bit(&sa->bitmap, slot_index); +} + +int main() +{ + + UC_SLOT_ALLOC_DEF(sa, 24, 1) + + void *p1 = uc_slot_alloc(&sa); + printf("%p\n", &sa_memory.memory[0]); + printf("%p\n", p1); + + void *p2 = uc_slot_alloc(&sa); + printf("%p\n", p2); + uc_slot_free(&sa, p1); + + p2 = uc_slot_alloc(&sa); + printf("%p\n", p2); + + printf("__malloc__\n"); + void *v = malloc(24 * (1<<16)); + UC_SLOT_ALLOC_DEF_EX(sa2, 24, (1<<16), v) + char *v2 = NULL; + for (int i = 0; i < 1<<16; i++) { + char *c = uc_slot_alloc(&sa2); + if (c == NULL) { + printf("uc_slot_alloc failed at %d\n", i); + break; + } + *c = i; + if (i == 0) { + v2 = c; + } + } + for (int i = (1<<16) -1 ; i >= 0; i--) { + uc_slot_free(&sa2, v2 + 24*i); + } + free(v); + return 0; +} + From b2d56f8094717640487bed8f8b0b05da4922ba76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 21 Jul 2025 20:30:33 +0200 Subject: [PATCH 42/43] Macro safe slot_allocator.h --- include/ucore/slot_allocator.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/ucore/slot_allocator.h b/include/ucore/slot_allocator.h index ddc13e1..d0cdc7f 100644 --- a/include/ucore/slot_allocator.h +++ b/include/ucore/slot_allocator.h @@ -56,13 +56,13 @@ struct UCSlotAlloc { */ #define UC_SLOT_ALLOC_DEF(var_name, slot_size_, num_slots_) \ struct {\ - uc_bv_integer bitmap[UC_BV_LEN(num_slots_)]; \ - uint8_t memory[num_slots_ * slot_size_] __attribute__((aligned)); \ + uc_bv_integer bitmap[UC_BV_LEN((num_slots_))]; \ + uint8_t memory[(num_slots_) * (slot_size_)] __attribute__((aligned)); \ } var_name ## _memory = { \ }; \ UCSlotAlloc var_name = { \ - .slot_size = slot_size_, \ - .num_slots = num_slots_, \ + .slot_size = (slot_size_), \ + .num_slots = (num_slots_), \ .bitmap = UC_BV_STATIC_INIT(var_name ## _memory.bitmap), \ .slots = var_name ## _memory.memory \ }; @@ -72,12 +72,12 @@ UCSlotAlloc var_name = { \ * bits is also allocated for the bitmap with this definition */ #define UC_SLOT_ALLOC_DEF_EX(var_name, slot_size_, num_slots_, memory) \ -uc_bv_integer var_name ## _bitmap[UC_BV_LEN(num_slots_)] = {}; \ +uc_bv_integer var_name ## _bitmap[UC_BV_LEN((num_slots_))] = {}; \ UCSlotAlloc var_name = { \ - .slot_size = slot_size_, \ - .num_slots = num_slots_, \ + .slot_size = (slot_size_), \ + .num_slots = (num_slots_), \ .bitmap = UC_BV_STATIC_INIT(var_name ## _bitmap), \ - .slots = memory \ + .slots = (memory) \ }; /** Allocate a memory slot @@ -99,8 +99,8 @@ void uc_slot_free(UCSlotAlloc *restrict sa, void *restrict slot); /** uc_slot_free() where the slot can be a NULL pointer */ #define uc_slot_free_safe(sa, slot) \ do { \ - if (slot != NULL) { \ - uc_slot_free(sa, slot); \ + if ((slot) != NULL) { \ + uc_slot_free((sa), (slot)); \ } \ } while (0) From 82e2337ecc9c1746cfffbf95dd6add9da16ad2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 4 Oct 2025 21:35:39 +0200 Subject: [PATCH 43/43] Substitube build_type --- CMakeLists.txt | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd1977e..f770602 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,7 @@ cmake_minimum_required(VERSION 3.12) project(libucore C) execute_process(COMMAND git -C ${CMAKE_SOURCE_DIR} describe --abbrev=5 --dirty --always OUTPUT_VARIABLE version_revision WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE) -execute_process(COMMAND hostname OUTPUT_VARIABLE build_host OUTPUT_STRIP_TRAILING_WHITESPACE) - +cmake_host_system_information(RESULT build_host QUERY HOSTNAME) set(libucore_VERSION_MAJOR 1) set(libucore_VERSION_MINOR 0) set(libucore_VERSION_PATCH 0) @@ -11,28 +10,32 @@ set(libucore_VERSION ${libucore_VERSION_MAJOR}.${libucore_VERSION_MINOR}.${libuc set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD 11) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wundef -Wcast-qual -Wshadow -Wcast-align -pipe -Wno-unused-parameter -Werror=implicit-function-declaration -Winit-self") add_definitions(-D_FILE_OFFSET_BITS=64) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -O2") set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) option(CODE_COVERAGE "build with code coverage intrumentation" OFF) -if (CODE_COVERAGE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") - add_definitions(-DCOVERAGE) -endif() - -option(BUILD_SANITIZE "build with address sanitizer" OFF) -if (BUILD_SANITIZE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") -endif() if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) # Set the property for multi-config generators as well, if applicable set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel) endif() +set(build_type ${CMAKE_BUILD_TYPE}) +if (CODE_COVERAGE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") + add_definitions(-DCOVERAGE) + set(build_type "${build_type}-coverage") +endif() + +option(BUILD_SANITIZE "build with address sanitizer" OFF) +if (BUILD_SANITIZE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") + set(build_type "${build_type}-sanitize") +endif() + include_directories(include)