Copy and free funcall tokens

Again, even though there is not as of yet any way to create them
This commit is contained in:
Glen Whitney 2019-08-04 10:39:20 -04:00
parent d6b4adfc8c
commit b0e989d848
1 changed files with 51 additions and 21 deletions

View File

@ -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;
}
}
/*}}}*/