save
authorOlivier Matz <zer0@droids-corp.org>
Fri, 10 Nov 2017 21:05:03 +0000 (22:05 +0100)
committerOlivier Matz <zer0@droids-corp.org>
Fri, 10 Nov 2017 21:05:03 +0000 (22:05 +0100)
15 files changed:
lib/Makefile
lib/ecoli_completed.c
lib/ecoli_completed.h
lib/ecoli_keyval.c
lib/ecoli_keyval.h
lib/ecoli_node_cmd.c
lib/ecoli_node_expr.c
lib/ecoli_node_int.c
lib/ecoli_node_int.h
lib/ecoli_parsed.c
lib/ecoli_parsed.h
lib/ecoli_vec.c
lib/ecoli_vec.h
lib/main-readline.c
lib/todo.txt

index d6a4e80..b258752 100644 (file)
@@ -50,6 +50,7 @@ srcs += ecoli_malloc.c
 srcs += ecoli_strvec.c
 srcs += ecoli_test.c
 srcs += ecoli_node.c
+srcs += ecoli_node_any.c
 srcs += ecoli_node_cmd.c
 srcs += ecoli_node_empty.c
 srcs += ecoli_node_expr.c
@@ -78,7 +79,7 @@ ldflags-$(O)test = -rdynamic
 exe-y-$(O)test = $(srcs) main.c
 
 ldflags-$(O)readline = -lreadline -ltermcap
-exe-y-$(O)readline = $(srcs) main-readline.c
+#exe-y-$(O)readline = $(srcs) main-readline.c
 
 include $(ECOLI)/mk/ecoli-post.mk
 
index 64bb70d..553eccc 100644 (file)
@@ -45,11 +45,22 @@ struct ec_completed *ec_completed(void)
 
        completed = ec_calloc(1, sizeof(*completed));
        if (completed == NULL)
-               return NULL;
+               goto fail;
 
        TAILQ_INIT(&completed->nodes);
 
+       completed->attrs = ec_keyval();
+       if (completed->attrs == NULL)
+               goto fail;
+
        return completed;
+
+ fail:
+       if (completed != NULL)
+               ec_keyval_free(completed->attrs);
+       ec_free(completed);
+
+       return NULL;
 }
 
 /* XXX on error, states are not freed ?
@@ -181,7 +192,11 @@ ec_completed_item(struct ec_parsed *state, const struct ec_node *node)
 
        item = ec_calloc(1, sizeof(*item));
        if (item == NULL)
-               return NULL;
+               goto fail;
+
+       item->attrs = ec_keyval();
+       if (item->attrs == NULL)
+               goto fail;
 
        /* get path len */
        for (p = state, len = 0; p != NULL;
@@ -207,8 +222,9 @@ fail:
                ec_free(item->path);
                ec_free(item->str);
                ec_free(item->display);
+               ec_keyval_free(item->attrs);
        }
-       ec_completed_item_free(item);
+       ec_free(item);
 
        return NULL;
 }
@@ -284,7 +300,6 @@ int ec_completed_item_set_display(struct ec_completed_item *item,
 fail:
        ec_free(display_copy);
        return ret;
-
 }
 
 int
@@ -333,6 +348,7 @@ void ec_completed_item_free(struct ec_completed_item *item)
        ec_free(item->str);
        ec_free(item->display);
        ec_free(item->path);
+       ec_keyval_free(item->attrs);
        ec_free(item);
 }
 
@@ -385,6 +401,7 @@ void ec_completed_free(struct ec_completed *completed)
                }
                ec_free(compnode);
        }
+       ec_keyval_free(completed->attrs);
        ec_free(completed);
 }
 
