summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--args.c78
-rw-r--r--args.h83
3 files changed, 162 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 1f17291b..016a9c0b 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ EXTRA_OBJS-y :=
OBJS := txr.o lex.yy.o y.tab.o match.o lib.o regex.o gc.o unwind.o stream.o
OBJS += arith.o hash.o utf8.o filter.o eval.o parser.o rand.o combi.o sysif.o
-OBJS += lisplib.o cadr.o
+OBJS += args.o lisplib.o cadr.o
OBJS-$(debug_support) += debug.o
OBJS-$(have_syslog) += syslog.o
OBJS-$(have_glob) += glob.o
diff --git a/args.c b/args.c
new file mode 100644
index 00000000..03a3686f
--- /dev/null
+++ b/args.c
@@ -0,0 +1,78 @@
+/* Copyright 2009-2015
+ * Kaz Kylheku <kaz@kylheku.com>
+ * Vancouver, Canada
+ * All rights reserved.
+ *
+ * Redistribution of this software in source and binary forms, with or without
+ * modification, is permitted provided that the following two conditions are met.
+ *
+ * Use of this software in any manner constitutes agreement with the disclaimer
+ * which follows the two conditions.
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DAMAGES, HOWEVER CAUSED,
+ * AND UNDER ANY THEORY OF LIABILITY, ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <setjmp.h>
+#include <signal.h>
+#include "config.h"
+#include "lib.h"
+#include "signal.h"
+#include "unwind.h"
+#include ALLOCA_H
+#include "args.h"
+
+val args_cons_list(struct args *args);
+
+cnum args_limit(val name, cnum in)
+{
+ if (in <= ARGS_MAX)
+ return in;
+ uw_throwf(assert_s, lit("~a: too many trailing arguments (limit is ~s)"),
+ name, num(ARGS_MAX), nao);
+}
+
+void args_add_list(struct args *args, val list)
+{
+ for (; list; list = cdr(list))
+ args_add(args, car(list));
+}
+
+val args_add_checked(val name, struct args *args, val arg)
+{
+ if (args->fill >= args->argc)
+ uw_throwf(assert_s, lit("~a: argument list size exceeded"), name, nao);
+ return args_add(args, arg);
+}
+
+val args_cons_list(struct args *args)
+{
+ cnum i;
+ list_collect_decl (out, ptail);
+
+ for (i = 0; i < args->argc; i++)
+ ptail = list_collect(ptail, args->arg[i]);
+
+ return args->list = out;
+}
+
+val args_get_checked(val name, struct args *args, cnum *arg_index)
+{
+ if (args->fill == 0 && args->list)
+ args_add_list(args, args->list);
+ if (*arg_index >= args->fill)
+ uw_throwf(assert_s, lit("~a: insufficient arguments"), name, nao);
+ return args_get(args, arg_index);
+}
diff --git a/args.h b/args.h
new file mode 100644
index 00000000..e748bb71
--- /dev/null
+++ b/args.h
@@ -0,0 +1,83 @@
+/* Copyright 2009-2015
+ * Kaz Kylheku <kaz@kylheku.com>
+ * Vancouver, Canada
+ * All rights reserved.
+ *
+ * Redistribution of this software in source and binary forms, with or without
+ * modification, is permitted provided that the following two conditions are met.
+ *
+ * Use of this software in any manner constitutes agreement with the disclaimer
+ * which follows the two conditions.
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DAMAGES, HOWEVER CAUSED,
+ * AND UNDER ANY THEORY OF LIABILITY, ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct args {
+ cnum argc;
+ cnum fill;
+ val list;
+ val arg[1];
+};
+
+typedef int arg_index;
+
+#define ARGS_MAX 1024
+
+#define args_alloc(N) \
+ (coerce(struct args *, \
+ alloca(offsetof(struct args, arg) + (N)*sizeof (val))))
+
+cnum args_limit(val name, cnum in);
+
+INLINE void args_init(struct args *args, cnum argc)
+{
+ args->argc = argc;
+ args->fill = 0;
+ args->list = nil;
+}
+
+INLINE void args_init_list(struct args *args, cnum argc, val list)
+{
+ args->argc = argc;
+ args->fill = 0;
+ args->list = list;
+}
+
+INLINE val args_add(struct args *args, val arg)
+{
+ return args->arg[args->fill++] = arg;
+}
+
+void args_add_list(struct args *args, val list);
+
+val args_add_checked(val name, struct args *args, val arg);
+
+INLINE int args_more(struct args *args, cnum index)
+{
+ return index < args->fill;
+}
+
+INLINE val args_get_list(struct args *args)
+{
+ extern val args_cons_list(struct args *args);
+ return (args->fill == 0 || args->list) ? args->list : args_cons_list(args);
+}
+
+INLINE val args_get(struct args *args, cnum *arg_index)
+{
+ return args->arg[(*arg_index)++];
+}
+
+val args_get_checked(val name, struct args *args, cnum *arg_index);