Skip to content

Commit

Permalink
* class.c (rb_scan_args), README.EXT, README.EXT.ja: Add support
Browse files Browse the repository at this point in the history
  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
  • Loading branch information
knu committed Feb 16, 2009
1 parent 1e5de38 commit f5ca95e
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 18 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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>

* debug.c (set_debug_option): added rtc_error option.
Expand Down
3 changes: 2 additions & 1 deletion README.EXT
Original file line number Diff line number Diff line change
Expand Up @@ -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
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

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
sym-for-variable-length-args := "*" ; -- indicates that the following variable length
; 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
; captured if given
--
Expand Down
3 changes: 2 additions & 1 deletion README.EXT.ja
Original file line number Diff line number Diff line change
Expand Up @@ -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
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

num-of-leading-mandatory-args := DIGIT ; -- ��Ƭ���֤�����ά�Բ�ǽ�ʰ����ο�
num-of-optional-args := DIGIT ; -- ³�����֤�����ά��ǽ�ʰ����ο�
sym-for-variable-length-args := "*" ; -- ³�����֤�������Ĺ������Ruby�������
; �������뤿��λ���
num-of-trailing-mandatory-args := DIGIT ; -- ��ü���֤�����ά�Բ�ǽ�ʰ����ο�
sym-for-block-arg := "&" ; -- ���ƥ졼���֥��å���������뤿��λ���
--

Expand Down
65 changes: 49 additions & 16 deletions class.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,20 +920,37 @@ rb_define_attr(VALUE klass, const char *name, int read, int write)
int
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
{
int n, i = 0;
const char *p = fmt;
int i = 0, postargc, nonpostargc;
const char *p = fmt, *q;
VALUE *var;
va_list vargs;

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)) {
n = *p - '0';
if (n > argc)
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, n);
for (i=0; i<n; i++) {
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];
}
Expand All @@ -943,12 +960,15 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
goto error;
}

/* optional arguments (typically with default values) */
if (ISDIGIT(*p)) {
n = i + *p - '0';
for (; i<n; i++) {
int n = *p - '0';

for (; n-- > 0; ) {
var = va_arg(vargs, VALUE*);
if (argc > i) {
if (i < nonpostargc) {
if (var) *var = argv[i];
i++;
}
else {
if (var) *var = Qnil;
Expand All @@ -957,20 +977,33 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
p++;
}

if(*p == '*') {
if (*p == '*') {
rest_arg:
/* variable length arguments (the <*rest> part) */
var = va_arg(vargs, VALUE*);
if (argc > i) {
if (var) *var = rb_ary_new4(argc-i, argv+i);
i = argc;
if (i < nonpostargc) {
if (var) *var = rb_ary_new4(nonpostargc-i, argv+i);
i = nonpostargc;
}
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*);
if (rb_block_given_p()) {
*var = rb_block_proc();
Expand All @@ -986,7 +1019,7 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
goto error;
}

if (argc > i) {
if (i < argc) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
}

Expand Down

0 comments on commit f5ca95e

Please sign in to comment.