index 1627cfe..22016e5 100644 (file)
@@ -46,7 +46,7 @@ struct ec_completed_item {
        const struct ec_node *node;
        char *str;
        char *display;
-       /* XXX add a keyval (attrs) */
+       struct ec_keyval *attrs;
 
        /* reverse order: [0] = last, [len-1] = root */
        const struct ec_node **path;
@@ -67,6 +67,7 @@ struct ec_completed {
        unsigned count;
        unsigned count_match;
        struct ec_completed_node_list nodes;
+       struct ec_keyval *attrs; // XXX per node instead?
 };
 
 /*
index a47ded9..e80dd08 100644 (file)
@@ -87,6 +87,11 @@ static void ec_keyval_elt_free(struct ec_keyval_elt *elt)
                elt->free(elt->val);
 }
 
+bool ec_keyval_has_key(const struct ec_keyval *keyval, const char *key)
+{
+       return !!ec_keyval_lookup(keyval, key);
+}
+
 void *ec_keyval_get(const struct ec_keyval *keyval, const char *key)
 {
        struct ec_keyval_elt *elt;
index 82fc9e4..30232d0 100644 (file)
@@ -29,6 +29,7 @@
 #define ECOLI_KEYVAL_
 
 #include <stdio.h>
+#include <stdbool.h>
 
 typedef void (*ec_keyval_elt_free_t)(void *);
 
@@ -37,6 +38,7 @@ struct ec_keyval;
 struct ec_keyval *ec_keyval(void);
 
 void *ec_keyval_get(const struct ec_keyval *keyval, const char *key);
+bool ec_keyval_has_key(const struct ec_keyval *keyval, const char *key);
 int ec_keyval_del(struct ec_keyval *keyval, const char *key);
 int ec_keyval_set(struct ec_keyval *keyval, const char *key, void *val,
        ec_keyval_elt_free_t free_cb);
index db08cbf..0aca9b1 100644 (file)
@@ -85,7 +85,7 @@ 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);
+               //printf("i=%d id=%s\n", i, id);
                if (id == NULL)
                        continue;
                if (strcmp(str, id))
@@ -104,7 +104,7 @@ ec_node_cmd_eval_var(void **result, void *userctx,
                        return -ENOMEM;
        }
 
-       printf("eval var %s %p\n", str, eval);
+       //printf("eval var %s %p\n", str, eval);
        *result = eval;
 
        return 0;
@@ -141,7 +141,7 @@ ec_node_cmd_eval_post_op(void **result, void *userctx, void *operand,
        else
                return -EINVAL;
 
-       printf("eval post_op %p\n", eval);
+       //printf("eval post_op %p\n", eval);
        *result = eval;
 
        return 0;
@@ -159,7 +159,7 @@ ec_node_cmd_eval_bin_op(void **result, void *userctx, void *operand1,
 
        (void)userctx;
 
-       printf("eval bin_op %p %p\n", in1, in2);
+       //printf("eval bin_op %p %p\n", in1, in2);
 
        /* get parsed string vector, it should contain only one str */
        vec = ec_parsed_strvec(operator);
@@ -192,7 +192,7 @@ ec_node_cmd_eval_bin_op(void **result, void *userctx, void *operand1,
                return -EINVAL;
        }
 
-       printf("eval bin_op out %p\n", *result);
+       //printf("eval bin_op out %p\n", *result);
 
        return 0;
 }
@@ -226,7 +226,7 @@ ec_node_cmd_eval_parenthesis(void **result, void *userctx,
                return -EINVAL;
        }
 
-       printf("eval paren\n");
+       //printf("eval paren\n");
        *result = out;
 
        return 0;
@@ -374,7 +374,7 @@ static int ec_node_cmd_build(struct ec_node *gen_node)
        }
        ec_parsed_free(p);
        p = NULL;
-       ec_node_dump(stdout, cmd);
+       //ec_node_dump(stdout, cmd);
 
        ec_node_free(node->expr);
        node->expr = expr;
@@ -413,7 +413,6 @@ int ec_node_cmd_add_child(struct ec_node *gen_node, struct ec_node *child)
 
        assert(node != NULL);
 
-       printf("add child %s\n", child->id);
        if (child == NULL)
                return -EINVAL;
 
index 24bdfd9..9207e4d 100644 (file)
@@ -213,7 +213,7 @@ static int ec_node_expr_build(struct ec_node *gen_node)
        weak = NULL;
 
        node->child = expr;
-       ec_node_dump(stdout, node->child); //XXX
+       //ec_node_dump(stdout, node->child); //XXX
 
        return 0;
 
