This rewrites proc to always take 3 arguments. It also adds proper error
handling. TCL does not allow for anonymous functions to be created with
proc. Allowing for a variable number of arguments makes the code much more
complex when adding error handling.

Since fnc_proc was the last user of lil_unused_name (other than
fnc_unusedname), remove it.

Signed-off-by: Sean Anderson <sean...@gmail.com>
---

 common/cli_lil.c | 103 ++++++++++++++++-------------------------------
 test/cmd/lil.c   |   6 ++-
 2 files changed, 38 insertions(+), 71 deletions(-)

diff --git a/common/cli_lil.c b/common/cli_lil.c
index 7ec73675f3..1c7c340bda 100644
--- a/common/cli_lil.c
+++ b/common/cli_lil.c
@@ -2985,32 +2985,6 @@ struct lil_value *lil_eval_expr(struct lil *lil, struct 
lil_value *code)
        return lil_alloc_integer(ee.ival);
 }
 
-struct lil_value *lil_unused_name(struct lil *lil, const char *part)
-{
-       char *name = malloc(strlen(part) + 64);
-       struct lil_value *val;
-       size_t i;
-
-       for (i = 0; i < (size_t)-1; i++) {
-               sprintf(name, "!!un!%s!%09u!nu!!", part, (unsigned int)i);
-               if (lil_find_cmd(lil, name))
-                       continue;
-
-               if (lil_find_var(lil, lil->env, name))
-                       continue;
-
-               val = lil_alloc_string(name);
-               free(name);
-               return val;
-       }
-       return NULL;
-}
-
-struct lil_value *lil_arg(struct lil_value **argv, size_t index)
-{
-       return argv ? argv[index] : NULL;
-}
-
 const char *lil_to_string(struct lil_value *val)
 {
        return (val && val->l) ? val->d : "";
@@ -3237,47 +3211,46 @@ static struct lil_value *fnc_reflect(struct lil *lil, 
size_t argc,
 static struct lil_value *fnc_proc(struct lil *lil, size_t argc,
                                  struct lil_value **argv)
 {
-       struct lil_value *name;
        struct lil_func *cmd;
-       struct lil_list *fargs;
+       struct lil_list *args;
+       struct lil_value *name, *code;
 
-       if (argc < 1)
+       if (argc != 3) {
+               lil_set_error_argc(lil, 3);
                return NULL;
-
-       if (argc >= 3) {
-               name = lil_clone_value(argv[0]);
-               fargs = lil_subst_to_list(lil, argv[1]);
-               cmd = add_func(lil, lil_to_string(argv[0]));
-               if (!cmd)
-                       return NULL;
-
-               cmd->argnames = fargs;
-               cmd->code = lil_clone_value(argv[2]);
-       } else {
-               name = lil_unused_name(lil, "anonymous-function");
-               if (argc < 2) {
-                       struct lil_value *tmp = lil_alloc_string("args");
-
-                       fargs = lil_subst_to_list(lil, tmp);
-                       lil_free_value(tmp);
-                       cmd = add_func(lil, lil_to_string(name));
-                       if (!cmd)
-                               return NULL;
-
-                       cmd->argnames = fargs;
-                       cmd->code = lil_clone_value(argv[0]);
-               } else {
-                       fargs = lil_subst_to_list(lil, argv[0]);
-                       cmd = add_func(lil, lil_to_string(name));
-                       if (!cmd)
-                               return NULL;
-
-                       cmd->argnames = fargs;
-                       cmd->code = lil_clone_value(argv[1]);
-               }
        }
 
+       name = lil_clone_value(argv[0]);
+       if (!name) {
+               lil_set_error_oom(lil);
+               return NULL;
+       }
+
+       args = lil_subst_to_list(lil, argv[1]);
+       if (!args)
+               goto err_args;
+
+       code = lil_clone_value(argv[2]);
+       if (!code) {
+               lil_set_error_oom(lil);
+               goto err_code;
+       }
+
+       cmd = add_func(lil, lil_to_string(name));
+       if (!cmd)
+               goto err_func;
+       cmd->argnames = args;
+       cmd->code = code;
+
        return name;
+
+err_func:
+       lil_free_value(code);
+err_code:
+       lil_free_list(args);
+err_args:
+       lil_free_value(name);
+       return NULL;
 }
 
 static struct lil_value *fnc_rename(struct lil *lil, size_t argc,
@@ -3312,13 +3285,6 @@ static struct lil_value *fnc_rename(struct lil *lil, 
size_t argc,
        return r;
 }
 
-static struct lil_value *fnc_unusedname(struct lil *lil, size_t argc,
-                                       struct lil_value **argv)
-{
-       return lil_unused_name(lil, argc > 0 ? lil_to_string(argv[0]) :
-                                                    "unusedname");
-}
-
 static struct lil_value *fnc_quote(struct lil *lil, size_t argc,
                                   struct lil_value **argv)
 {
@@ -4310,7 +4276,6 @@ static void register_stdcmds(struct lil *lil)
                lil_register(lil, "substr", fnc_substr);
                lil_register(lil, "topeval", fnc_topeval);
                lil_register(lil, "trim", fnc_trim);
-               lil_register(lil, "unusedname", fnc_unusedname);
                lil_register(lil, "upeval", fnc_upeval);
        }
 }
diff --git a/test/cmd/lil.c b/test/cmd/lil.c
index fb33fa83a6..58bc6ee842 100644
--- a/test/cmd/lil.c
+++ b/test/cmd/lil.c
@@ -149,9 +149,11 @@ static const struct {
                        "[list eh??]"
                "];"
                "asserteq_list [lapply $list length] [list 9 10 4];"
-               "asserteq_list [lapply $list [proc {a} {"
+               "proc firstword {a} {"
                        "return [index [split $a] 0]"
-               "}]] [list {bad's} {good's} eh??]"
+               "};"
+               "asserteq_list [lapply $list firstword] "
+                       "[list {bad's} {good's} eh??]"
        },
        {"lists",
                "set l [list foo bar baz bad];"
-- 
2.32.0

Reply via email to