]> git.droids-corp.org - protos/libecoli.git/commitdiff
save
authorOlivier Matz <zer0@droids-corp.org>
Wed, 21 Dec 2016 19:10:49 +0000 (20:10 +0100)
committerOlivier Matz <zer0@droids-corp.org>
Wed, 21 Dec 2016 19:10:49 +0000 (20:10 +0100)
15 files changed:
lib/ecoli_tk.h
lib/ecoli_tk_expr.c
lib/ecoli_tk_expr.h
lib/ecoli_tk_int.c
lib/ecoli_tk_int.h
lib/ecoli_tk_many.c
lib/ecoli_tk_option.c
lib/ecoli_tk_or.c
lib/ecoli_tk_or.h
lib/ecoli_tk_seq.c
lib/ecoli_tk_seq.h
lib/ecoli_tk_shlex.c
lib/ecoli_tk_str.c
lib/ecoli_tk_str.h
lib/main-readline.c

index b417a0380d1dc2758f750cb55d241f20012b14cd..b3f43bcd633cb84289b74e94ab550ec6f2c6075e 100644 (file)
@@ -64,6 +64,8 @@ struct ec_tk {
        /* XXX ensure parent and child are properly set in all nodes */
        struct ec_tk *parent;
        unsigned int refcnt;
+#define EC_TK_F_INITIALIZED 0x0001
+       unsigned int flags;
 
        TAILQ_ENTRY(ec_tk) next;
        struct ec_tk_list children;
index 5625727d02755e4ce69b226468c06e54eab6c6c4..2117d36577d9be5ac0f407ebe2e44c81ab13cc7f 100644 (file)
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <assert.h>
 #include <stdarg.h>
+#include <limits.h>
 #include <errno.h>
 
 #include <ecoli_malloc.h>
 #include <ecoli_strvec.h>
 #include <ecoli_tk.h>
 #include <ecoli_tk_str.h>
+#include <ecoli_tk_int.h>
 #include <ecoli_tk_seq.h>
 #include <ecoli_tk_many.h>
+#include <ecoli_tk_or.h>
 #include <ecoli_tk_expr.h>
 
 struct ec_tk_expr {
@@ -49,10 +52,16 @@ struct ec_tk_expr {
 
        struct ec_tk **bin_ops;
        unsigned int bin_ops_len;
+
        struct ec_tk **pre_ops;
        unsigned int pre_ops_len;
+
        struct ec_tk **post_ops;
        unsigned int post_ops_len;
+
+       struct ec_tk **open_ops;
+       struct ec_tk **close_ops;
+       unsigned int paren_len;
 };
 
 static struct ec_parsed_tk *ec_tk_expr_parse(const struct ec_tk *gen_tk,
@@ -119,9 +128,10 @@ int ec_tk_expr_add_bin_op(struct ec_tk *gen_tk, struct ec_tk *op)
 
        // XXX check tk type
 
-       /* XXX use assert or check like this ? */
        if (tk == NULL || op == NULL)
                return -EINVAL;
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
 
        bin_ops = ec_realloc(tk->bin_ops,
                (tk->bin_ops_len + 1) * sizeof(*tk->bin_ops));
@@ -142,9 +152,10 @@ int ec_tk_expr_add_pre_op(struct ec_tk *gen_tk, struct ec_tk *op)
 
        // XXX check tk type
 
-       /* XXX use assert or check like this ? */
        if (tk == NULL || op == NULL)
                return -EINVAL;
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
 
        pre_ops = ec_realloc(tk->pre_ops,
                (tk->pre_ops_len + 1) * sizeof(*tk->pre_ops));
@@ -165,9 +176,10 @@ int ec_tk_expr_add_post_op(struct ec_tk *gen_tk, struct ec_tk *op)
 
        // XXX check tk type
 
-       /* XXX use assert or check like this ? */
        if (tk == NULL || op == NULL)
                return -EINVAL;
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
 
        post_ops = ec_realloc(tk->post_ops,
                (tk->post_ops_len + 1) * sizeof(*tk->post_ops));
@@ -181,112 +193,199 @@ int ec_tk_expr_add_post_op(struct ec_tk *gen_tk, struct ec_tk *op)
        return 0;
 }
 
+int ec_tk_expr_add_parenthesis(struct ec_tk *gen_tk,
+       struct ec_tk *open, struct ec_tk *close)
+{
+       struct ec_tk_expr *tk = (struct ec_tk_expr *)gen_tk;
+       struct ec_tk **open_ops, **close_ops;
+
+       // XXX check tk type
+
+       if (tk == NULL || open == NULL || close == NULL)
+               return -EINVAL;
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
+
+       open_ops = ec_realloc(tk->open_ops,
+               (tk->paren_len + 1) * sizeof(*tk->open_ops));
+       if (open_ops == NULL)
+               return -1;
+       close_ops = ec_realloc(tk->close_ops,
+               (tk->paren_len + 1) * sizeof(*tk->close_ops));
+       if (close_ops == NULL)
+               return -1;
+
+       tk->open_ops = open_ops;
+       tk->close_ops = close_ops;
+       open_ops[tk->paren_len] = open;
+       close_ops[tk->paren_len] = close;
+       tk->paren_len++;
+
+       return 0;
+}
+
 int ec_tk_expr_start(struct ec_tk *gen_tk)
 {
        struct ec_tk_expr *tk = (struct ec_tk_expr *)gen_tk;
+       struct ec_tk *term = NULL, *prev = NULL, *expr = NULL,
+               *val = NULL, *pre_op = NULL, *post_op = NULL,
+               *post = NULL, *final = NULL, *next = NULL;
+       unsigned int i;
 
        if (tk->val_tk == NULL)
                return -EINVAL;
-       if (tk->bin_ops_len == 0 || tk->pre_ops_len == 0 ||
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
+       if (tk->bin_ops_len == 0 && tk->pre_ops_len == 0 &&
                        tk->post_ops_len == 0)
                return -EINVAL;
 
-       return 0;
-}
+       /* create the object, we will initialize it later: this is
+        * needed because we have a circular dependency */
+       expr = ec_tk_seq_new("expr");
 
-struct ec_tk *ec_tk_expr(const char *id, struct ec_tk *val_tk,
-       const char *bin_ops)
-{
-       struct ec_tk_expr *tk = NULL;
-       struct ec_tk *gen_tk = NULL, *child = NULL, *sub_expr = NULL;
-       char *op = NULL;
+       val = ec_tk_int("val", 0, UCHAR_MAX, 0);
 
-       gen_tk = ec_tk_expr_new(id);
-       if (gen_tk == NULL)
+       /* prefix unary operators */
+       pre_op = ec_tk_or_new("pre-op");
+       for (i = 0; i < tk->pre_ops_len; i++) {
+               if (ec_tk_or_add(pre_op, ec_tk_clone(tk->pre_ops[i])) < 0)
+                       goto fail;
+       }
+       if (ec_tk_or_start(pre_op) < 0)
                goto fail;
-       tk = (struct ec_tk_expr *)gen_tk;
 
-       if (bin_ops == NULL || bin_ops[0] == '\0') {
-               child = val_tk;
-       } else {
-               /* recursively create an expr tk without the first operator */
-               sub_expr = ec_tk_expr(NULL,
-                       ec_tk_clone(val_tk),
-                       &bin_ops[1]);
-               if (sub_expr == NULL)
+       /* suffix unary operators */
+       post_op = ec_tk_or_new("post-op");
+       for (i = 0; i < tk->post_ops_len; i++) {
+               if (ec_tk_or_add(post_op, ec_tk_clone(tk->post_ops[i])) < 0)
                        goto fail;
+       }
+       if (ec_tk_or_start(post_op) < 0)
+               goto fail;
 
-               op = ec_strdup(bin_ops);
-               if (op == NULL)
+       term = ec_tk_or_new("term");
+       if (ec_tk_or_add(term, ec_tk_clone(val)) < 0)
+               goto fail;
+       if (ec_tk_or_add(term,
+               ec_tk_seq(NULL,
+                       ec_tk_clone(pre_op),
+                       ec_tk_clone(expr),
+                       EC_TK_ENDLIST)) < 0)
+               goto fail;
+       for (i = 0; i < tk->paren_len; i++) {
+               if (ec_tk_or_add(term, ec_tk_seq(NULL,
+                                       ec_tk_clone(tk->open_ops[i]),
+                                       ec_tk_clone(expr),
+                                       ec_tk_clone(tk->close_ops[i]),
+                                       EC_TK_ENDLIST)) < 0)
                        goto fail;
-               op[1] = '\0';
+       }
 
-               /* we match:
-                *   <subexpr> (<op> <subexpr>)*
-                */
-               child = ec_tk_seq_new_list(NULL,
-                       ec_tk_clone(sub_expr),
+       prev = term;
+       term = NULL;
+       for (i = 0; i < tk->bin_ops_len; i++) {
+               next = ec_tk_seq("next",
+                       ec_tk_clone(prev),
                        ec_tk_many_new(NULL,
-                               ec_tk_seq_new_list(NULL,
-                                       ec_tk_str_new(NULL, op),
-                                       ec_tk_clone(sub_expr),
+                               ec_tk_seq(NULL,
+                                       ec_tk_clone(tk->bin_ops[i]),
+                                       ec_tk_clone(prev),
                                        EC_TK_ENDLIST
                                ),
                                0, 0
                        ),
                        EC_TK_ENDLIST
                );
-               ec_free(op);
-               op = NULL;
-
-               /* remove initial reference */
-               ec_tk_free(sub_expr);
+               prev = next;
+       }
 
-               if (child == NULL)
-                       goto fail;
+       final = ec_tk_seq("final",
+               ec_tk_clone(next),
+               ec_tk_many_new(NULL, ec_tk_clone(post_op), 0, 0),
+               EC_TK_ENDLIST
+       );
 
-               ec_tk_free(val_tk);
-       }
+       tk->child = final;
 
-       tk->child = child;
+       gen_tk->flags |= EC_TK_F_INITIALIZED;
 
-       return &tk->gen;
+       return 0;
 
 fail:
-       ec_free(op);
-       ec_tk_free(child);
-       ec_tk_free(val_tk);
-       ec_tk_free(gen_tk);
-       return NULL;
+       ec_tk_free(val);
+       ec_tk_free(pre_op);
+       ec_tk_free(post_op);
+       ec_tk_free(term);
+       ec_tk_free(post);
+       return -1;
 }
 
 static int ec_tk_expr_testcase(void)
 {
-       struct ec_tk *tk, *tk2, *val_tk;
+       struct ec_tk *term, *factor, *expr, *tk, *val,
+               *pre_op, *post_op, *post, *final;
        int ret = 0;
 
-       val_tk = ec_tk_str_new(NULL, "val");
-       tk = ec_tk_seq_new_list(NULL,
-               ec_tk_clone(val_tk),
+       // XXX check all APIs: pointers are "moved", they are freed by
+       // the callee
+
+       /* Example that generates an expression "manually". We keep it
+        * here for reference. */
+
+       /* create the object, we will initialize it later: this is
+        * needed because we have a circular dependency */
+       expr = ec_tk_seq_new("expr");
+
+       val = ec_tk_int("val", 0, UCHAR_MAX, 0);
+
+       /* reverse bits */
+       pre_op = ec_tk_or("pre-op",
+               ec_tk_str(NULL, "~"),
+               EC_TK_ENDLIST
+       );
+
+       /* factorial */
+       post_op = ec_tk_or("post-op",
+               ec_tk_str(NULL, "!"),
+               EC_TK_ENDLIST
+       );
+
+       term = ec_tk_or("term",
+               ec_tk_clone(val),
+               ec_tk_seq(NULL,
+                       ec_tk_str(NULL, "("),
+                       ec_tk_clone(expr),
+                       ec_tk_str(NULL, ")"),
+                       EC_TK_ENDLIST
+               ),
+               ec_tk_seq(NULL,
+                       ec_tk_clone(pre_op),
+                       ec_tk_clone(expr),
+                       EC_TK_ENDLIST
+               ),
+               EC_TK_ENDLIST
+       );
+
+       factor = ec_tk_seq("factor",
+               ec_tk_clone(term),
                ec_tk_many_new(NULL,
-                       ec_tk_seq_new_list(NULL,
-                               ec_tk_str_new(NULL, "*"),
-                               ec_tk_clone(val_tk),
+                       ec_tk_seq(NULL,
+                               ec_tk_str(NULL, "+"),
+                               ec_tk_clone(term),
                                EC_TK_ENDLIST
                        ),
                        0, 0
                ),
                EC_TK_ENDLIST
        );
-       ec_tk_free(val_tk);
-       val_tk = NULL;
 
-       tk2 = ec_tk_seq_new_list(NULL,
-               ec_tk_clone(tk),
+       post = ec_tk_seq("post",
+               ec_tk_clone(factor),
                ec_tk_many_new(NULL,
-                       ec_tk_seq_new_list(NULL,
-                               ec_tk_str_new(NULL, "+"),
-                               ec_tk_clone(tk),
+                       ec_tk_seq(NULL,
+                               ec_tk_str(NULL, "*"),
+                               ec_tk_clone(factor),
                                EC_TK_ENDLIST
                        ),
                        0, 0
@@ -294,29 +393,62 @@ static int ec_tk_expr_testcase(void)
                EC_TK_ENDLIST
        );
 
+       final = ec_tk_seq("final",
+               ec_tk_clone(post),
+               ec_tk_many_new(NULL, ec_tk_clone(post_op), 0, 0),
+               EC_TK_ENDLIST
+       );
 
-//             "/*-+");
-       if (tk2 == NULL) {
-               ec_log(EC_LOG_ERR, "cannot create tk\n");
+       /* free the initial references */
+       ec_tk_free(val);
+       ec_tk_free(pre_op);
+       ec_tk_free(post_op);
+       ec_tk_free(term);
+       ec_tk_free(factor);
+       ec_tk_free(post);
+
+       if (ec_tk_seq_add(expr, ec_tk_clone(final)) < 0) {
+               ec_tk_free(final);
+               ec_tk_free(expr);
                return -1;
        }
 
-       ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "val", EC_TK_ENDLIST);
-       ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "val", "*", EC_TK_ENDLIST);
-       ret |= EC_TEST_CHECK_TK_PARSE(tk, 3, "val", "*", "val", EC_TK_ENDLIST);
+       ec_tk_free(final);
 
-       ret |= EC_TEST_CHECK_TK_PARSE(tk2, 1, "val", EC_TK_ENDLIST);
-       ret |= EC_TEST_CHECK_TK_PARSE(tk2, 1, "val", "*", EC_TK_ENDLIST);
-       ret |= EC_TEST_CHECK_TK_PARSE(tk2, 3, "val", "*", "val", EC_TK_ENDLIST);
-       ret |= EC_TEST_CHECK_TK_PARSE(tk2, 3, "val", "+", "val", EC_TK_ENDLIST);
-       ret |= EC_TEST_CHECK_TK_PARSE(tk2, 5, "val", "*", "val", "+", "val",
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 1, "1", EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 1, "1", "*", EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 3, "1", "*", "1", EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 3, "1", "+", "1", EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 5, "1", "*", "1", "+", "1",
+               EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(
+               expr, 10, "~", "(", "1", "*", "(", "1", "+", "1", ")", ")",
+               EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 4, "1", "+", "~", "1",
                EC_TK_ENDLIST);
 
-       ec_tk_free(tk);
-       ec_tk_free(tk2);
-
-       tk = ec_tk_expr(NULL, ec_tk_str_new(NULL, "val"), "*+");
-       ret |= EC_TEST_CHECK_TK_PARSE(tk, 5, "val", "*", "val", "+", "val",
+       ec_tk_free(expr);
+
+       tk = ec_tk_expr_new(NULL);
+       ec_tk_expr_set_val_tk(tk, ec_tk_int(NULL, 0, UCHAR_MAX, 0));
+       ec_tk_expr_add_bin_op(tk, ec_tk_str(NULL, "+"));
+       ec_tk_expr_add_bin_op(tk, ec_tk_str(NULL, "*"));
+       ec_tk_expr_add_pre_op(tk, ec_tk_str(NULL, "~"));
+       ec_tk_expr_add_pre_op(tk, ec_tk_str(NULL, "!"));
+       ec_tk_expr_add_parenthesis(tk, ec_tk_str(NULL, "("),
+               ec_tk_str(NULL, ")"));
+       ec_tk_expr_start(tk);
+
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 1, "1", EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 1, "1", "*", EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 3, "1", "*", "1", EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 3, "1", "+", "1", EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 5, "1", "*", "1", "+", "1",
+               EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(
+               expr, 10, "~", "(", "1", "*", "(", "1", "+", "1", ")", ")",
+               EC_TK_ENDLIST);
+       ret |= EC_TEST_CHECK_TK_PARSE(expr, 4, "1", "+", "~", "1",
                EC_TK_ENDLIST);
        ec_tk_free(tk);
 
index 73bce00d675f14123e1446208012968f2cb1148d..84a1228fb07035e28e14dc2147f7e690889a1186 100644 (file)
@@ -40,6 +40,8 @@ struct ec_tk *ec_tk_expr_new(const char *id);
 int ec_tk_expr_add_bin_op(struct ec_tk *gen_tk, struct ec_tk *op);
 int ec_tk_expr_add_pre_op(struct ec_tk *gen_tk, struct ec_tk *op);
 int ec_tk_expr_add_post_op(struct ec_tk *gen_tk, struct ec_tk *op);
+int ec_tk_expr_add_parenthesis(struct ec_tk *gen_tk,
+       struct ec_tk *open, struct ec_tk *close);
 
 
 #endif
index 5e404e9a7b8e3d4bebca35d4dd773dddbd40c893..247426ac17a52286a2ec045d47431f36a2476ee5 100644 (file)
@@ -107,18 +107,21 @@ static struct ec_tk_ops ec_tk_int_ops = {
        .complete = ec_tk_default_complete,
 };
 
-struct ec_tk *ec_tk_int_new(const char *id, long long int min,
+struct ec_tk *ec_tk_int(const char *id, long long int min,
        long long int max, unsigned int base)
 {
+       struct ec_tk *gen_tk = NULL;
        struct ec_tk_int *tk = NULL;
 
-       tk = (struct ec_tk_int *)ec_tk_new(id, &ec_tk_int_ops, sizeof(*tk));
-       if (tk == NULL)
+       gen_tk = ec_tk_new(id, &ec_tk_int_ops, sizeof(*tk));
+       if (gen_tk == NULL)
                return NULL;
+       tk = (struct ec_tk_int *)gen_tk;
 
        tk->min = min;
        tk->max = max;
        tk->base = base;
+       gen_tk->flags |= EC_TK_F_INITIALIZED;
 
        return &tk->gen;
 }
@@ -143,7 +146,7 @@ static int ec_tk_int_testcase(void)
        const char *s;
        int ret = 0;
 
-       tk = ec_tk_int_new(NULL, 0, 256, 0);
+       tk = ec_tk_int(NULL, 0, 256, 0);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -166,7 +169,7 @@ static int ec_tk_int_testcase(void)
        ec_parsed_tk_free(p);
        ec_tk_free(tk);
 
-       tk = ec_tk_int_new(NULL, -1, LLONG_MAX, 16);
+       tk = ec_tk_int(NULL, -1, LLONG_MAX, 16);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -183,7 +186,7 @@ static int ec_tk_int_testcase(void)
        ec_parsed_tk_free(p);
        ec_tk_free(tk);
 
-       tk = ec_tk_int_new(NULL, LLONG_MIN, 0, 10);
+       tk = ec_tk_int(NULL, LLONG_MIN, 0, 10);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -197,7 +200,7 @@ static int ec_tk_int_testcase(void)
        ec_tk_free(tk);
 
        /* test completion */
-       tk = ec_tk_int_new(NULL, 0, 10, 0);
+       tk = ec_tk_int(NULL, 0, 10, 0);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
index 147e2d09baa05c49deced12d8f07f88afc1f6a99..b7fa6a6f4a1df01a35f50a7e62957cd28061cb96 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <ecoli_tk.h>
 
-struct ec_tk *ec_tk_int_new(const char *id, long long int min,
+struct ec_tk *ec_tk_int(const char *id, long long int min,
        long long int max, unsigned int base);
 long long ec_tk_int_getval(struct ec_tk *tk, const char *str);
 
index d93a6dec5834cdc806d894bad8ef917c306ffa21..3c37450941f1737da2723faefc21ea22cd3fd860 100644 (file)
@@ -207,7 +207,7 @@ static int ec_tk_many_testcase(void)
        struct ec_tk *tk;
        int ret = 0;
 
-       tk = ec_tk_many_new(NULL, ec_tk_str_new(NULL, "foo"), 0, 0);
+       tk = ec_tk_many_new(NULL, ec_tk_str(NULL, "foo"), 0, 0);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -219,7 +219,7 @@ static int ec_tk_many_testcase(void)
        ret |= EC_TEST_CHECK_TK_PARSE(tk, 0, EC_TK_ENDLIST);
        ec_tk_free(tk);
 
-       tk = ec_tk_many_new(NULL, ec_tk_str_new(NULL, "foo"), 1, 0);
+       tk = ec_tk_many_new(NULL, ec_tk_str(NULL, "foo"), 1, 0);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -231,7 +231,7 @@ static int ec_tk_many_testcase(void)
        ret |= EC_TEST_CHECK_TK_PARSE(tk, -1, EC_TK_ENDLIST);
        ec_tk_free(tk);
 
-       tk = ec_tk_many_new(NULL, ec_tk_str_new(NULL, "foo"), 1, 2);
+       tk = ec_tk_many_new(NULL, ec_tk_str(NULL, "foo"), 1, 2);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
index 5427e19aa38c62949880bbcbb356c10edc2a07a2..ab82d471b1ec10dea9bd84d3a30555c3c15e3738 100644 (file)
@@ -125,7 +125,7 @@ static int ec_tk_option_testcase(void)
        struct ec_tk *tk;
        int ret = 0;
 
-       tk = ec_tk_option_new(NULL, ec_tk_str_new(NULL, "foo"));
+       tk = ec_tk_option_new(NULL, ec_tk_str(NULL, "foo"));
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -137,7 +137,7 @@ static int ec_tk_option_testcase(void)
        ec_tk_free(tk);
 
        /* test completion */
-       tk = ec_tk_option_new(NULL, ec_tk_str_new(NULL, "foo"));
+       tk = ec_tk_option_new(NULL, ec_tk_str(NULL, "foo"));
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
index 55f3e69a50e35a9b76cb9938ab193486d46f335c..d3e2d201baab16b932a5bcc9d753b6ed3f3470cc 100644 (file)
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <assert.h>
 #include <stdarg.h>
+#include <errno.h>
 
 #include <ecoli_malloc.h>
 #include <ecoli_log.h>
@@ -141,7 +142,42 @@ struct ec_tk *ec_tk_or_new(const char *id)
        return &tk->gen;
 }
 
-struct ec_tk *ec_tk_or_new_list(const char *id, ...)
+int ec_tk_or_add(struct ec_tk *gen_tk, struct ec_tk *child)
+{
+       struct ec_tk_or *tk = (struct ec_tk_or *)gen_tk;
+       struct ec_tk **table;
+
+       assert(tk != NULL);
+       assert(child != NULL);
+
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
+
+       table = ec_realloc(tk->table, (tk->len + 1) * sizeof(*tk->table));
+       if (table == NULL)
+               return -1;
+
+       tk->table = table;
+       table[tk->len] = child;
+       tk->len++;
+
+       child->parent = gen_tk;
+       TAILQ_INSERT_TAIL(&gen_tk->children, child, next);
+
+       return 0;
+}
+
+int ec_tk_or_start(struct ec_tk *gen_tk)
+{
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
+
+       gen_tk->flags |= EC_TK_F_INITIALIZED;
+
+       return 0;
+}
+
+struct ec_tk *ec_tk_or(const char *id, ...)
 {
        struct ec_tk_or *tk = NULL;
        struct ec_tk *child;
@@ -152,7 +188,7 @@ struct ec_tk *ec_tk_or_new_list(const char *id, ...)
 
        tk = (struct ec_tk_or *)ec_tk_or_new(id);
        if (tk == NULL)
-               goto fail;
+               fail = 1;
 
        for (child = va_arg(ap, struct ec_tk *);
             child != EC_TK_ENDLIST;
@@ -178,36 +214,14 @@ fail:
        return NULL;
 }
 
-int ec_tk_or_add(struct ec_tk *gen_tk, struct ec_tk *child)
-{
-       struct ec_tk_or *tk = (struct ec_tk_or *)gen_tk;
-       struct ec_tk **table;
-
-       assert(tk != NULL);
-       assert(child != NULL);
-
-       table = ec_realloc(tk->table, (tk->len + 1) * sizeof(*tk->table));
-       if (table == NULL)
-               return -1;
-
-       tk->table = table;
-       table[tk->len] = child;
-       tk->len ++;
-
-       child->parent = gen_tk;
-       TAILQ_INSERT_TAIL(&gen_tk->children, child, next);
-
-       return 0;
-}
-
 static int ec_tk_or_testcase(void)
 {
        struct ec_tk *tk;
        int ret = 0;
 
-       tk = ec_tk_or_new_list(NULL,
-               ec_tk_str_new(NULL, "foo"),
-               ec_tk_str_new(NULL, "bar"),
+       tk = ec_tk_or(NULL,
+               ec_tk_str(NULL, "foo"),
+               ec_tk_str(NULL, "bar"),
                EC_TK_ENDLIST);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
@@ -223,12 +237,12 @@ static int ec_tk_or_testcase(void)
        ec_tk_free(tk);
 
        /* test completion */
-       tk = ec_tk_or_new_list(NULL,
-               ec_tk_str_new(NULL, "foo"),
-               ec_tk_str_new(NULL, "bar"),
-               ec_tk_str_new(NULL, "bar2"),
-               ec_tk_str_new(NULL, "toto"),
-               ec_tk_str_new(NULL, "titi"),
+       tk = ec_tk_or(NULL,
+               ec_tk_str(NULL, "foo"),
+               ec_tk_str(NULL, "bar"),
+               ec_tk_str(NULL, "bar2"),
+               ec_tk_str(NULL, "toto"),
+               ec_tk_str(NULL, "titi"),
                EC_TK_ENDLIST);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
index 07d4cea0427550e8dde3f255a187927fdf52b42b..e11d96bfe36397969d889118cec5449ca9ba82ee 100644 (file)
 
 #include <ecoli_tk.h>
 
-struct ec_tk *ec_tk_or_new(const char *id);
-
 /* list must be terminated with EC_TK_ENDLIST */
 /* all token given in the list will be freed when freeing this one */
-struct ec_tk *ec_tk_or_new_list(const char *id, ...);
+struct ec_tk *ec_tk_or(const char *id, ...);
 
+struct ec_tk *ec_tk_or_new(const char *id);
 /* all token given in the list will be freed when freeing this one */
 int ec_tk_or_add(struct ec_tk *tk, struct ec_tk *child);
+int ec_tk_or_start(struct ec_tk *tk);
 
 #endif
index 6feb17df87e5452b4da0e3de01d4557233d19306..3cfc06194cf2540f6b93eef83e4e4e779dc54cfd 100644 (file)
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <assert.h>
 #include <stdarg.h>
+#include <errno.h>
 
 #include <ecoli_malloc.h>
 #include <ecoli_log.h>
@@ -182,7 +183,44 @@ struct ec_tk *ec_tk_seq_new(const char *id)
        return &tk->gen;
 }
 
-struct ec_tk *ec_tk_seq_new_list(const char *id, ...)
+int ec_tk_seq_add(struct ec_tk *gen_tk, struct ec_tk *child)
+{
+       struct ec_tk_seq *tk = (struct ec_tk_seq *)gen_tk;
+       struct ec_tk **table;
+
+       // XXX check tk type
+
+       assert(tk != NULL);
+       assert(child != NULL);
+
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
+
+       table = ec_realloc(tk->table, (tk->len + 1) * sizeof(*tk->table));
+       if (table == NULL)
+               return -1;
+
+       tk->table = table;
+       table[tk->len] = child;
+       tk->len++;
+
+       child->parent = gen_tk;
+       TAILQ_INSERT_TAIL(&gen_tk->children, child, next); // XXX really needed?
+
+       return 0;
+}
+
+int ec_tk_seq_start(struct ec_tk *gen_tk)
+{
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
+
+       gen_tk->flags |= EC_TK_F_INITIALIZED;
+
+       return 0;
+}
+
+struct ec_tk *ec_tk_seq(const char *id, ...)
 {
        struct ec_tk_seq *tk = NULL;
        struct ec_tk *child;
@@ -219,38 +257,14 @@ fail:
        return NULL;
 }
 
-int ec_tk_seq_add(struct ec_tk *gen_tk, struct ec_tk *child)
-{
-       struct ec_tk_seq *tk = (struct ec_tk_seq *)gen_tk;
-       struct ec_tk **table;
-
-       // XXX check tk type
-
-       assert(tk != NULL);
-       assert(child != NULL);
-
-       table = ec_realloc(tk->table, (tk->len + 1) * sizeof(*tk->table));
-       if (table == NULL)
-               return -1;
-
-       tk->table = table;
-       table[tk->len] = child;
-       tk->len++;
-
-       child->parent = gen_tk;
-       TAILQ_INSERT_TAIL(&gen_tk->children, child, next); // XXX really needed?
-
-       return 0;
-}
-
 static int ec_tk_seq_testcase(void)
 {
        struct ec_tk *tk;
        int ret = 0;
 
-       tk = ec_tk_seq_new_list(NULL,
-               ec_tk_str_new(NULL, "foo"),
-               ec_tk_str_new(NULL, "bar"),
+       tk = ec_tk_seq(NULL,
+               ec_tk_str(NULL, "foo"),
+               ec_tk_str(NULL, "bar"),
                EC_TK_ENDLIST);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
@@ -267,10 +281,10 @@ static int ec_tk_seq_testcase(void)
        ec_tk_free(tk);
 
        /* test completion */
-       tk = ec_tk_seq_new_list(NULL,
-               ec_tk_str_new(NULL, "foo"),
-               ec_tk_option_new(NULL, ec_tk_str_new(NULL, "toto")),
-               ec_tk_str_new(NULL, "bar"),
+       tk = ec_tk_seq(NULL,
+               ec_tk_str(NULL, "foo"),
+               ec_tk_option_new(NULL, ec_tk_str(NULL, "toto")),
+               ec_tk_str(NULL, "bar"),
                EC_TK_ENDLIST);
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
index 2385da22031b8c6867bf7ab3c6585f2512851910..03c5834baaa031438e1de17a391b08c44c452de6 100644 (file)
 
 #include <ecoli_tk.h>
 
-struct ec_tk *ec_tk_seq_new(const char *id);
 
 /* list must be terminated with EC_TK_ENDLIST */
-struct ec_tk *ec_tk_seq_new_list(const char *id, ...);
+struct ec_tk *ec_tk_seq(const char *id, ...);
 
+struct ec_tk *ec_tk_seq_new(const char *id);
 int ec_tk_seq_add(struct ec_tk *tk, struct ec_tk *child);
+int ec_tk_seq_start(struct ec_tk *tk);
+
 
 #endif
index 0b53968c1bed10c2037f403ae2f0da195d6b5e62..0becba5a6873bb9562d731171e038b58b00e1bc0 100644 (file)
@@ -402,12 +402,12 @@ static int ec_tk_shlex_testcase(void)
        int ret = 0;
 
        tk = ec_tk_shlex_new(NULL,
-               ec_tk_seq_new_list(NULL,
-                       ec_tk_str_new(NULL, "foo"),
+               ec_tk_seq(NULL,
+                       ec_tk_str(NULL, "foo"),
                        ec_tk_option_new(NULL,
-                               ec_tk_str_new(NULL, "toto")
+                               ec_tk_str(NULL, "toto")
                        ),
-                       ec_tk_str_new(NULL, "bar"),
+                       ec_tk_str(NULL, "bar"),
                        EC_TK_ENDLIST
                )
        );
@@ -424,13 +424,13 @@ static int ec_tk_shlex_testcase(void)
 
        /* test completion */
        tk = ec_tk_shlex_new(NULL,
-               ec_tk_seq_new_list(NULL,
-                       ec_tk_str_new(NULL, "foo"),
+               ec_tk_seq(NULL,
+                       ec_tk_str(NULL, "foo"),
                        ec_tk_option_new(NULL,
-                               ec_tk_str_new(NULL, "toto")
+                               ec_tk_str(NULL, "toto")
                        ),
-                       ec_tk_str_new(NULL, "bar"),
-                       ec_tk_str_new(NULL, "titi"),
+                       ec_tk_str(NULL, "bar"),
+                       ec_tk_str(NULL, "titi"),
                        EC_TK_ENDLIST
                )
        );
index f3999ff349771df4abbf0c536d524363f0799232..2904713eb1b12b0e138bc63696d77c7f328b1250 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include <ecoli_log.h>
 #include <ecoli_malloc.h>
@@ -136,28 +137,64 @@ static const struct ec_tk_ops ec_tk_str_ops = {
        .free_priv = ec_tk_str_free_priv,
 };
 
-struct ec_tk *ec_tk_str_new(const char *id, const char *str)
+struct ec_tk *ec_tk_str_new(const char *id)
 {
        struct ec_tk *gen_tk = NULL;
-       struct ec_tk_str *tk = NULL;
-       char *s = NULL;
 
-       gen_tk = ec_tk_new(id, &ec_tk_str_ops, sizeof(*tk));
+       gen_tk = ec_tk_new(id, &ec_tk_str_ops, sizeof(struct ec_tk_str));
+       if (gen_tk == NULL)
+               return NULL;
+
+       return gen_tk;
+}
+
+int ec_tk_str_set_str(struct ec_tk *gen_tk, const char *str)
+{
+       struct ec_tk_str *tk = (struct ec_tk_str *)gen_tk;
+
+       if (str == NULL)
+               return -EINVAL;
+       if (tk->string != NULL)
+               return -EEXIST;
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
+
+       tk->string = ec_strdup(str);
+       if (tk->string == NULL)
+               return -ENOMEM;
+
+       tk->len = strlen(tk->string);
+
+       return 0;
+}
+
+int ec_tk_str_start(struct ec_tk *gen_tk)
+{
+       if (gen_tk->flags & EC_TK_F_INITIALIZED)
+               return -EPERM;
+
+       gen_tk->flags |= EC_TK_F_INITIALIZED;
+
+       return 0;
+}
+
+struct ec_tk *ec_tk_str(const char *id, const char *str)
+{
+       struct ec_tk *gen_tk = NULL;
+
+       gen_tk = ec_tk_str_new(id);
        if (gen_tk == NULL)
                goto fail;
 
-       s = ec_strdup(str);
-       if (s == NULL)
+       if (ec_tk_str_set_str(gen_tk, str) < 0)
                goto fail;
 
-       tk = (struct ec_tk_str *)gen_tk;
-       tk->string = s;
-       tk->len = strlen(s);
+       if (ec_tk_str_start(gen_tk) < 0)
+               goto fail;
 
        return gen_tk;
 
 fail:
-       ec_free(s);
        ec_tk_free(gen_tk);
        return NULL;
 }
@@ -167,7 +204,7 @@ static int ec_tk_str_testcase(void)
        struct ec_tk *tk;
        int ret = 0;
 
-       tk = ec_tk_str_new(NULL, "foo");
+       tk = ec_tk_str(NULL, "foo");
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -179,7 +216,7 @@ static int ec_tk_str_testcase(void)
        ret |= EC_TEST_CHECK_TK_PARSE(tk, -1, "", EC_TK_ENDLIST);
        ec_tk_free(tk);
 
-       tk = ec_tk_str_new(NULL, "Здравствуйте");
+       tk = ec_tk_str(NULL, "Здравствуйте");
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -192,7 +229,7 @@ static int ec_tk_str_testcase(void)
        ec_tk_free(tk);
 
        /* an empty token string always matches */
-       tk = ec_tk_str_new(NULL, "");
+       tk = ec_tk_str(NULL, "");
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
@@ -203,7 +240,7 @@ static int ec_tk_str_testcase(void)
        ec_tk_free(tk);
 
        /* test completion */
-       tk = ec_tk_str_new(NULL, "foo");
+       tk = ec_tk_str(NULL, "foo");
        if (tk == NULL) {
                ec_log(EC_LOG_ERR, "cannot create tk\n");
                return -1;
index 00632ecdd09ab7fcbb93a0d7207c45b26923e07f..437182386fe4e95c27a1937afa7b953a16bd0f58 100644 (file)
 
 #include <ecoli_tk.h>
 
-struct ec_tk *ec_tk_str_new(const char *id, const char *str);
+struct ec_tk *ec_tk_str(const char *id, const char *str);
+
+struct ec_tk *ec_tk_str_new(const char *id);
+int ec_tk_str_set_str(struct ec_tk *tk, const char *str);
+int ec_tk_str_start(struct ec_tk *tk);
 
 #endif
index 8c5ffc5a01b243e2bed75a6364790af4cd2d238f..7432f3c57ffc47a782ac499643bc8477033ada18 100644 (file)
@@ -175,16 +175,16 @@ static int create_commands(void)
        if (cmdlist == NULL)
                goto fail;
 
-       cmd = ec_tk_seq_new_list(NULL,
-               ec_tk_str_new(NULL, "hello"),
-               ec_tk_or_new_list(NULL,
-                       ec_tk_or_new_list("name",
-                               ec_tk_str_new(NULL, "john"),
-                               ec_tk_str_new(NULL, "johnny"),
-                               ec_tk_str_new(NULL, "mike"),
+       cmd = ec_tk_seq(NULL,
+               ec_tk_str(NULL, "hello"),
+               ec_tk_or(NULL,
+                       ec_tk_or("name",
+                               ec_tk_str(NULL, "john"),
+                               ec_tk_str(NULL, "johnny"),
+                               ec_tk_str(NULL, "mike"),
                                EC_TK_ENDLIST
                        ),
-                       ec_tk_int_new("int", 0, 10, 10),
+                       ec_tk_int("int", 0, 10, 10),
                        EC_TK_ENDLIST
                ),
                EC_TK_ENDLIST
@@ -197,8 +197,8 @@ static int create_commands(void)
        if (ec_tk_or_add(cmdlist, cmd) < 0)
                goto fail;
 
-       cmd = ec_tk_seq_new_list(NULL,
-               ec_tk_str_new(NULL, "bye"),
+       cmd = ec_tk_seq(NULL,
+               ec_tk_str(NULL, "bye"),
                EC_TK_ENDLIST
        );
        ec_keyval_set(ec_tk_attrs(cmd), "help", "say bye to someone", NULL);