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] 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);