X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fecoli_node_cmd.c;h=743f3b985515ce8b4a5989ca034f9e78bf63975a;hb=f1ce472396323a1c74b552bdd327febbe3eae121;hp=d1d2c7d2eb992356325927fc319b30459554bea6;hpb=575fd5b430d5f1557d9a6bdb19c037efaf023759;p=protos%2Flibecoli.git diff --git a/lib/ecoli_node_cmd.c b/lib/ecoli_node_cmd.c index d1d2c7d..743f3b9 100644 --- a/lib/ecoli_node_cmd.c +++ b/lib/ecoli_node_cmd.c @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -50,6 +53,8 @@ #include #include +EC_LOG_TYPE_REGISTER(node_cmd); + struct ec_node_cmd { struct ec_node gen; char *cmd_str; /* the command string. */ @@ -80,7 +85,6 @@ ec_node_cmd_eval_var(void **result, void *userctx, for (i = 0; i < node->len; i++) { id = ec_node_id(node->table[i]); - printf("i=%d id=%s\n", i, id); if (id == NULL) continue; if (strcmp(str, id)) @@ -94,12 +98,11 @@ ec_node_cmd_eval_var(void **result, void *userctx, /* ...or create a string node */ if (eval == NULL) { - eval = ec_node_str(NULL, str); + eval = ec_node_str(EC_NO_ID, str); if (eval == NULL) return -ENOMEM; } - printf("eval var %s %p\n", str, eval); *result = eval; return 0; @@ -122,7 +125,8 @@ ec_node_cmd_eval_post_op(void **result, void *userctx, void *operand, const struct ec_parsed *operator) { const struct ec_strvec *vec; - struct ec_node *eval = operand;; + struct ec_node *in = operand;; + struct ec_node *out = NULL;; (void)userctx; @@ -131,13 +135,16 @@ ec_node_cmd_eval_post_op(void **result, void *userctx, void *operand, if (ec_strvec_len(vec) != 1) return -EINVAL; - if (!strcmp(ec_strvec_val(vec, 0), "*")) - eval = NULL; //XXX - else + if (!strcmp(ec_strvec_val(vec, 0), "*")) { + out = ec_node_many(EC_NO_ID, + ec_node_clone(in), 0, 0); + if (out == NULL) + return -EINVAL; + ec_node_free(in); + *result = out; + } else { return -EINVAL; - - printf("eval post_op %p\n", eval); - *result = eval; + } return 0; } @@ -154,27 +161,66 @@ ec_node_cmd_eval_bin_op(void **result, void *userctx, void *operand1, (void)userctx; - printf("eval bin_op %p %p\n", in1, in2); - /* get parsed string vector, it should contain only one str */ vec = ec_parsed_strvec(operator); - if (ec_strvec_len(vec) != 1) + if (ec_strvec_len(vec) > 1) return -EINVAL; - if (!strcmp(ec_strvec_val(vec, 0), "|")) { - out = EC_NODE_OR(NULL, ec_node_clone(in1), ec_node_clone(in2)); - if (out == NULL) - return -EINVAL; - ec_node_free(in1); - ec_node_free(in2); - *result = out; + if (ec_strvec_len(vec) == 0) { + if (!strcmp(in1->type->name, "seq")) { + if (ec_node_seq_add(in1, ec_node_clone(in2)) < 0) + return -EINVAL; + ec_node_free(in2); + *result = in1; + } else { + out = EC_NODE_SEQ(EC_NO_ID, ec_node_clone(in1), + ec_node_clone(in2)); + if (out == NULL) + return -EINVAL; + ec_node_free(in1); + ec_node_free(in2); + *result = out; + } + } else if (!strcmp(ec_strvec_val(vec, 0), "|")) { + if (!strcmp(in2->type->name, "or")) { + if (ec_node_or_add(in2, ec_node_clone(in1)) < 0) + return -EINVAL; + ec_node_free(in1); + *result = in2; + } else if (!strcmp(in1->type->name, "or")) { + if (ec_node_or_add(in1, ec_node_clone(in2)) < 0) + return -EINVAL; + ec_node_free(in2); + *result = in1; + } else { + out = EC_NODE_OR(EC_NO_ID, ec_node_clone(in1), + ec_node_clone(in2)); + if (out == NULL) + return -EINVAL; + ec_node_free(in1); + ec_node_free(in2); + *result = out; + } } else if (!strcmp(ec_strvec_val(vec, 0), ",")) { - out = EC_NODE_SUBSET(NULL, ec_node_clone(in1), ec_node_clone(in2)); - if (out == NULL) - return -EINVAL; - ec_node_free(in1); - ec_node_free(in2); - *result = out; + if (!strcmp(in2->type->name, "subset")) { + if (ec_node_subset_add(in2, ec_node_clone(in1)) < 0) + return -EINVAL; + ec_node_free(in1); + *result = in2; + } else if (!strcmp(in1->type->name, "subset")) { + if (ec_node_subset_add(in1, ec_node_clone(in2)) < 0) + return -EINVAL; + ec_node_free(in2); + *result = in1; + } else { + out = EC_NODE_SUBSET(EC_NO_ID, ec_node_clone(in1), + ec_node_clone(in2)); + if (out == NULL) + return -EINVAL; + ec_node_free(in1); + ec_node_free(in2); + *result = out; + } } else { return -EINVAL; } @@ -201,7 +247,7 @@ ec_node_cmd_eval_parenthesis(void **result, void *userctx, return -EINVAL; if (!strcmp(ec_strvec_val(vec, 0), "[")) { - out = ec_node_option(NULL, ec_node_clone(in)); + out = ec_node_option(EC_NO_ID, ec_node_clone(in)); if (out == NULL) return -EINVAL; ec_node_free(in); @@ -211,7 +257,6 @@ ec_node_cmd_eval_parenthesis(void **result, void *userctx, return -EINVAL; } - printf("eval paren\n"); *result = out; return 0; @@ -233,77 +278,55 @@ static const struct ec_node_expr_eval_ops test_ops = { .eval_free = ec_node_cmd_eval_free, }; -static struct ec_parsed *ec_node_cmd_parse(const struct ec_node *gen_node, - const struct ec_strvec *strvec) -{ - struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; - - return ec_node_parse_strvec(node->cmd, strvec); -} - -static struct ec_completed *ec_node_cmd_complete(const struct ec_node *gen_node, - const struct ec_strvec *strvec) -{ - struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; - - return ec_node_complete_strvec(node->cmd, strvec); -} - -static void ec_node_cmd_free_priv(struct ec_node *gen_node) -{ - struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; - unsigned int i; - - ec_free(node->cmd_str); - ec_node_free(node->cmd); - ec_node_free(node->expr); - ec_node_free(node->lex); - for (i = 0; i < node->len; i++) - ec_node_free(node->table[i]); - ec_free(node->table); -} - -static int ec_node_cmd_build(struct ec_node *gen_node) +static int ec_node_cmd_build(struct ec_node_cmd *node) { struct ec_node *expr = NULL, *lex = NULL, *cmd = NULL; - struct ec_parsed *p, *child; - struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; + struct ec_parsed *p = NULL; void *result; int ret; + ec_node_free(node->expr); + node->expr = NULL; + ec_node_free(node->lex); + node->lex = NULL; + ec_node_free(node->cmd); + node->cmd = NULL; + /* build the expression parser */ ret = -ENOMEM; - expr = ec_node_new("expr", "expr"); + expr = ec_node("expr", "expr"); if (expr == NULL) goto fail; - ret = ec_node_expr_set_val_node(expr, ec_node_re(NULL, "[a-zA-Z0-9]+")); + ret = ec_node_expr_set_val_node(expr, ec_node_re(EC_NO_ID, "[a-zA-Z0-9]+")); if (ret < 0) goto fail; - ret = ec_node_expr_add_bin_op(expr, ec_node_str(NULL, ",")); + ret = ec_node_expr_add_bin_op(expr, ec_node_str(EC_NO_ID, ",")); if (ret < 0) goto fail; - ret = ec_node_expr_add_bin_op(expr, ec_node_str(NULL, "|")); + ret = ec_node_expr_add_bin_op(expr, ec_node_str(EC_NO_ID, "|")); if (ret < 0) goto fail; - ret = ec_node_expr_add_post_op(expr, ec_node_str(NULL, "+")); + ret = ec_node_expr_add_bin_op(expr, ec_node("empty", EC_NO_ID)); if (ret < 0) goto fail; - ret = ec_node_expr_add_post_op(expr, ec_node_str(NULL, "*")); + ret = ec_node_expr_add_post_op(expr, ec_node_str(EC_NO_ID, "+")); if (ret < 0) goto fail; - ret = ec_node_expr_add_parenthesis(expr, ec_node_str(NULL, "["), - ec_node_str(NULL, "]")); + ret = ec_node_expr_add_post_op(expr, ec_node_str(EC_NO_ID, "*")); if (ret < 0) goto fail; - ec_node_expr_add_parenthesis(expr, ec_node_str(NULL, "("), - ec_node_str(NULL, ")")); + ret = ec_node_expr_add_parenthesis(expr, ec_node_str(EC_NO_ID, "["), + ec_node_str(EC_NO_ID, "]")); + if (ret < 0) + goto fail; + ec_node_expr_add_parenthesis(expr, ec_node_str(EC_NO_ID, "("), + ec_node_str(EC_NO_ID, ")")); if (ret < 0) goto fail; - /* prepend a lexer and a "many" to the expression node */ + /* prepend a lexer to the expression node */ ret = -ENOMEM; - lex = ec_node_re_lex(NULL, - ec_node_many(NULL, ec_node_clone(expr), 1, 0)); + lex = ec_node_re_lex(EC_NO_ID, ec_node_clone(expr)); if (lex == NULL) goto fail; @@ -332,47 +355,71 @@ static int ec_node_cmd_build(struct ec_node *gen_node) ret = -EINVAL; if (!ec_parsed_matches(p)) goto fail; - if (TAILQ_EMPTY(&p->children)) - goto fail; - if (TAILQ_EMPTY(&TAILQ_FIRST(&p->children)->children)) + if (!ec_parsed_has_child(p)) goto fail; - ret = -ENOMEM; - cmd = ec_node_new("seq", NULL); - if (cmd == NULL) + ret = ec_node_expr_eval(&result, expr, ec_parsed_get_first_child(p), + &test_ops, node); + if (ret < 0) goto fail; - TAILQ_FOREACH(child, &TAILQ_FIRST(&p->children)->children, next) { - ret = ec_node_expr_eval(&result, expr, child, - &test_ops, node); - if (ret < 0) - goto fail; - ret = ec_node_seq_add(cmd, result); - if (ret < 0) - goto fail; - } ec_parsed_free(p); - ec_node_dump(stdout, cmd); + p = NULL; - ec_node_free(node->expr); node->expr = expr; - ec_node_free(node->lex); node->lex = lex; - ec_node_free(node->cmd); - node->cmd = cmd; + node->cmd = result; return 0; fail: + ec_parsed_free(p); ec_node_free(expr); ec_node_free(lex); ec_node_free(cmd); return ret; } +static int +ec_node_cmd_parse(const struct ec_node *gen_node, struct ec_parsed *state, + const struct ec_strvec *strvec) +{ + struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; + + if (node->cmd == NULL) + return -ENOENT; + return ec_node_parse_child(node->cmd, state, strvec); +} + +static int +ec_node_cmd_complete(const struct ec_node *gen_node, + struct ec_completed *completed, + const struct ec_strvec *strvec) +{ + struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; + + if (node->cmd == NULL) + return -ENOENT; + return ec_node_complete_child(node->cmd, completed, strvec); +} + +static void ec_node_cmd_free_priv(struct ec_node *gen_node) +{ + struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; + unsigned int i; + + ec_free(node->cmd_str); + ec_node_free(node->cmd); + ec_node_free(node->expr); + ec_node_free(node->lex); + for (i = 0; i < node->len; i++) + ec_node_free(node->table[i]); + ec_free(node->table); +} + + static struct ec_node_type ec_node_cmd_type = { .name = "cmd", - .build = ec_node_cmd_build, .parse = ec_node_cmd_parse, .complete = ec_node_cmd_complete, .size = sizeof(struct ec_node_cmd), @@ -385,52 +432,41 @@ int ec_node_cmd_add_child(struct ec_node *gen_node, struct ec_node *child) { struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; struct ec_node **table; - - // XXX check node type + int ret; assert(node != NULL); - printf("add child %s\n", child->id); - if (child == NULL) - return -EINVAL; - - gen_node->flags &= ~EC_NODE_F_BUILT; - - table = ec_realloc(node->table, (node->len + 1) * sizeof(*node->table)); - if (table == NULL) { - ec_node_free(child); - return -ENOMEM; + if (child == NULL) { + errno = EINVAL; + goto fail; } - node->table = table; - table[node->len] = child; - node->len++; + if (ec_node_check_type(gen_node, &ec_node_cmd_type) < 0) + goto fail; - child->parent = gen_node; - TAILQ_INSERT_TAIL(&gen_node->children, child, next); // XXX really needed? + if (node->cmd == NULL) { + ret = ec_node_cmd_build(node); + if (ret < 0) + return ret; + } - return 0; -} + table = ec_realloc(node->table, (node->len + 1) * sizeof(*node->table)); + if (table == NULL) + goto fail; -struct ec_node *ec_node_cmd(const char *id, const char *cmd_str) -{ - struct ec_node *gen_node = NULL; - struct ec_node_cmd *node = NULL; + node->table = table; - gen_node = __ec_node_new(&ec_node_cmd_type, id); - if (gen_node == NULL) + if (ec_node_add_child(gen_node, child) < 0) goto fail; - node = (struct ec_node_cmd *)gen_node; - node->cmd_str = ec_strdup(cmd_str); - if (node->cmd_str == NULL) - goto fail; + table[node->len] = child; + node->len++; - return gen_node; + return 0; fail: - ec_node_free(gen_node); - return NULL; + ec_node_free(child); + return -1; } struct ec_node *__ec_node_cmd(const char *id, const char *cmd, ...) @@ -441,12 +477,18 @@ struct ec_node *__ec_node_cmd(const char *id, const char *cmd, ...) va_list ap; int fail = 0; - va_start(ap, cmd); + gen_node = __ec_node(&ec_node_cmd_type, id); + if (gen_node == NULL) + fail = 1; - gen_node = ec_node_cmd(id, cmd); - node = (struct ec_node_cmd *)gen_node; - if (node == NULL) - fail = 1;; + if (fail == 0) { + node = (struct ec_node_cmd *)gen_node; + node->cmd_str = ec_strdup(cmd); + if (node->cmd_str == NULL) + fail = 1; + } + + va_start(ap, cmd); for (child = va_arg(ap, struct ec_node *); child != EC_NODE_ENDLIST; @@ -460,43 +502,91 @@ struct ec_node *__ec_node_cmd(const char *id, const char *cmd, ...) } } + va_end(ap); + if (fail == 1) goto fail; - va_end(ap); + if (ec_node_cmd_build(node) < 0) + goto fail; + return gen_node; fail: ec_node_free(gen_node); /* will also free children */ - va_end(ap); return NULL; } +struct ec_node *ec_node_cmd(const char *id, const char *cmd_str) +{ + return __ec_node_cmd(id, cmd_str, EC_NODE_ENDLIST); +} + +/* LCOV_EXCL_START */ static int ec_node_cmd_testcase(void) { struct ec_node *node; int ret = 0; - node = EC_NODE_CMD(NULL, - "command [option] (subset1, subset2) x | y", + node = EC_NODE_CMD(EC_NO_ID, + "command [option] (subset1, subset2, subset3, subset4) x|y z*", ec_node_int("x", 0, 10, 10), ec_node_int("y", 20, 30, 10) ); if (node == NULL) { - ec_log(EC_LOG_ERR, "cannot create node\n"); + EC_LOG(EC_LOG_ERR, "cannot create node\n"); return -1; } ret |= EC_TEST_CHECK_PARSE(node, 2, "command", "1"); + ret |= EC_TEST_CHECK_PARSE(node, 3, "command", "subset1", "1"); + ret |= EC_TEST_CHECK_PARSE(node, 4, "command", "subset3", "subset2", + "1"); + ret |= EC_TEST_CHECK_PARSE(node, 5, "command", "subset2", "subset3", + "subset1", "1"); + ret |= EC_TEST_CHECK_PARSE(node, 6, "command", "subset3", "subset1", + "subset4", "subset2", "4"); ret |= EC_TEST_CHECK_PARSE(node, 2, "command", "23"); ret |= EC_TEST_CHECK_PARSE(node, 3, "command", "option", "23"); + ret |= EC_TEST_CHECK_PARSE(node, 5, "command", "option", "23", + "z", "z"); ret |= EC_TEST_CHECK_PARSE(node, -1, "command", "15"); ret |= EC_TEST_CHECK_PARSE(node, -1, "foo"); ec_node_free(node); - // XXX completion + node = EC_NODE_CMD(EC_NO_ID, "good morning [count] bob|bobby|michael", + ec_node_int("count", 0, 10, 10)); + if (node == NULL) { + EC_LOG(EC_LOG_ERR, "cannot create node\n"); + return -1; + } + ret |= EC_TEST_CHECK_PARSE(node, 4, "good", "morning", "1", "bob"); + + ret |= EC_TEST_CHECK_COMPLETE(node, + "", EC_NODE_ENDLIST, + "good", EC_NODE_ENDLIST); + ret |= EC_TEST_CHECK_COMPLETE(node, + "g", EC_NODE_ENDLIST, + "good", EC_NODE_ENDLIST); + ret |= EC_TEST_CHECK_COMPLETE(node, + "good", "morning", "", EC_NODE_ENDLIST, + "bob", "bobby", "michael", EC_NODE_ENDLIST); + + ec_node_free(node); + + node = EC_NODE_CMD(EC_NO_ID, "[foo [bar]]"); + if (node == NULL) { + EC_LOG(EC_LOG_ERR, "cannot create node\n"); + return -1; + } + ret |= EC_TEST_CHECK_PARSE(node, 0); + ret |= EC_TEST_CHECK_PARSE(node, 1, "foo"); + ret |= EC_TEST_CHECK_PARSE(node, 2, "foo", "bar"); + ret |= EC_TEST_CHECK_PARSE(node, 0, "x"); + ec_node_free(node); return ret; } +/* LCOV_EXCL_STOP */ static struct ec_test ec_node_cmd_test = { .name = "node_cmd",