From 76148a8ca8e948ef166243084b5f291c43456e3e Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Thu, 12 Jan 2017 20:24:49 +0100 Subject: [PATCH] save --- lib/Makefile | 2 +- lib/ecoli_tk.c | 2 + lib/ecoli_tk_bypass.c | 184 ++++++++++++++++++++++++++++++++++++++++++ lib/ecoli_tk_bypass.h | 74 +++++++++++++++++ lib/ecoli_tk_expr.c | 137 ++++++++++++++++++++++++------- lib/ecoli_tk_or.c | 12 ++- lib/ecoli_tk_or.h | 3 + lib/ecoli_tk_seq.c | 12 ++- lib/ecoli_tk_seq.h | 5 +- lib/main-readline.c | 1 - 10 files changed, 394 insertions(+), 38 deletions(-) create mode 100644 lib/ecoli_tk_bypass.c create mode 100644 lib/ecoli_tk_bypass.h diff --git a/lib/Makefile b/lib/Makefile index ba88840..ba852eb 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -39,7 +39,7 @@ srcs += ecoli_tk_str.c ecoli_tk_seq.c srcs += ecoli_tk_space.c ecoli_tk_or.c ecoli_test.c srcs += ecoli_tk_empty.c ecoli_tk_int.c srcs += ecoli_tk_option.c ecoli_tk_many.c -srcs += ecoli_tk_shlex.c ecoli_tk_expr.c +srcs += ecoli_tk_shlex.c ecoli_tk_expr.c ecoli_tk_bypass.c shlib-y-$(O)libecoli.so := $(srcs) ldflags-$(O)test = -rdynamic diff --git a/lib/ecoli_tk.c b/lib/ecoli_tk.c index db28b53..615ed85 100644 --- a/lib/ecoli_tk.c +++ b/lib/ecoli_tk.c @@ -79,6 +79,8 @@ void ec_tk_free(struct ec_tk *tk) if (tk == NULL) return; + assert(tk->refcnt > 0); + if (--tk->refcnt > 0) return; diff --git a/lib/ecoli_tk_bypass.c b/lib/ecoli_tk_bypass.c new file mode 100644 index 0000000..d2fe401 --- /dev/null +++ b/lib/ecoli_tk_bypass.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct ec_tk_bypass { + struct ec_tk gen; + struct ec_tk *child; +}; + +static struct ec_parsed_tk *ec_tk_bypass_parse(const struct ec_tk *gen_tk, + const struct ec_strvec *strvec) +{ + struct ec_tk_bypass *tk = (struct ec_tk_bypass *)gen_tk; + + return ec_tk_parse_tokens(tk->child, strvec); +} + +static struct ec_completed_tk *ec_tk_bypass_complete(const struct ec_tk *gen_tk, + const struct ec_strvec *strvec) +{ + struct ec_tk_bypass *tk = (struct ec_tk_bypass *)gen_tk; + + return ec_tk_complete_tokens(tk->child, strvec); +} + +static void ec_tk_bypass_free_priv(struct ec_tk *gen_tk) +{ + struct ec_tk_bypass *tk = (struct ec_tk_bypass *)gen_tk; + + ec_tk_free(tk->child); +} + +static struct ec_tk_ops ec_tk_bypass_ops = { + .typename = "bypass", + .parse = ec_tk_bypass_parse, + .complete = ec_tk_bypass_complete, + .free_priv = ec_tk_bypass_free_priv, +}; + +struct ec_tk *ec_tk_bypass_new(const char *id) +{ + struct ec_tk_bypass *tk = NULL; + + tk = (struct ec_tk_bypass *)ec_tk_new(id, + &ec_tk_bypass_ops, sizeof(*tk)); + if (tk == NULL) + return NULL; + + tk->child = NULL; + + return &tk->gen; +} + +int ec_tk_bypass_set(struct ec_tk *gen_tk, struct ec_tk *child) +{ + struct ec_tk_bypass *tk = (struct ec_tk_bypass *)gen_tk; + + // XXX check tk type + + assert(tk != NULL); + + if (child == NULL) + return -EINVAL; + + if (gen_tk->flags & EC_TK_F_INITIALIZED) { + ec_tk_free(child); + return -EPERM; + } + + tk->child = child; + + child->parent = gen_tk; + TAILQ_INSERT_TAIL(&gen_tk->children, child, next); // XXX really needed? + + return 0; +} + +struct ec_tk *ec_tk_bypass_pop(struct ec_tk *gen_tk) +{ + struct ec_tk_bypass *tk = (struct ec_tk_bypass *)gen_tk; + struct ec_tk *child; + + if (gen_tk->flags & EC_TK_F_INITIALIZED) + return NULL; + + child = tk->child; + tk->child = NULL; + + return child; +} + +int ec_tk_bypass_start(struct ec_tk *gen_tk) +{ + struct ec_tk_bypass *tk = (struct ec_tk_bypass *)gen_tk; + + if (gen_tk->flags & EC_TK_F_INITIALIZED) + return -EPERM; + if (tk->child == NULL) + return -EINVAL; + + gen_tk->flags |= EC_TK_F_INITIALIZED; + + return 0; +} + +int ec_tk_bypass_stop(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_bypass(const char *id, struct ec_tk *child) +{ + struct ec_tk *gen_tk = NULL; + + if (child == NULL) + return NULL; + + gen_tk = ec_tk_bypass_new(id); + if (gen_tk == NULL) { + ec_tk_free(child); + return NULL; + } + + ec_tk_bypass_set(gen_tk, child); + ec_tk_bypass_start(gen_tk); + + return gen_tk; +} + +static int ec_tk_bypass_testcase(void) +{ + return 0; +} + +static struct ec_test ec_tk_bypass_test = { + .name = "tk_bypass", + .test = ec_tk_bypass_testcase, +}; + +EC_REGISTER_TEST(ec_tk_bypass_test); diff --git a/lib/ecoli_tk_bypass.h b/lib/ecoli_tk_bypass.h new file mode 100644 index 0000000..c20064a --- /dev/null +++ b/lib/ecoli_tk_bypass.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TK_BYPASS_ +#define ECOLI_TK_BYPASS_ + +#include + +/// XXX rename in loop ? +// XXX + provide the helper to free ? + +/* a tk that just behaves like its child + * useful to create cyclic graphs of tokens: + * creating a loop (with clones) result in something that is not + * freeable, due to reference counters + * bypass node can solve the issue: before freeing the graph, + * the loop can be cut, falling back to a valid tree that can + * be freed. + * + * Example: + * seq = seq() + * i = int() + * seq_add(seq, i) + * seq_add(seq, clone(seq)) + * FAIL, cannot be freed + * + * seq = seq() + * bypass = bypass(clone(seq)) + * i = int() + * seq_add(seq, i) + * seq_add(seq, bypass) + * + * TO FREE: + * seq2 = bypass_del(bypass) // breaks the loop (seq2 == seq) + * free(bypass) + * free(seq2) + * free(seq) + */ + +struct ec_tk *ec_tk_bypass(const char *id, struct ec_tk *child); + +struct ec_tk *ec_tk_bypass_new(const char *id); + +/* child is consumed */ +/* all token given in the list will be freed when freeing this one */ +int ec_tk_bypass_set(struct ec_tk *tk, struct ec_tk *child); + +struct ec_tk *ec_tk_bypass_pop(struct ec_tk *gen_tk); + +#endif diff --git a/lib/ecoli_tk_expr.c b/lib/ecoli_tk_expr.c index 2117d36..fe1b23f 100644 --- a/lib/ecoli_tk_expr.c +++ b/lib/ecoli_tk_expr.c @@ -44,6 +44,7 @@ #include #include #include +#include struct ec_tk_expr { struct ec_tk gen; @@ -83,8 +84,21 @@ static struct ec_completed_tk *ec_tk_expr_complete(const struct ec_tk *gen_tk, static void ec_tk_expr_free_priv(struct ec_tk *gen_tk) { struct ec_tk_expr *tk = (struct ec_tk_expr *)gen_tk; + unsigned int i; ec_tk_free(tk->child); + ec_tk_free(tk->val_tk); + + for (i = 0; i < tk->bin_ops_len; i++) + ec_tk_free(tk->bin_ops[i]); + for (i = 0; i < tk->pre_ops_len; i++) + ec_tk_free(tk->pre_ops[i]); + for (i = 0; i < tk->post_ops_len; i++) + ec_tk_free(tk->post_ops[i]); + for (i = 0; i < tk->paren_len; i++) { + ec_tk_free(tk->open_ops[i]); + ec_tk_free(tk->close_ops[i]); + } } static struct ec_tk_ops ec_tk_expr_ops = { @@ -228,7 +242,7 @@ 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, + *pre_op = NULL, *post_op = NULL, *post = NULL, *final = NULL, *next = NULL; unsigned int i; @@ -242,9 +256,7 @@ int ec_tk_expr_start(struct ec_tk *gen_tk) /* 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); + expr = ec_tk_bypass_new("expr"); /* prefix unary operators */ pre_op = ec_tk_or_new("pre-op"); @@ -265,7 +277,7 @@ int ec_tk_expr_start(struct ec_tk *gen_tk) goto fail; term = ec_tk_or_new("term"); - if (ec_tk_or_add(term, ec_tk_clone(val)) < 0) + if (ec_tk_or_add(term, ec_tk_clone(tk->val_tk)) < 0) goto fail; if (ec_tk_or_add(term, ec_tk_seq(NULL, @@ -306,25 +318,43 @@ int ec_tk_expr_start(struct ec_tk *gen_tk) EC_TK_ENDLIST ); - tk->child = final; + /* free the initial references */ + ec_tk_free(pre_op); + pre_op = NULL; + ec_tk_free(post_op); + post_op = NULL; + ec_tk_free(term); + term = NULL; + ec_tk_free(post); + post = NULL; + + if (ec_tk_bypass_set(expr, ec_tk_clone(final)) < 0) + goto fail; + + ec_tk_free(final); + final = NULL; + + tk->child = expr; gen_tk->flags |= EC_TK_F_INITIALIZED; return 0; fail: - ec_tk_free(val); + ec_tk_free(term); + ec_tk_free(expr); ec_tk_free(pre_op); ec_tk_free(post_op); - ec_tk_free(term); ec_tk_free(post); + ec_tk_free(final); + return -1; } -static int ec_tk_expr_testcase(void) +static int ec_tk_expr_testcase_manual(void) { - struct ec_tk *term, *factor, *expr, *tk, *val, - *pre_op, *post_op, *post, *final; + struct ec_tk *term = NULL, *factor = NULL, *expr = NULL, *val = NULL, + *pre_op = NULL, *post_op = NULL, *post = NULL, *final = NULL; int ret = 0; // XXX check all APIs: pointers are "moved", they are freed by @@ -335,24 +365,28 @@ static int ec_tk_expr_testcase(void) /* 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); + ec_log(EC_LOG_INFO, "%d\n", __LINE__); + expr = ec_tk_bypass_new("expr"); + ec_log(EC_LOG_INFO, "%d\n", __LINE__); /* reverse bits */ pre_op = ec_tk_or("pre-op", ec_tk_str(NULL, "~"), EC_TK_ENDLIST ); + ec_log(EC_LOG_INFO, "%d\n", __LINE__); /* factorial */ post_op = ec_tk_or("post-op", ec_tk_str(NULL, "!"), EC_TK_ENDLIST ); + ec_log(EC_LOG_INFO, "%d\n", __LINE__); + val = ec_tk_int("val", 0, UCHAR_MAX, 0); + ec_log(EC_LOG_INFO, "%d\n", __LINE__); term = ec_tk_or("term", - ec_tk_clone(val), + val, ec_tk_seq(NULL, ec_tk_str(NULL, "("), ec_tk_clone(expr), @@ -366,6 +400,9 @@ static int ec_tk_expr_testcase(void) ), EC_TK_ENDLIST ); + val = NULL; + + ec_log(EC_LOG_INFO, "%d\n", __LINE__); factor = ec_tk_seq("factor", ec_tk_clone(term), @@ -393,27 +430,35 @@ static int ec_tk_expr_testcase(void) EC_TK_ENDLIST ); + ec_log(EC_LOG_INFO, "%d\n", __LINE__); final = ec_tk_seq("final", ec_tk_clone(post), ec_tk_many_new(NULL, ec_tk_clone(post_op), 0, 0), EC_TK_ENDLIST ); + ec_log(EC_LOG_INFO, "%d\n", __LINE__); /* free the initial references */ - ec_tk_free(val); ec_tk_free(pre_op); + pre_op = NULL; ec_tk_free(post_op); + post_op = NULL; ec_tk_free(term); + term = NULL; ec_tk_free(factor); + factor = NULL; ec_tk_free(post); + post = NULL; - if (ec_tk_seq_add(expr, ec_tk_clone(final)) < 0) { - ec_tk_free(final); - ec_tk_free(expr); - return -1; - } + ec_log(EC_LOG_INFO, "%d\n", __LINE__); + if (ec_tk_bypass_set(expr, ec_tk_clone(final)) < 0) + goto fail; + ec_log(EC_LOG_INFO, "%d\n", __LINE__); ec_tk_free(final); + final = NULL; + + ec_log(EC_LOG_INFO, "%d\n", __LINE__); ret |= EC_TEST_CHECK_TK_PARSE(expr, 1, "1", EC_TK_ENDLIST); ret |= EC_TEST_CHECK_TK_PARSE(expr, 1, "1", "*", EC_TK_ENDLIST); @@ -427,7 +472,41 @@ static int ec_tk_expr_testcase(void) ret |= EC_TEST_CHECK_TK_PARSE(expr, 4, "1", "+", "~", "1", EC_TK_ENDLIST); + final = ec_tk_bypass_pop(expr); ec_tk_free(expr); + ec_tk_free(final); + + return ret; + +fail: + ec_log(EC_LOG_INFO, "%d term %p\n", __LINE__, term); + ec_tk_free(term); + ec_log(EC_LOG_INFO, "%d factor %p\n", __LINE__, factor); + ec_tk_free(factor); + ec_log(EC_LOG_INFO, "%d expr %p\n", __LINE__, expr); + ec_tk_free(expr); + ec_log(EC_LOG_INFO, "%d val %p\n", __LINE__, val); + ec_tk_free(val); + ec_log(EC_LOG_INFO, "%d pre_op %p\n", __LINE__, pre_op); + ec_tk_free(pre_op); + ec_log(EC_LOG_INFO, "%d post_op %p\n", __LINE__, post_op); + ec_tk_free(post_op); + ec_log(EC_LOG_INFO, "%d post %p\n", __LINE__, post); + ec_tk_free(post); + ec_log(EC_LOG_INFO, "%d final %p\n", __LINE__, final); + ec_tk_free(final); + ec_log(EC_LOG_INFO, "%d\n", __LINE__); + return 0; +} + +static int ec_tk_expr_testcase(void) +{ + struct ec_tk *tk; + int ret; + + ret = ec_tk_expr_testcase_manual(); + if (ret < 0) + return ret; tk = ec_tk_expr_new(NULL); ec_tk_expr_set_val_tk(tk, ec_tk_int(NULL, 0, UCHAR_MAX, 0)); @@ -437,18 +516,18 @@ static int ec_tk_expr_testcase(void) 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); + ec_tk_expr_start(tk); // XXX start -> commit ? - 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", + ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "1", EC_TK_ENDLIST); + ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "1", "*", EC_TK_ENDLIST); + ret |= EC_TEST_CHECK_TK_PARSE(tk, 3, "1", "*", "1", EC_TK_ENDLIST); + ret |= EC_TEST_CHECK_TK_PARSE(tk, 3, "1", "+", "1", EC_TK_ENDLIST); + ret |= EC_TEST_CHECK_TK_PARSE(tk, 5, "1", "*", "1", "+", "1", EC_TK_ENDLIST); ret |= EC_TEST_CHECK_TK_PARSE( - expr, 10, "~", "(", "1", "*", "(", "1", "+", "1", ")", ")", + tk, 10, "~", "(", "1", "*", "(", "1", "+", "1", ")", ")", EC_TK_ENDLIST); - ret |= EC_TEST_CHECK_TK_PARSE(expr, 4, "1", "+", "~", "1", + ret |= EC_TEST_CHECK_TK_PARSE(tk, 4, "1", "+", "~", "1", EC_TK_ENDLIST); ec_tk_free(tk); diff --git a/lib/ecoli_tk_or.c b/lib/ecoli_tk_or.c index d3e2d20..04701e6 100644 --- a/lib/ecoli_tk_or.c +++ b/lib/ecoli_tk_or.c @@ -148,14 +148,20 @@ int ec_tk_or_add(struct ec_tk *gen_tk, struct ec_tk *child) struct ec_tk **table; assert(tk != NULL); - assert(child != NULL); - if (gen_tk->flags & EC_TK_F_INITIALIZED) + if (child == NULL) + return -EINVAL; + + if (gen_tk->flags & EC_TK_F_INITIALIZED) { + ec_tk_free(child); return -EPERM; + } table = ec_realloc(tk->table, (tk->len + 1) * sizeof(*tk->table)); - if (table == NULL) + if (table == NULL) { + ec_tk_free(child); return -1; + } tk->table = table; table[tk->len] = child; diff --git a/lib/ecoli_tk_or.h b/lib/ecoli_tk_or.h index e11d96b..6f11735 100644 --- a/lib/ecoli_tk_or.h +++ b/lib/ecoli_tk_or.h @@ -35,8 +35,11 @@ struct ec_tk *ec_tk_or(const char *id, ...); struct ec_tk *ec_tk_or_new(const char *id); + +/* child is consumed */ /* 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 diff --git a/lib/ecoli_tk_seq.c b/lib/ecoli_tk_seq.c index 3cfc061..889ea34 100644 --- a/lib/ecoli_tk_seq.c +++ b/lib/ecoli_tk_seq.c @@ -191,14 +191,20 @@ int ec_tk_seq_add(struct ec_tk *gen_tk, struct ec_tk *child) // XXX check tk type assert(tk != NULL); - assert(child != NULL); - if (gen_tk->flags & EC_TK_F_INITIALIZED) + if (child == NULL) + return -EINVAL; + + if (gen_tk->flags & EC_TK_F_INITIALIZED) { + ec_tk_free(child); return -EPERM; + } table = ec_realloc(tk->table, (tk->len + 1) * sizeof(*tk->table)); - if (table == NULL) + if (table == NULL) { + ec_tk_free(child); return -1; + } tk->table = table; table[tk->len] = child; diff --git a/lib/ecoli_tk_seq.h b/lib/ecoli_tk_seq.h index 03c5834..5340fbf 100644 --- a/lib/ecoli_tk_seq.h +++ b/lib/ecoli_tk_seq.h @@ -35,8 +35,11 @@ struct ec_tk *ec_tk_seq(const char *id, ...); struct ec_tk *ec_tk_seq_new(const char *id); + +/* child is consumed */ +/* all token given in the list will be freed when freeing this one */ int ec_tk_seq_add(struct ec_tk *tk, struct ec_tk *child); -int ec_tk_seq_start(struct ec_tk *tk); +int ec_tk_seq_start(struct ec_tk *tk); #endif diff --git a/lib/main-readline.c b/lib/main-readline.c index 7432f3c..db1574e 100644 --- a/lib/main-readline.c +++ b/lib/main-readline.c @@ -213,7 +213,6 @@ static int create_commands(void) fail: fprintf(stderr, "cannot initialize tokens\n"); - ec_tk_free(cmd); ec_tk_free(cmdlist); return -1; } -- 2.39.5