{
if (ec_tk_type_lookup(type->name) != NULL)
return -EEXIST;
+ if (type->size < sizeof(struct ec_tk))
+ return -EINVAL;
+
TAILQ_INSERT_TAIL(&tk_type_list, type, next);
return 0;
fprintf(out, "%s\n", type->name);
}
-struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_type *type,
- size_t size)
+struct ec_tk *__ec_tk_new(const struct ec_tk_type *type, const char *id)
{
struct ec_tk *tk = NULL;
char buf[256]; // XXX
- assert(size >= sizeof(*tk));
-
ec_log(EC_LOG_DEBUG, "create node type=%s id=%s\n", type->name, id);
- tk = ec_calloc(1, size);
+ tk = ec_calloc(1, type->size);
if (tk == NULL)
goto fail;
return NULL;
}
+struct ec_tk *ec_tk_new(const char *typename, const char *id)
+{
+ struct ec_tk_type *type;
+
+ type = ec_tk_type_lookup(typename);
+ if (type == NULL) {
+ ec_log(EC_LOG_ERR, "type=%s does not exist\n", typename);
+ return NULL;
+ }
+
+ return __ec_tk_new(type, id);
+}
+
void ec_tk_free(struct ec_tk *tk)
{
if (tk == NULL)
typedef struct ec_completed_tk *(*ec_tk_complete_t)(const struct ec_tk *tk,
const struct ec_strvec *strvec);
typedef const char * (*ec_tk_desc_t)(const struct ec_tk *);
+typedef void (*ec_tk_init_priv_t)(struct ec_tk *);
typedef void (*ec_tk_free_priv_t)(struct ec_tk *);
#define EC_TK_TYPE_REGISTER(t) \
ec_tk_parse_t parse;
ec_tk_complete_t complete;
ec_tk_desc_t desc;
+ size_t size;
+ ec_tk_init_priv_t init_priv;
ec_tk_free_priv_t free_priv;
};
struct ec_tk_list children;
};
-struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_type *type,
- size_t priv_size);
+/* create a new token when the type is known, typically called from the node
+ * code */
+struct ec_tk *__ec_tk_new(const struct ec_tk_type *type, const char *id);
+
+/* create a_new token node */
+struct ec_tk *ec_tk_new(const char *typename, const char *id);
void ec_tk_free(struct ec_tk *tk);
/* build the expression parser */
ret = -ENOMEM;
- expr = ec_tk_expr("expr");
+ expr = ec_tk_new("expr", "expr");
if (expr == NULL)
goto fail;
ret = ec_tk_expr_set_val_tk(expr, ec_tk_re(NULL, "[a-zA-Z0-9]+"));
goto fail;
ret = -ENOMEM;
- cmd = ec_tk_seq(NULL);
+ cmd = ec_tk_new("seq", NULL);
if (cmd == NULL)
goto fail;
.build = ec_tk_cmd_build,
.parse = ec_tk_cmd_parse,
.complete = ec_tk_cmd_complete,
+ .size = sizeof(struct ec_tk_cmd),
.free_priv = ec_tk_cmd_free_priv,
};
struct ec_tk *gen_tk = NULL;
struct ec_tk_cmd *tk = NULL;
- gen_tk = ec_tk_new(id, &ec_tk_cmd_type, sizeof(*tk));
+ gen_tk = __ec_tk_new(&ec_tk_cmd_type, id);
if (gen_tk == NULL)
goto fail;
.name = "empty",
.parse = ec_tk_empty_parse,
.complete = ec_tk_default_complete,
+ .size = sizeof(struct ec_tk_empty),
};
EC_TK_TYPE_REGISTER(ec_tk_empty_type);
-struct ec_tk *ec_tk_empty(const char *id)
-{
- return ec_tk_new(id, &ec_tk_empty_type,
- sizeof(struct ec_tk_empty));
-}
-
static int ec_tk_empty_testcase(void)
{
struct ec_tk *tk;
int ret = 0;
- tk = ec_tk_empty(NULL);
+ tk = ec_tk_new("empty", NULL);
if (tk == NULL) {
ec_log(EC_LOG_ERR, "cannot create tk\n");
return -1;
ec_tk_free(tk);
/* never completes */
- tk = ec_tk_empty(NULL);
+ tk = ec_tk_new("empty", NULL);
if (tk == NULL) {
ec_log(EC_LOG_ERR, "cannot create tk\n");
return -1;
/* create the object, we will initialize it later: this is
* needed because we have a circular dependency */
ret = -ENOMEM;
- weak = ec_tk_weakref_empty("weak");
+ weak = ec_tk_new("weakref", "weak");
if (weak == NULL)
return -1;
/* prefix unary operators */
- pre_op = ec_tk_or("pre-op");
+ pre_op = ec_tk_new("or", "pre-op");
if (pre_op == NULL)
goto fail;
for (i = 0; i < tk->pre_ops_len; i++) {
}
/* suffix unary operators */
- post_op = ec_tk_or("post-op");
+ post_op = ec_tk_new("or", "post-op");
if (post_op == NULL)
goto fail;
for (i = 0; i < tk->post_ops_len; i++) {
goto fail;
}
- post = ec_tk_or("post");
+ post = ec_tk_new("or", "post");
if (post == NULL)
goto fail;
if (ec_tk_or_add(post, ec_tk_clone(tk->val_tk)) < 0)
.build = ec_tk_expr_build,
.parse = ec_tk_expr_parse,
.complete = ec_tk_expr_complete,
+ .size = sizeof(struct ec_tk_expr),
.free_priv = ec_tk_expr_free_priv,
};
EC_TK_TYPE_REGISTER(ec_tk_expr_type);
-struct ec_tk *ec_tk_expr(const char *id)
-{
- struct ec_tk_expr *tk = NULL;
- struct ec_tk *gen_tk = NULL;
-
- gen_tk = ec_tk_new(id, &ec_tk_expr_type, sizeof(*tk));
- if (gen_tk == NULL)
- return NULL;
- tk = (struct ec_tk_expr *)gen_tk;
-
- return gen_tk;
-}
-
int ec_tk_expr_set_val_tk(struct ec_tk *gen_tk, struct ec_tk *val_tk)
{
struct ec_tk_expr *tk = (struct ec_tk_expr *)gen_tk;
struct ec_tk *tk = NULL, *lex_tk = NULL;
int ret = 0;
- tk = ec_tk_expr("expr");
+ tk = ec_tk_new("expr", "my_expr");
if (tk == NULL)
return -1;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
struct ec_tk_int {
struct ec_tk gen;
+ bool check_min;
long long int min;
+ bool check_max;
long long int max;
unsigned int base;
};
(errno != 0 && *val == 0))
return -1;
- if (*val < tk->min || *val > tk->max)
+ if (tk->check_min && *val < tk->min)
+ return -1;
+
+ if (tk->check_max && *val > tk->max)
return -1;
if (*endptr != 0)
.name = "int",
.parse = ec_tk_int_parse,
.complete = ec_tk_default_complete,
+ .size = sizeof(struct ec_tk_int),
};
EC_TK_TYPE_REGISTER(ec_tk_int_type);
struct ec_tk *gen_tk = NULL;
struct ec_tk_int *tk = NULL;
- gen_tk = ec_tk_new(id, &ec_tk_int_type, sizeof(*tk));
+ gen_tk = __ec_tk_new(&ec_tk_int_type, id);
if (gen_tk == NULL)
return NULL;
tk = (struct ec_tk_int *)gen_tk;
+ tk->check_min = true;
tk->min = min;
+ tk->check_max = true;
tk->max = max;
tk->base = base;
.parse = ec_tk_many_parse,
.complete = ec_tk_default_complete,
//XXX .complete = ec_tk_many_complete,
+ .size = sizeof(struct ec_tk_many),
.free_priv = ec_tk_many_free_priv,
};
if (child == NULL)
return NULL;
- tk = (struct ec_tk_many *)ec_tk_new(id, &ec_tk_many_type,
- sizeof(*tk));
+ tk = (struct ec_tk_many *)__ec_tk_new(&ec_tk_many_type, id);
if (tk == NULL) {
ec_tk_free(child);
return NULL;
.name = "option",
.parse = ec_tk_option_parse,
.complete = ec_tk_option_complete,
+ .size = sizeof(struct ec_tk_option),
.free_priv = ec_tk_option_free_priv,
};
if (child == NULL)
return NULL;
- gen_tk = ec_tk_new(id, &ec_tk_option_type, sizeof(*tk));
+ gen_tk = __ec_tk_new(&ec_tk_option_type, id);
if (gen_tk == NULL) {
ec_tk_free(child);
return NULL;
}
static struct ec_tk_type ec_tk_or_type = {
- .name = "tk_or",
+ .name = "or",
.parse = ec_tk_or_parse,
.complete = ec_tk_or_complete,
+ .size = sizeof(struct ec_tk_or),
.free_priv = ec_tk_or_free_priv,
};
EC_TK_TYPE_REGISTER(ec_tk_or_type);
-struct ec_tk *ec_tk_or(const char *id)
-{
- struct ec_tk *gen_tk = NULL;
- struct ec_tk_or *tk = NULL;
-
- gen_tk = ec_tk_new(id, &ec_tk_or_type, sizeof(*tk));
- if (gen_tk == NULL)
- return NULL;
-
- tk = (struct ec_tk_or *)gen_tk;
- tk->table = NULL;
- tk->len = 0;
-
- return gen_tk;
-}
-
struct ec_tk *__ec_tk_or(const char *id, ...)
{
struct ec_tk *gen_tk = NULL;
va_start(ap, id);
- gen_tk = ec_tk_or(id);
+ gen_tk = __ec_tk_new(&ec_tk_or_type, id);
tk = (struct ec_tk_or *)gen_tk;
if (tk == NULL)
fail = 1;;
.name = "re",
.parse = ec_tk_re_parse,
.complete = ec_tk_default_complete,
+ .size = sizeof(struct ec_tk_re),
.free_priv = ec_tk_re_free_priv,
};
EC_TK_TYPE_REGISTER(ec_tk_re_type);
-struct ec_tk *ec_tk_re_new(const char *id)
-{
- struct ec_tk *gen_tk = NULL;
-
- gen_tk = ec_tk_new(id, &ec_tk_re_type, sizeof(struct ec_tk_re));
- if (gen_tk == NULL)
- return NULL;
-
- return gen_tk;
-}
-
int ec_tk_re_set_regexp(struct ec_tk *gen_tk, const char *str)
{
struct ec_tk_re *tk = (struct ec_tk_re *)gen_tk;
{
struct ec_tk *gen_tk = NULL;
- gen_tk = ec_tk_re_new(id);
+ gen_tk = __ec_tk_new(&ec_tk_re_type, id);
if (gen_tk == NULL)
goto fail;
.name = "re_lex",
.parse = ec_tk_re_lex_parse,
//.complete = ec_tk_re_lex_complete, //XXX
+ .size = sizeof(struct ec_tk_re_lex),
.free_priv = ec_tk_re_lex_free_priv,
};
if (child == NULL)
return NULL;
- tk = (struct ec_tk_re_lex *)ec_tk_new(id, &ec_tk_re_lex_type,
- sizeof(*tk));
+ tk = (struct ec_tk_re_lex *)__ec_tk_new(&ec_tk_re_lex_type, id);
if (tk == NULL) {
ec_tk_free(child);
return NULL;
.name = "seq",
.parse = ec_tk_seq_parse,
.complete = ec_tk_seq_complete,
+ .size = sizeof(struct ec_tk_seq),
.free_priv = ec_tk_seq_free_priv,
};
return 0;
}
-struct ec_tk *ec_tk_seq(const char *id)
-{
- struct ec_tk *gen_tk = NULL;
- struct ec_tk_seq *tk = NULL;
-
- gen_tk = ec_tk_new(id, &ec_tk_seq_type, sizeof(*tk));
- if (gen_tk == NULL)
- return NULL;
-
- tk = (struct ec_tk_seq *)gen_tk;
- tk->table = NULL;
- tk->len = 0;
-
- return gen_tk;
-}
-
struct ec_tk *__ec_tk_seq(const char *id, ...)
{
struct ec_tk *gen_tk = NULL;
va_start(ap, id);
- gen_tk = ec_tk_seq(id);
+ gen_tk = __ec_tk_new(&ec_tk_seq_type, id);
tk = (struct ec_tk_seq *)gen_tk;
if (tk == NULL)
fail = 1;;
.name = "sh_lex",
.parse = ec_tk_sh_lex_parse,
.complete = ec_tk_sh_lex_complete,
+ .size = sizeof(struct ec_tk_sh_lex),
.free_priv = ec_tk_sh_lex_free_priv,
};
if (child == NULL)
return NULL;
- tk = (struct ec_tk_sh_lex *)ec_tk_new(id, &ec_tk_sh_lex_type,
- sizeof(*tk));
+ tk = (struct ec_tk_sh_lex *)__ec_tk_new(&ec_tk_sh_lex_type, id);
if (tk == NULL) {
ec_tk_free(child);
return NULL;
.name = "space",
.parse = ec_tk_space_parse,
.complete = ec_tk_default_complete,
+ .size = sizeof(struct ec_tk_space),
};
EC_TK_TYPE_REGISTER(ec_tk_space_type);
-struct ec_tk *ec_tk_space_new(const char *id)
-{
- return ec_tk_new(id, &ec_tk_space_type, sizeof(struct ec_tk_space));
-}
-
static int ec_tk_space_testcase(void)
{
struct ec_tk *tk;
int ret = 0;
- tk = ec_tk_space_new(NULL);
+ tk = ec_tk_new("space", NULL);
if (tk == NULL) {
ec_log(EC_LOG_ERR, "cannot create tk\n");
return -1;
ec_tk_free(tk);
/* test completion */
- tk = ec_tk_space_new(NULL);
+ tk = ec_tk_new("space", NULL);
if (tk == NULL) {
ec_log(EC_LOG_ERR, "cannot create tk\n");
return -1;
.parse = ec_tk_str_parse,
.complete = ec_tk_str_complete,
.desc = ec_tk_str_desc,
+ .size = sizeof(struct ec_tk_str),
.free_priv = ec_tk_str_free_priv,
};
EC_TK_TYPE_REGISTER(ec_tk_str_type);
-struct ec_tk *ec_tk_str_new(const char *id)
-{
- struct ec_tk *gen_tk = NULL;
-
- gen_tk = ec_tk_new(id, &ec_tk_str_type, 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;
{
struct ec_tk *gen_tk = NULL;
- gen_tk = ec_tk_str_new(id);
+ gen_tk = __ec_tk_new(&ec_tk_str_type, id);
if (gen_tk == NULL)
goto fail;
}
static struct ec_tk_type ec_tk_subset_type = {
- .name = "tk_subset",
+ .name = "subset",
.parse = ec_tk_subset_parse,
.complete = ec_tk_subset_complete,
+ .size = sizeof(struct ec_tk_subset),
.free_priv = ec_tk_subset_free_priv,
};
EC_TK_TYPE_REGISTER(ec_tk_subset_type);
-struct ec_tk *ec_tk_subset(const char *id)
-{
- struct ec_tk *gen_tk = NULL;
- struct ec_tk_subset *tk = NULL;
-
- gen_tk = ec_tk_new(id, &ec_tk_subset_type, sizeof(*tk));
- if (gen_tk == NULL)
- return NULL;
-
- tk = (struct ec_tk_subset *)gen_tk;
- tk->table = NULL;
- tk->len = 0;
-
- return gen_tk;
-}
-
struct ec_tk *__ec_tk_subset(const char *id, ...)
{
struct ec_tk *gen_tk = NULL;
va_start(ap, id);
- gen_tk = ec_tk_subset(id);
+ gen_tk = __ec_tk_new(&ec_tk_subset_type, id);
tk = (struct ec_tk_subset *)gen_tk;
if (tk == NULL)
fail = 1;;
.name = "weakref",
.parse = ec_tk_weakref_parse,
.complete = ec_tk_weakref_complete,
+ .size = sizeof(struct ec_tk_weakref),
};
EC_TK_TYPE_REGISTER(ec_tk_weakref_type);
-struct ec_tk *ec_tk_weakref_empty(const char *id)
-{
- struct ec_tk_weakref *tk = NULL;
-
- tk = (struct ec_tk_weakref *)ec_tk_new(id,
- &ec_tk_weakref_type, sizeof(*tk));
- if (tk == NULL)
- return NULL;
-
- tk->child = NULL;
-
- return &tk->gen;
-}
-
int ec_tk_weakref_set(struct ec_tk *gen_tk, struct ec_tk *child)
{
struct ec_tk_weakref *tk = (struct ec_tk_weakref *)gen_tk;
if (child == NULL)
return NULL;
- gen_tk = ec_tk_weakref_empty(id);
+ gen_tk = __ec_tk_new(&ec_tk_weakref_type, id);
if (gen_tk == NULL)
return NULL;
{
struct ec_tk *cmdlist = NULL, *cmd = NULL;
- cmdlist = ec_tk_or(NULL);
+ cmdlist = ec_tk_new("or", NULL);
if (cmdlist == NULL)
goto fail;
=======
- check XXX in code
-- remove the _new() functions
+X remove the _new() functions
- add a tk vector type: will be used in several nodes (ex: or, seq, ...)
- check allocation model everywhere
- checkpatch?
- use linux style (update .emacs)
- better logs
- return values
+- use errno when returning pointers
- missing static / const
- license: "s/neither the name...may/the names of its contributors may not/"
- check all completion nodes
- split ecoli_tk.h
- cache results when appropriate?
- size_t or unsigned int?
+- rename:
+ - ec_tk -> ec_node
+ - ec_parsed_tk -> ec_parsed
+ - ec_completed_tk -> ec_completed
+ - tk, gen_tk, token, ... -> node
+ - tokens -> input_str / input_strvec ?
logs
====