Skip to content

Commit ca29209

Browse files
committed
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent d91f52a commit ca29209

File tree

2 files changed

+74
-78
lines changed

2 files changed

+74
-78
lines changed

ChangeLog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
Wed Feb 25 00:05:13 2009 Akinori MUSHA <[email protected]>
2+
3+
* class.c (rb_scan_args): Revamp rb_scan_args() to compute the
4+
number of required and optional arguments precisely to prepare
5+
for a more informative error message.
6+
17
Tue Feb 24 23:58:52 2009 Akinori MUSHA <[email protected]>
28

39
* array.c (rb_ary_index, rb_ary_rindex): Emit a warning that a

class.c

Lines changed: 68 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -920,112 +920,102 @@ rb_define_attr(VALUE klass, const char *name, int read, int write)
920920
int
921921
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
922922
{
923-
int i = 0, postargc, nonpostargc;
924-
const char *p = fmt, *q;
923+
int i;
924+
const char *p = fmt;
925925
VALUE *var;
926926
va_list vargs;
927+
int f_var = 0, f_block = 0;
928+
int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
929+
int argi = 0;
927930

928-
va_start(vargs, fmt);
929-
930-
/* check the trailing mandatory argument length in advance */
931-
if ((q = strchr(p, '*')) != NULL && ISDIGIT(*++q)) {
932-
postargc = *q - '0';
933-
nonpostargc = argc - postargc;
934-
}
935-
else {
936-
postargc = 0;
937-
nonpostargc = argc;
931+
if (ISDIGIT(*p)) {
932+
n_lead = *p - '0';
933+
p++;
934+
if (ISDIGIT(*p)) {
935+
n_opt = *p - '0';
936+
p++;
937+
}
938938
}
939-
940939
if (*p == '*') {
941-
if (nonpostargc < 0)
942-
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
943-
argc, postargc);
944-
goto rest_arg;
945-
}
946-
else if (ISDIGIT(*p)) {
947-
/* leading mandatory arguments */
948-
int n = *p - '0';
949-
950-
if (nonpostargc < n)
951-
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
952-
argc, n + postargc);
953-
for (; n-- > 0; i++) {
954-
var = va_arg(vargs, VALUE*);
955-
if (var) *var = argv[i];
940+
f_var = 1;
941+
p++;
942+
if (ISDIGIT(*p)) {
943+
n_trail = *p - '0';
944+
p++;
956945
}
946+
}
947+
if (*p == '&') {
948+
f_block = 1;
957949
p++;
958950
}
959-
else {
960-
goto error;
951+
if (*p != '\0') {
952+
rb_fatal("bad scan arg format: %s", fmt);
961953
}
954+
n_mand = n_lead + n_trail;
962955

963-
/* optional arguments (typically with default values) */
964-
if (ISDIGIT(*p)) {
965-
int n = *p - '0';
966-
967-
for (; n-- > 0; ) {
968-
var = va_arg(vargs, VALUE*);
969-
if (i < nonpostargc) {
970-
if (var) *var = argv[i];
971-
i++;
972-
}
973-
else {
974-
if (var) *var = Qnil;
975-
}
956+
if (argc < n_mand)
957+
goto argc_error;
958+
959+
va_start(vargs, fmt);
960+
961+
/* capture leading mandatory arguments */
962+
for (i = n_lead; i-- > 0; ) {
963+
var = va_arg(vargs, VALUE *);
964+
if (var) *var = argv[argi];
965+
argi++;
966+
}
967+
/* capture optional arguments */
968+
for (i = n_opt; i-- > 0; ) {
969+
var = va_arg(vargs, VALUE *);
970+
if (argi < argc - n_trail) {
971+
if (var) *var = argv[argi];
972+
argi++;
973+
}
974+
else {
975+
if (var) *var = Qnil;
976976
}
977-
p++;
978977
}
978+
/* capture variable length arguments */
979+
if (f_var) {
980+
int n_var = argc - argi - n_trail;
979981

980-
if (*p == '*') {
981-
rest_arg:
982-
/* variable length arguments (the <*rest> part) */
983-
var = va_arg(vargs, VALUE*);
984-
if (i < nonpostargc) {
985-
if (var) *var = rb_ary_new4(nonpostargc-i, argv+i);
986-
i = nonpostargc;
982+
var = va_arg(vargs, VALUE *);
983+
if (0 < n_var) {
984+
if (var) *var = rb_ary_new4(n_var, &argv[argi]);
985+
argi += n_var;
987986
}
988987
else {
989988
if (var) *var = rb_ary_new();
990989
}
991-
p++;
992-
993-
if (0 < postargc) {
994-
/* trailing mandatory arguments */
995-
int n = postargc;
996-
997-
for (; n-- > 0; i++) {
998-
var = va_arg(vargs, VALUE*);
999-
if (var) *var = argv[i];
1000-
}
1001-
p++;
1002-
}
1003990
}
1004-
1005-
if (*p == '&') {
1006-
/* iterator block */
1007-
var = va_arg(vargs, VALUE*);
991+
/* capture trailing mandatory arguments */
992+
for (i = n_trail; i-- > 0; ) {
993+
var = va_arg(vargs, VALUE *);
994+
if (var) *var = argv[argi];
995+
argi++;
996+
}
997+
/* capture iterator block */
998+
if (f_block) {
999+
var = va_arg(vargs, VALUE *);
10081000
if (rb_block_given_p()) {
10091001
*var = rb_block_proc();
10101002
}
10111003
else {
10121004
*var = Qnil;
10131005
}
1014-
p++;
10151006
}
10161007
va_end(vargs);
10171008

1018-
if (*p != '\0') {
1019-
goto error;
1020-
}
1021-
1022-
if (i < argc) {
1023-
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
1024-
}
1009+
if (argi < argc)
1010+
goto argc_error;
10251011

10261012
return argc;
10271013

1028-
error:
1029-
rb_fatal("bad scan arg format: %s", fmt);
1030-
return 0;
1014+
argc_error:
1015+
if (0 < n_opt)
1016+
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d..%d%s)",
1017+
argc, n_mand, n_mand + n_opt, f_var ? "+" : "");
1018+
else
1019+
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d%s)",
1020+
argc, n_mand, f_var ? "+" : "");
10311021
}

0 commit comments

Comments
 (0)