diff --git a/src/common/eval.c b/src/common/eval.c index 86f48be..b3ccbca 100644 --- a/src/common/eval.c +++ b/src/common/eval.c @@ -38,10 +38,21 @@ Token tcopy(Token n) Token result; /*}}}*/ - result=n; - if (result.type==STRING) result.u.string=strcpy(malloc(strlen(n.u.string)+1),n.u.string); - else if (result.type==EEK) result.u.err=strcpy(malloc(strlen(n.u.err)+1),n.u.err); - else if (result.type==LIDENT) result.u.lident=strcpy(malloc(strlen(n.u.lident)+1),n.u.lident); + result = n; + switch (n.type) { + case STRING: result.u.string = strdup(n.u.string); break; + case LIDENT: result.u.lident = strdup(n.u.lident); break; + case FUNCALL: + if (n.u.funcall.argc > 0) + { + result.u.funcall.argv = malloc(n.u.funcall.argc*sizeof(Token)); + for (size_t ai = 0; ai < n.u.funcall.argc; ++ai) + result.u.funcall.argv[ai] = tcopy(n.u.funcall.argv[ai]); + } + break; + case EEK: result.u.err = strdup(n.u.err); break; + default: break; + } return result; } /*}}}*/ @@ -58,23 +69,42 @@ void tfree(Token *n) /* tfree_protected -- free dynamic data of token but not if same as protected */ /*{{{*/ void tfree_protected(Token *n, const Token dontfree) { - if (n->type == STRING && - (dontfree.type != STRING || n->u.string != dontfree.u.string)) - { - free(n->u.string); - n->u.string=(char*)0; - } - else if (n->type == EEK && - (dontfree.type != EEK || n->u.err != dontfree.u.err)) - { - free(n->u.err); - n->u.err=(char*)0; - } - else if (n->type==LIDENT && - (dontfree.type != LIDENT || n->u.lident != dontfree.u.lident)) - { - free(n->u.lident); - n->u.lident=(char*)0; + bool difftype = (dontfree.type != n->type); + switch (n->type) { + case STRING: + if (difftype || n->u.string != dontfree.u.string) + { + free(n->u.string); + n->u.string=(char*)0; + } + break; + case LIDENT: + if (difftype || n->u.lident != dontfree.u.lident) + { + free(n->u.lident); + n->u.lident=(char*)0; + } + break; + case FUNCALL: + if (difftype || n->u.funcall.argv != dontfree.u.funcall.argv) + { + for (int ai = 0; ai < n->u.funcall.argc; ++ai) + tfree_protected(n->u.funcall.argv + ai, dontfree); + if (n->u.funcall.argv != NULLTOKEN) { + free(n->u.funcall.argv); + n->u.funcall.argv = NULLTOKEN; + } + } + break; + case EEK: + if (difftype || n->u.err != dontfree.u.err) + { + free(n->u.err); + n->u.err=(char*)0; + } + break; + default: + break; } } /*}}}*/