@@ -595,7 +595,7 @@ int ec_node_expr_eval(void **user_result, const struct ec_node *node,
        if (!ec_parsed_matches(parsed))
                return -EINVAL;
 
-       ec_parsed_dump(stdout, parsed); //XXX
+       //ec_parsed_dump(stdout, parsed); //XXX
        ret = eval_expression(&result, userctx, ops, node, parsed);
        if (ret < 0)
                return ret;
index b685f16..cb7f60b 100644 (file)
@@ -47,24 +47,32 @@ EC_LOG_TYPE_REGISTER(node_int);
 
 struct ec_node_int {
        struct ec_node gen;
+       bool is_signed;
        bool check_min;
-       long long int min;
        bool check_max;
-       long long int max;
+       union {
+               int64_t min;
+               uint64_t umin;
+       };
+       union {
+               int64_t max;
+               uint64_t umax;
+       };
        unsigned int base;
 };
 
 static int parse_llint(struct ec_node_int *node, const char *str,
-       long long *val)
+       int64_t *val)
 {
        char *endptr;
 
        errno = 0;
        *val = strtoll(str, &endptr, node->base);
 
-       /* out of range */
-       if ((errno == ERANGE && (*val == LLONG_MAX || *val == LLONG_MIN)) ||
-                       (errno != 0 && *val == 0))
+       if (errno == ERANGE && (*val == LLONG_MAX || *val == LLONG_MIN))
+               return -1;
+
+       if (errno != 0 && *val == 0)
                return -1;
 
        if (node->check_min && *val < node->min)
@@ -79,13 +87,44 @@ static int parse_llint(struct ec_node_int *node, const char *str,
        return 0;
 }
 
+static int parse_ullint(struct ec_node_int *node, const char *str,
+                       uint64_t *val)
+{
+       char *endptr;
+
+       /* since a negative input is silently converted to a positive
+        * one by strtoull(), first check that it is positive */
+       if (strchr(str, '-'))
+               return -1;
+
+       errno = 0;
+       *val = strtoull(str, &endptr, node->base);
+
+       if (errno == ERANGE && *val == ULLONG_MAX)
+               return -1;
+
+       if (errno != 0 && *val == 0)
+               return -1;
+
+       if (node->check_min && *val < node->umin)
+               return -1;
+
+       if (node->check_max && *val > node->umax)
+               return -1;
+
+       if (*endptr != 0)
+               return -1;
+
+       return 0;
+}
+
 static int ec_node_int_parse(const struct ec_node *gen_node,
                        struct ec_parsed *state,
                        const struct ec_strvec *strvec)
 {
        struct ec_node_int *node = (struct ec_node_int *)gen_node;
        const char *str;
-       long long val;
+       int64_t val;
 
        (void)state;
 
@@ -115,12 +154,15 @@ static struct ec_node_type ec_node_int_type = {
 
 EC_NODE_TYPE_REGISTER(ec_node_int_type);
 
-struct ec_node *ec_node_int(const char *id, long long int min,
-       long long int max, unsigned int base)
+struct ec_node *ec_node_int(const char *id, int64_t min,
+       int64_t max, unsigned int base)
 {
        struct ec_node *gen_node = NULL;
        struct ec_node_int *node = NULL;
 
+       if (min > max)
+               return NULL;
+
        gen_node = __ec_node(&ec_node_int_type, id);
        if (gen_node == NULL)
                return NULL;
@@ -131,14 +173,39 @@ struct ec_node *ec_node_int(const char *id, long long int min,
        node->check_max = true;
        node->max = max;
        node->base = base;
+       node->is_signed = true;
 
        return &node->gen;
 }
 
-long long ec_node_int_getval(struct ec_node *gen_node, const char *str)
+struct ec_node *ec_node_uint(const char *id, uint64_t min,
+       uint64_t max, unsigned int base)
+{
+       struct ec_node *gen_node = NULL;
+       struct ec_node_int *node = NULL;
+
+       if (min > max)
+               return NULL;
+
+       gen_node = __ec_node(&ec_node_int_type, id);
+       if (gen_node == NULL)
+               return NULL;
+       node = (struct ec_node_int *)gen_node;
+
+       node->check_min = true;
+       node->min = min;
+       node->check_max = true;
+       node->max = max;
+       node->base = base;
+       node->is_signed = true;
+
+       return &node->gen;
+}
+
+int64_t ec_node_int_getval(struct ec_node *gen_node, const char *str)
 {
        struct ec_node_int *node = (struct ec_node_int *)gen_node;
-       long long val = 0;
+       int64_t val = 0;
 
        // XXX check type here
        // if gen_node->type != int fail
@@ -148,6 +215,19 @@ long long ec_node_int_getval(struct ec_node *gen_node, const char *str)
        return val;
 }
 
+uint64_t ec_node_uint_getval(struct ec_node *gen_node, const char *str)
+{
+       struct ec_node_int *node = (struct ec_node_int *)gen_node;
+       uint64_t val = 0;
+
+       // XXX check type here
+       // if gen_node->type != int fail
+
+       parse_ullint(node, str, &val);
+
+       return val;
+}
+
 /* LCOV_EXCL_START */
 static int ec_node_int_testcase(void)
 {
@@ -156,7 +236,7 @@ static int ec_node_int_testcase(void)
        const char *s;
        int ret = 0;
 
-       node = ec_node_int(NULL, 0, 256, 0);
+       node = ec_node_uint(NULL, 0, 256, 0);
        if (node == NULL) {
                EC_LOG(EC_LOG_ERR, "cannot create node\n");
                return -1;
@@ -175,7 +255,7 @@ static int ec_node_int_testcase(void)
 
        p = ec_node_parse(node, "10");
        s = ec_strvec_val(ec_parsed_strvec(p), 0);
-       EC_TEST_ASSERT(s != NULL && ec_node_int_getval(node, s) == 10);
+       EC_TEST_ASSERT(s != NULL && ec_node_uint_getval(node, s) == 10);
        ec_parsed_free(p);
        ec_node_free(node);
 
index d03dd3d..b871529 100644 (file)
 #ifndef ECOLI_NODE_INT_
 #define ECOLI_NODE_INT_
 
+#include <stdint.h>
+
 #include <ecoli_node.h>
 
 // XXX remove min, max, base from new(), and add ec_node_int_set_limits() +
 // XXX ec_node_int_set_base() ?
-struct ec_node *ec_node_int(const char *id, long long int min,
-       long long int max, unsigned int base);
-long long ec_node_int_getval(struct ec_node *node, const char *str);
+
+struct ec_node *ec_node_int(const char *id, int64_t min,
+                       int64_t max, unsigned int base);
+int64_t ec_node_int_getval(struct ec_node *node, const char *str);
+
+struct ec_node *ec_node_uint(const char *id, uint64_t min,
+                       uint64_t max, unsigned int base);
+uint64_t ec_node_uint_getval(struct ec_node *node, const char *str);
+
 
 #endif
index c717723..e951671 100644 (file)
@@ -147,9 +147,17 @@ struct ec_parsed *ec_parsed(void)
 
        TAILQ_INIT(&parsed->children);
 
+       parsed->attrs = ec_keyval();
+       if (parsed->attrs == NULL)
+               goto fail;
+
        return parsed;
 
  fail:
+       if (parsed != NULL)
+               ec_keyval_free(parsed->attrs);
+       ec_free(parsed);
+
        return NULL;
 }
 
@@ -174,6 +182,7 @@ void ec_parsed_free(struct ec_parsed *parsed)
 
        ec_parsed_free_children(parsed);
        ec_strvec_free(parsed->strvec);
+       ec_keyval_free(parsed->attrs);
        ec_free(parsed);
 }
 
index 1a246ce..459f93d 100644 (file)
@@ -47,7 +47,7 @@ struct ec_parsed {
        struct ec_parsed *parent;
        const struct ec_node *node;
        struct ec_strvec *strvec;
-       /* XXX add a keyval (attrs) */
+       struct ec_keyval *attrs;
 };
 
 struct ec_parsed *ec_parsed(void);
index 001891e..871911d 100644 (file)
@@ -93,6 +93,7 @@ int ec_vec_add_by_ref(struct ec_vec *vec, void *ptr)
                new_vec = ec_realloc(vec->vec, vec->elt_size * (vec->len + 1));
                if (new_vec == NULL)
                        return -ENOMEM;
+               vec->size = vec->len + 1;
        }
 
        vec->vec = new_vec;
index defd652..493e453 100644 (file)
@@ -62,6 +62,8 @@ struct ec_vec *ec_vec_dup(const struct ec_vec *vec);
 struct ec_vec *ec_vec_ndup(const struct ec_vec *vec,
        size_t off, size_t len);
 void ec_vec_free(struct ec_vec *vec);
+
+__attribute__((pure))
 size_t ec_vec_len(const struct ec_vec *vec);
 
 #endif
index 8fecad4..4601ae8 100644 (file)
@@ -55,7 +55,7 @@ static char *my_completion_entry(const char *s, int state)
 {
        static struct ec_completed *c;
        static struct ec_completed_iter *iter;
-       static const struct ec_completed_item *item;
+       const struct ec_completed_item *item;
 
        (void)s;
 
index 37a61d7..8d56dc5 100644 (file)
@@ -9,6 +9,9 @@ X tk_re
 cleanup / rework
 ================
 
+- ec_completed_item_update()
+- ec_completed_item_set_display_value()
+
 - add_no_match
 - add_partial_match
 - check XXX in code