[前][次][番号順一覧][スレッド一覧]

ruby-changes:11011

From: knu <ko1@a...>
Date: Wed, 25 Feb 2009 00:15:37 +0900 (JST)
Subject: [ruby-changes:11011] Ruby:r22601 (trunk): * class.c (rb_scan_args): Revamp rb_scan_args() to compute the

knu	2009-02-25 00:15:25 +0900 (Wed, 25 Feb 2009)

  New Revision: 22601

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=22601

  Log:
    * class.c (rb_scan_args): Revamp rb_scan_args() to compute the
      number of required and optional arguments precisely to prepare
      for a more informative error message.

  Modified files:
    trunk/ChangeLog
    trunk/class.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 22600)
+++ ChangeLog	(revision 22601)
@@ -1,3 +1,9 @@
+Wed Feb 25 00:05:13 2009  Akinori MUSHA  <knu@i...>
+
+	* class.c (rb_scan_args): Revamp rb_scan_args() to compute the
+	  number of required and optional arguments precisely to prepare
+	  for a more informative error message.
+
 Tue Feb 24 23:58:52 2009  Akinori MUSHA  <knu@i...>
 
 	* array.c (rb_ary_index, rb_ary_rindex): Emit a warning that a
Index: class.c
===================================================================
--- class.c	(revision 22600)
+++ class.c	(revision 22601)
@@ -920,112 +920,102 @@
 int
 rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
 {
-    int i = 0, postargc, nonpostargc;
-    const char *p = fmt, *q;
+    int i;
+    const char *p = fmt;
     VALUE *var;
     va_list vargs;
+    int f_var = 0, f_block = 0;
+    int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
+    int argi = 0;
 
-    va_start(vargs, fmt);
-
-    /* check the trailing mandatory argument length in advance */
-    if ((q = strchr(p, '*')) != NULL && ISDIGIT(*++q)) {
-	postargc = *q - '0';
-	nonpostargc = argc - postargc;
+    if (ISDIGIT(*p)) {
+	n_lead = *p - '0';
+	p++;
+	if (ISDIGIT(*p)) {
+	    n_opt = *p - '0';
+	    p++;
+	}
     }
-    else {
-	postargc = 0;
-	nonpostargc = argc;
-    }
-
     if (*p == '*') {
-	if (nonpostargc < 0)
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-		     argc, postargc);
-	goto rest_arg;
-    }
-    else if (ISDIGIT(*p)) {
-	/* leading mandatory arguments */
-	int n = *p - '0';
-
-	if (nonpostargc < n)
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-		     argc, n + postargc);
-	for (; n-- > 0; i++) {
-	    var = va_arg(vargs, VALUE*);
-	    if (var) *var = argv[i];
+	f_var = 1;
+	p++;
+	if (ISDIGIT(*p)) {
+	    n_trail = *p - '0';
+	    p++;
 	}
+    }
+    if (*p == '&') {
+	f_block = 1;
 	p++;
     }
-    else {
-	goto error;
+    if (*p != '\0') {
+	rb_fatal("bad scan arg format: %s", fmt);
     }
+    n_mand = n_lead + n_trail;
 
-    /* optional arguments (typically with default values) */
-    if (ISDIGIT(*p)) {
-	int n = *p - '0';
+    if (argc < n_mand)
+	goto argc_error;
 
-	for (; n-- > 0; ) {
-	    var = va_arg(vargs, VALUE*);
-	    if (i < nonpostargc) {
-		if (var) *var = argv[i];
-		i++;
-	    }
-	    else {
-		if (var) *var = Qnil;
-	    }
+    va_start(vargs, fmt);
+
+    /* capture leading mandatory arguments */
+    for (i = n_lead; i-- > 0; ) {
+	var = va_arg(vargs, VALUE *);
+	if (var) *var = argv[argi];
+	argi++;
+    }
+    /* capture optional arguments */
+    for (i = n_opt; i-- > 0; ) {
+	var = va_arg(vargs, VALUE *);
+	if (argi < argc - n_trail) {
+	    if (var) *var = argv[argi];
+	    argi++;
 	}
-	p++;
+	else {
+	    if (var) *var = Qnil;
+	}
     }
+    /* capture variable length arguments */
+    if (f_var) {
+	int n_var = argc - argi - n_trail;
 
-    if (*p == '*') {
-      rest_arg:
-	/* variable length arguments (the <*rest> part) */
-	var = va_arg(vargs, VALUE*);
-	if (i < nonpostargc) {
-	    if (var) *var = rb_ary_new4(nonpostargc-i, argv+i);
-	    i = nonpostargc;
+	var = va_arg(vargs, VALUE *);
+	if (0 < n_var) {
+	    if (var) *var = rb_ary_new4(n_var, &argv[argi]);
+	    argi += n_var;
 	}
 	else {
 	    if (var) *var = rb_ary_new();
 	}
-	p++;
-
-	if (0 < postargc) {
-	    /* trailing mandatory arguments */
-	    int n = postargc;
-
-	    for (; n-- > 0; i++) {
-		var = va_arg(vargs, VALUE*);
-		if (var) *var = argv[i];
-	    }
-	    p++;
-	}
     }
-
-    if (*p == '&') {
-	/* iterator block */
-	var = va_arg(vargs, VALUE*);
+    /* capture trailing mandatory arguments */
+    for (i = n_trail; i-- > 0; ) {
+	var = va_arg(vargs, VALUE *);
+	if (var) *var = argv[argi];
+	argi++;
+    }
+    /* capture iterator block */
+    if (f_block) {
+	var = va_arg(vargs, VALUE *);
 	if (rb_block_given_p()) {
 	    *var = rb_block_proc();
 	}
 	else {
 	    *var = Qnil;
 	}
-	p++;
     }
     va_end(vargs);
 
-    if (*p != '\0') {
-	goto error;
-    }
+    if (argi < argc)
+	goto argc_error;
 
-    if (i < argc) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
-    }
-
     return argc;
 
-  error:
-    rb_fatal("bad scan arg format: %s", fmt);
-    return 0;
+  argc_error:
+    if (0 < n_opt)
+	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d..%d%s)",
+		 argc, n_mand, n_mand + n_opt, f_var ? "+" : "");
+    else
+	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d%s)",
+		 argc, n_mand, f_var ? "+" : "");
 }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]