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
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
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 ?
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;
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;
}
fail:
ec_free(display_copy);
return ret;
-
}
int
ec_free(item->str);
ec_free(item->display);
ec_free(item->path);
+ ec_keyval_free(item->attrs);
ec_free(item);
}
}
ec_free(compnode);
}
+ ec_keyval_free(completed->attrs);
ec_free(completed);
}
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;
unsigned count;
unsigned count_match;
struct ec_completed_node_list nodes;
+ struct ec_keyval *attrs; // XXX per node instead?
};
/*
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;
#define ECOLI_KEYVAL_
#include <stdio.h>
+#include <stdbool.h>
typedef void (*ec_keyval_elt_free_t)(void *);
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);
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))
return -ENOMEM;
}
- printf("eval var %s %p\n", str, eval);
+ //printf("eval var %s %p\n", str, eval);
*result = eval;
return 0;
else
return -EINVAL;
- printf("eval post_op %p\n", eval);
+ //printf("eval post_op %p\n", eval);
*result = eval;
return 0;
(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);
return -EINVAL;
}
- printf("eval bin_op out %p\n", *result);
+ //printf("eval bin_op out %p\n", *result);
return 0;
}
return -EINVAL;
}
- printf("eval paren\n");
+ //printf("eval paren\n");
*result = out;
return 0;
}
ec_parsed_free(p);
p = NULL;
- ec_node_dump(stdout, cmd);
+ //ec_node_dump(stdout, cmd);
ec_node_free(node->expr);
node->expr = expr;
assert(node != NULL);
- printf("add child %s\n", child->id);
if (child == NULL)
return -EINVAL;
weak = NULL;
node->child = expr;
- ec_node_dump(stdout, node->child); //XXX
+ //ec_node_dump(stdout, node->child); //XXX
return 0;
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;
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)
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;
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;
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
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)
{
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;
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);
#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
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;
}
ec_parsed_free_children(parsed);
ec_strvec_free(parsed->strvec);
+ ec_keyval_free(parsed->attrs);
ec_free(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);
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;
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
{
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;
cleanup / rework
================
+- ec_completed_item_update()
+- ec_completed_item_set_display_value()
+
- add_no_match
- add_partial_match
- check XXX in code