save
[protos/libecoli.git] / lib / ecoli_tk.c
index fec8492..9d877c0 100644 (file)
@@ -34,6 +34,7 @@
 #include <ecoli_malloc.h>
 #include <ecoli_strvec.h>
 #include <ecoli_keyval.h>
+#include <ecoli_log.h>
 #include <ecoli_tk.h>
 
 struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_ops *ops,
@@ -44,12 +45,15 @@ struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_ops *ops,
 
        assert(size >= sizeof(*tk));
 
+       ec_log(EC_LOG_DEBUG, "create node type=%s id=%s\n", ops->typename, id);
+
        tk = ec_calloc(1, size);
        if (tk == NULL)
                goto fail;
 
        TAILQ_INIT(&tk->children);
        tk->ops = ops;
+       tk->refcnt = 1;
 
        if (id != NULL) {
                tk->id = ec_strdup(id);
@@ -69,9 +73,6 @@ struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_ops *ops,
        return tk;
 
  fail:
-       ec_free(tk->attrs);
-       ec_free(tk->desc);
-       ec_free(tk->id);
        ec_tk_free(tk);
        return NULL;
 }
@@ -81,6 +82,11 @@ void ec_tk_free(struct ec_tk *tk)
        if (tk == NULL)
                return;
 
+       assert(tk->refcnt > 0);
+
+       if (--tk->refcnt > 0)
+               return;
+
        if (tk->ops != NULL && tk->ops->free_priv != NULL)
                tk->ops->free_priv(tk);
        ec_free(tk->id);
@@ -89,6 +95,13 @@ void ec_tk_free(struct ec_tk *tk)
        ec_free(tk);
 }
 
+struct ec_tk *ec_tk_clone(struct ec_tk *tk)
+{
+       if (tk != NULL)
+               tk->refcnt++;
+       return tk;
+}
+
 struct ec_tk *ec_tk_find(struct ec_tk *tk, const char *id)
 {
        struct ec_tk *child, *ret;
@@ -121,7 +134,7 @@ struct ec_tk *ec_tk_parent(const struct ec_tk *tk)
        return tk->parent;
 }
 
-struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *tk, const char *str)
+struct ec_parsed_tk *ec_tk_parse(struct ec_tk *tk, const char *str)
 {
        struct ec_strvec *strvec = NULL;
        struct ec_parsed_tk *parsed_tk;
@@ -146,10 +159,23 @@ struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *tk, const char *str)
        return NULL;
 }
 
-struct ec_parsed_tk *ec_tk_parse_tokens(const struct ec_tk *tk,
+struct ec_parsed_tk *ec_tk_parse_tokens(struct ec_tk *tk,
        const struct ec_strvec *strvec)
 {
        struct ec_parsed_tk *parsed_tk;
+       int ret;
+
+       /* build the node if required */
+       if (tk->ops->build != NULL) {
+               if ((tk->flags & EC_TK_F_BUILT) == 0) {
+                       ret = tk->ops->build(tk);
+                       if (ret < 0) {
+                               errno = -ret;
+                               return NULL;
+                       }
+               }
+       }
+       tk->flags |= EC_TK_F_BUILT;
 
        if (tk->ops->parse == NULL) {
                errno = ENOTSUP;
@@ -213,22 +239,37 @@ static void __ec_parsed_tk_dump(FILE *out,
        const struct ec_parsed_tk *parsed_tk, size_t indent)
 {
        struct ec_parsed_tk *child;
+       const struct ec_strvec *vec;
        size_t i;
-       const char *s, *id = "None", *typename = "None";
-
-       /* XXX enhance */
-       for (i = 0; i < indent; i++)
-               fprintf(out, " ");
+       const char *id = "None", *typename = "None";
 
-       s = ec_parsed_tk_to_string(parsed_tk);
        if (parsed_tk->tk != NULL) {
                if (parsed_tk->tk->id != NULL)
                        id = parsed_tk->tk->id;
                typename = parsed_tk->tk->ops->typename;
        }
 
-       /* XXX we only display the first token */
-       fprintf(out, "tk_type=%s, id=%s, s=<%s>\n", typename, id, s);
+       /* XXX remove this debug hack */
+       if (!strcmp(typename, "str") || !strcmp(typename, "int"))
+               fprintf(out, ">>> ");
+       else
+               fprintf(out, "    ");
+
+       /* XXX enhance */
+       for (i = 0; i < indent; i++) {
+               if (i % 2)
+                       fprintf(out, " ");
+               else
+                       fprintf(out, "|");
+       }
+
+       fprintf(out, "tk_type=%s id=%s vec=[", typename, id);
+       vec = ec_parsed_tk_strvec(parsed_tk);
+       for (i = 0; i < ec_strvec_len(vec); i++)
+               fprintf(out, "%s<%s>",
+                       i == 0 ? "" : ",",
+                       ec_strvec_val(vec, i));
+       fprintf(out, "]\n");
 
        TAILQ_FOREACH(child, &parsed_tk->children, next)
                __ec_parsed_tk_dump(out, child, indent + 2);
@@ -236,6 +277,8 @@ static void __ec_parsed_tk_dump(FILE *out,
 
 void ec_parsed_tk_dump(FILE *out, const struct ec_parsed_tk *parsed_tk)
 {
+       fprintf(out, "------------------- dump:\n");
+
        if (parsed_tk == NULL) {
                fprintf(out, "parsed_tk is NULL, error in parse\n");
                return;
@@ -276,14 +319,13 @@ struct ec_parsed_tk *ec_parsed_tk_find_first(struct ec_parsed_tk *parsed_tk,
        return NULL;
 }
 
-/* XXX return NUL if it matches several tokens?
-   or add a parameter to join() the tokens ? */
-const char *ec_parsed_tk_to_string(const struct ec_parsed_tk *parsed_tk)
+const struct ec_strvec *ec_parsed_tk_strvec(
+       const struct ec_parsed_tk *parsed_tk)
 {
        if (parsed_tk == NULL || parsed_tk->strvec == NULL)
                return NULL;
 
-       return ec_strvec_val(parsed_tk->strvec, 0);
+       return parsed_tk->strvec;
 }
 
 /* number of parsed tokens */