Commit Diff


commit - 5de2d36f1a5eb853fde34fb18b57bca902f17362
commit + 0e62706aed4499a4b0bc7b0f349b851d9d9eb104
blob - 8735f24bd0c12b7159d6687776b08f688c2197e7
blob + 3207aba3d37bbaa7e4064702c8554c2e3bf328c2
--- np.y
+++ np.y
@@ -206,10 +206,14 @@ funcall	: procname {
 	;
 
 optcomma: /* empty */ | ',' ;
+
+dots	: '.' '.' '.' ;
 
 args	: /* empty */
 	| args ',' expr	{ push_arg($3); }
+	| args ',' dots	{ push_arg(op_rest()); }
 	| expr		{ push_arg($1); }
+	| dots		{ push_arg(op_rest()); }
 	;
 
 proc	: PROC SYMBOL {
blob - 5bb65d30e98066b8b74e712420d77168aaa25689
blob + 69dbdc54ccd1194af8b5463ab94cc061aef8a661
--- script.c
+++ script.c
@@ -278,6 +278,12 @@ free_op(struct op *op)
 {
 	/* TODO: probably more... */
 	free(op);
+}
+
+struct op *
+op_rest(void)
+{
+	return newop(OP_REST);
 }
 
 struct op *
@@ -505,6 +511,9 @@ pp_op(struct op *op)
 	struct op	*aux;
 
 	switch (op->type) {
+	case OP_REST:
+		printf("...");
+		break;
 	case OP_ASSIGN:
 		printf("%s = ", op->v.assign.name);
                 pp_op(op->v.assign.expr);
@@ -723,10 +732,10 @@ proc_setup_body(void)
 	argv = peek(&args);
 	for (i = 0, op = argv->base.next; op != NULL; i++) {
 		/*
-		 * TODO: should free the whole list but.., we're gonna
-		 * exit real soon(tm)!
+		 * TODO: should free the whole list on error but..,
+		 * we're gonna exit real soon(tm)!
 		 */
-		if (op->type != OP_VAR)
+		if (op->type != OP_VAR && op->type != OP_REST)
 			return 0;
 
 		op = op->next;
@@ -752,13 +761,19 @@ proc_done(char *name)
 	proc->minargs = argc;
 
         for (i = 0, op = argv; op != NULL; ++i) {
+		if (op->type == OP_REST) {
+			proc->vararg = 1;
+			proc->minargs = i;
+			break;
+		}
+
 		proc->args[i] = xstrdup(op->v.var);
 
 		next = op->next;
 		free_op(op);
 		op = next;
 	}
-	assert(i == argc);
+	assert(i == argc || (proc->vararg && i == proc->minargs));
 
 	proc->body = body;
 
blob - 28896865a4f7b7adaaf21480fa6c533b78787ea4
blob + 8d50f348364bead955dc6c4a819478aa79cd1da3
--- script.h
+++ script.h
@@ -51,6 +51,7 @@ struct value {
 };
 
 enum {
+	OP_REST,
 	OP_ASSIGN,
 	OP_ASSERT,
 	OP_FUNCALL,
@@ -139,6 +140,7 @@ int		 global_set(char *, struct op *);
 
 struct op	*newop(int);
 void		 free_op(struct op *);
+struct op	*op_rest(void);
 struct op	*op_assign(char *, struct op *);
 struct op	*op_assert(struct op *);
 struct op	*op_var(char *);