set() can unset now

Fixing two bugs with this commit.
This commit is contained in:
Přemysl Eric Janouch 2017-05-21 09:03:57 +02:00
parent 706f452d9d
commit 1caec277bf
Signed by: p
GPG Key ID: B715679E3A361BE6
1 changed files with 27 additions and 21 deletions

48
ell.c
View File

@ -694,21 +694,24 @@ get (struct context *ctx, const char *name) {
static bool static bool
set (struct context *ctx, const char *name, struct item *value) { set (struct context *ctx, const char *name, struct item *value) {
struct item *iter, *key, *pair; struct item **p;
for (iter = ctx->variables; iter; iter = iter->next) for (p = &ctx->variables; *p; p = &(*p)->next)
if (!strcmp (iter->head->value, name)) if (!strcmp ((*p)->head->value, name)) {
struct item *tmp = *p;
*p = (*p)->next;
item_free (tmp);
break; break;
if (iter) { }
item_free (iter->head->next); if (!value)
return check (ctx, (iter->head->next = new_clone (value))); return true;
}
struct item *key, *pair;
if (!check (ctx, (key = new_string (name, strlen (name)))) if (!check (ctx, (key = new_string (name, strlen (name))))
|| !check (ctx, (pair = new_list (key)))) || !check (ctx, (pair = new_list (key)))) {
return false; item_free_list (value);
if (!check (ctx, (key->next = new_clone (value)))) {
item_free (pair);
return false; return false;
} }
key->next = value;
pair->next = ctx->variables; pair->next = ctx->variables;
ctx->variables = pair; ctx->variables = pair;
return true; return true;
@ -731,16 +734,14 @@ static bool
rename_arguments (struct context *ctx, struct item *names) { rename_arguments (struct context *ctx, struct item *names) {
size_t i = 0; size_t i = 0;
for (; names; names = names->next) { for (; names; names = names->next) {
if (names->type != ITEM_STRING)
return set_error (ctx, "argument names must be strings");
char buf[64]; char buf[64];
(void) snprintf (buf, sizeof buf, "%zu", i++); (void) snprintf (buf, sizeof buf, "%zu", i++);
struct item *value = get (ctx, buf); struct item *value = get (ctx, buf);
if (value && !check (ctx, (value = new_clone (value))))
// TODO: set to some sort of nil value? return false;
if (!value)
return true;
if (names->type != ITEM_STRING)
return set_error (ctx, "argument names must be strings");
if (!set (ctx, names->value, value)) if (!set (ctx, names->value, value))
return false; return false;
} }
@ -770,7 +771,8 @@ static bool
set_arg (struct context *ctx, size_t arg, struct item *value) { set_arg (struct context *ctx, size_t arg, struct item *value) {
char buf[64]; char buf[64];
(void) snprintf (buf, sizeof buf, "%zu", arg); (void) snprintf (buf, sizeof buf, "%zu", arg);
return set (ctx, buf, value); return check (ctx, (value = new_clone (value)))
&& set (ctx, buf, value);
} }
// TODO: we should probably maintain arguments in a separate list, // TODO: we should probably maintain arguments in a separate list,
@ -896,7 +898,8 @@ defn (fn_set) {
struct item *value; struct item *value;
if ((value = name->next)) if ((value = name->next))
return set (ctx, name->value, value); return check (ctx, (value = new_clone (value)))
&& set (ctx, name->value, value);
// We return an empty list for a nil value // We return an empty list for a nil value
if (!(value = get (ctx, name->value))) if (!(value = get (ctx, name->value)))
@ -1091,8 +1094,11 @@ init_runtime_library (struct context *ctx) {
printf ("error parsing internal function `%s': %s\n", printf ("error parsing internal function `%s': %s\n",
functions[i].name, e); functions[i].name, e);
ok = false; ok = false;
} else if (!check (ctx, (body = new_list (body)))
|| !set (ctx, functions[i].name, body)) {
ok = false;
} else } else
ok &= set (ctx, functions[i].name, body); body = NULL;
item_free_list (body); item_free_list (body);
parser_free (&parser); parser_free (&parser);
} }