+
+#define GSUBR_ARGS_1(f) f (arg1)
+#define GSUBR_ARGS_2(f) GSUBR_ARGS_1 (f), f (arg2)
+#define GSUBR_ARGS_3(f) GSUBR_ARGS_2 (f), f (arg3)
+#define GSUBR_ARGS_4(f) GSUBR_ARGS_3 (f), f (arg4)
+#define GSUBR_ARGS_5(f) GSUBR_ARGS_4 (f), f (arg5)
+#define GSUBR_ARGS_6(f) GSUBR_ARGS_5 (f), f (arg6)
+#define GSUBR_ARGS_7(f) GSUBR_ARGS_6 (f), f (arg7)
+#define GSUBR_ARGS_8(f) GSUBR_ARGS_7 (f), f (arg8)
+
+#define GSUBR_ARGS(n) GSUBR_ARGS_PASTE (GSUBR_ARGS_, n)
+#define GSUBR_ARGS_PASTE(a, b) a ## b
+
+#define DEFUN_GSUBR_N(fn, maxargs) \
+ Lisp_Object \
+ gsubr_ ## fn \
+ (GSUBR_ARGS (maxargs) (Lisp_Object)) \
+ { \
+ return fn (GSUBR_ARGS (maxargs) (GSUBR_ARG)); \
+ }
+#define GSUBR_ARG(x) (SCM_UNBNDP (x) ? Qnil : x)
+
+#define DEFUN_GSUBR_0(lname, fn, minargs, maxargs) \
+ Lisp_Object gsubr_ ## fn (void) { return fn (); }
+#define DEFUN_GSUBR_1(lname, fn, min, max) DEFUN_GSUBR_N(fn, max)
+#define DEFUN_GSUBR_2(lname, fn, min, max) DEFUN_GSUBR_N(fn, max)
+#define DEFUN_GSUBR_3(lname, fn, min, max) DEFUN_GSUBR_N(fn, max)
+#define DEFUN_GSUBR_4(lname, fn, min, max) DEFUN_GSUBR_N(fn, max)
+#define DEFUN_GSUBR_5(lname, fn, min, max) DEFUN_GSUBR_N(fn, max)
+#define DEFUN_GSUBR_6(lname, fn, min, max) DEFUN_GSUBR_N(fn, max)
+#define DEFUN_GSUBR_7(lname, fn, min, max) DEFUN_GSUBR_N(fn, max)
+#define DEFUN_GSUBR_8(lname, fn, min, max) DEFUN_GSUBR_N(fn, max)
+
+#define DEFUN_GSUBR_UNEVALLED(lname, fn, minargs, maxargs) \
+ Lisp_Object \
+ gsubr_ ## fn (Lisp_Object rest) \
+ { \
+ Lisp_Object len = Flength (rest); \
+ if (XINT (len) < minargs) \
+ xsignal2 (Qwrong_number_of_arguments, \
+ intern (lname), len); \
+ return fn (rest); \
+ }
+#define DEFUN_GSUBR_MANY(lname, fn, minargs, maxargs) \
+ Lisp_Object \
+ gsubr_ ## fn (Lisp_Object rest) \
+ { \
+ int len = scm_to_int (scm_length (rest)); \
+ Lisp_Object *args; \
+ SAFE_ALLOCA_LISP (args, len); \
+ int i; \
+ for (i = 0; \
+ i < len && scm_is_pair (rest); \
+ i++, rest = SCM_CDR (rest)) \
+ args[i] = SCM_CAR (rest); \
+ if (i < minargs) \
+ xsignal2 (Qwrong_number_of_arguments, \
+ intern (lname), make_number (i)); \
+ return fn (i, args); \
+ }