* class.c (rb_scan_args), README.EXT, README.EXT.ja: Add support
for specifying the number of the trailing mandatory arguments. Update the documents accordingly. [ruby-dev:37995] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22339 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1e5de389da
commit
f5ca95ee10
@ -1,3 +1,9 @@
|
|||||||
|
Mon Feb 16 17:04:14 2009 Akinori MUSHA <knu@iDaemons.org>
|
||||||
|
|
||||||
|
* class.c (rb_scan_args), README.EXT, README.EXT.ja: Add support
|
||||||
|
for specifying the number of the trailing mandatory arguments.
|
||||||
|
Update the documents accordingly. [ruby-dev:37995]
|
||||||
|
|
||||||
Mon Feb 16 16:46:14 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Mon Feb 16 16:46:14 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* debug.c (set_debug_option): added rtc_error option.
|
* debug.c (set_debug_option): added rtc_error option.
|
||||||
|
@ -687,13 +687,14 @@ scan-arg-spec := param-arg-spec [block-arg-spec]
|
|||||||
|
|
||||||
param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec
|
param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec
|
||||||
pre-arg-spec := num-of-leading-mandatory-args [num-of-optional-args]
|
pre-arg-spec := num-of-leading-mandatory-args [num-of-optional-args]
|
||||||
post-arg-spec := sym-for-variable-length-args
|
post-arg-spec := sym-for-variable-length-args [num-of-trailing-mandatory-args]
|
||||||
block-arg-spec := sym-for-block-arg
|
block-arg-spec := sym-for-block-arg
|
||||||
|
|
||||||
num-of-leading-mandatory-args := DIGIT ; -- the number of the leading mandatory arguments
|
num-of-leading-mandatory-args := DIGIT ; -- the number of the leading mandatory arguments
|
||||||
num-of-optional-args := DIGIT ; -- the number of the following optional arguments
|
num-of-optional-args := DIGIT ; -- the number of the following optional arguments
|
||||||
sym-for-variable-length-args := "*" ; -- indicates that the following variable length
|
sym-for-variable-length-args := "*" ; -- indicates that the following variable length
|
||||||
; arguments are captured as a Ruby array
|
; arguments are captured as a Ruby array
|
||||||
|
num-of-trailing-mandatory-args := DIGIT ; -- the number of the trailing mandatory arguments
|
||||||
sym-for-block-arg := "&" ; -- indicates that the iterator block should be
|
sym-for-block-arg := "&" ; -- indicates that the iterator block should be
|
||||||
; captured if given
|
; captured if given
|
||||||
--
|
--
|
||||||
|
@ -775,13 +775,14 @@ scan-arg-spec := param-arg-spec [block-arg-spec]
|
|||||||
|
|
||||||
param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec
|
param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec
|
||||||
pre-arg-spec := num-of-leading-mandatory-args [num-of-optional-args]
|
pre-arg-spec := num-of-leading-mandatory-args [num-of-optional-args]
|
||||||
post-arg-spec := sym-for-variable-length-args
|
post-arg-spec := sym-for-variable-length-args [num-of-trailing-mandatory-args]
|
||||||
block-arg-spec := sym-for-block-arg
|
block-arg-spec := sym-for-block-arg
|
||||||
|
|
||||||
num-of-leading-mandatory-args := DIGIT ; -- 先頭に置かれる省略不可能な引数の数
|
num-of-leading-mandatory-args := DIGIT ; -- 先頭に置かれる省略不可能な引数の数
|
||||||
num-of-optional-args := DIGIT ; -- 続いて置かれる省略可能な引数の数
|
num-of-optional-args := DIGIT ; -- 続いて置かれる省略可能な引数の数
|
||||||
sym-for-variable-length-args := "*" ; -- 続いて置かれる可変長引数をRubyの配列で
|
sym-for-variable-length-args := "*" ; -- 続いて置かれる可変長引数をRubyの配列で
|
||||||
; 取得するための指定
|
; 取得するための指定
|
||||||
|
num-of-trailing-mandatory-args := DIGIT ; -- 終端に置かれる省略不可能な引数の数
|
||||||
sym-for-block-arg := "&" ; -- イテレータブロックを取得するための指定
|
sym-for-block-arg := "&" ; -- イテレータブロックを取得するための指定
|
||||||
--
|
--
|
||||||
|
|
||||||
|
65
class.c
65
class.c
@ -920,20 +920,37 @@ rb_define_attr(VALUE klass, const char *name, int read, int write)
|
|||||||
int
|
int
|
||||||
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
int n, i = 0;
|
int i = 0, postargc, nonpostargc;
|
||||||
const char *p = fmt;
|
const char *p = fmt, *q;
|
||||||
VALUE *var;
|
VALUE *var;
|
||||||
va_list vargs;
|
va_list vargs;
|
||||||
|
|
||||||
va_start(vargs, fmt);
|
va_start(vargs, fmt);
|
||||||
|
|
||||||
if (*p == '*') goto rest_arg;
|
/* check the trailing mandatory argument length in advance */
|
||||||
|
if ((q = strchr(p, '*')) != NULL && ISDIGIT(*++q)) {
|
||||||
|
postargc = *q - '0';
|
||||||
|
nonpostargc = argc - postargc;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
postargc = 0;
|
||||||
|
nonpostargc = argc;
|
||||||
|
}
|
||||||
|
|
||||||
if (ISDIGIT(*p)) {
|
if (*p == '*') {
|
||||||
n = *p - '0';
|
if (nonpostargc < 0)
|
||||||
if (n > argc)
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
|
||||||
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, n);
|
argc, postargc);
|
||||||
for (i=0; i<n; i++) {
|
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*);
|
var = va_arg(vargs, VALUE*);
|
||||||
if (var) *var = argv[i];
|
if (var) *var = argv[i];
|
||||||
}
|
}
|
||||||
@ -943,12 +960,15 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* optional arguments (typically with default values) */
|
||||||
if (ISDIGIT(*p)) {
|
if (ISDIGIT(*p)) {
|
||||||
n = i + *p - '0';
|
int n = *p - '0';
|
||||||
for (; i<n; i++) {
|
|
||||||
|
for (; n-- > 0; ) {
|
||||||
var = va_arg(vargs, VALUE*);
|
var = va_arg(vargs, VALUE*);
|
||||||
if (argc > i) {
|
if (i < nonpostargc) {
|
||||||
if (var) *var = argv[i];
|
if (var) *var = argv[i];
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (var) *var = Qnil;
|
if (var) *var = Qnil;
|
||||||
@ -957,20 +977,33 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
|||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*p == '*') {
|
if (*p == '*') {
|
||||||
rest_arg:
|
rest_arg:
|
||||||
|
/* variable length arguments (the <*rest> part) */
|
||||||
var = va_arg(vargs, VALUE*);
|
var = va_arg(vargs, VALUE*);
|
||||||
if (argc > i) {
|
if (i < nonpostargc) {
|
||||||
if (var) *var = rb_ary_new4(argc-i, argv+i);
|
if (var) *var = rb_ary_new4(nonpostargc-i, argv+i);
|
||||||
i = argc;
|
i = nonpostargc;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (var) *var = rb_ary_new();
|
if (var) *var = rb_ary_new();
|
||||||
}
|
}
|
||||||
p++;
|
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 == '&') {
|
if (*p == '&') {
|
||||||
|
/* iterator block */
|
||||||
var = va_arg(vargs, VALUE*);
|
var = va_arg(vargs, VALUE*);
|
||||||
if (rb_block_given_p()) {
|
if (rb_block_given_p()) {
|
||||||
*var = rb_block_proc();
|
*var = rb_block_proc();
|
||||||
@ -986,7 +1019,7 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > i) {
|
if (i < argc) {
|
||||||
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user