@@ -920,112 +920,102 @@ rb_define_attr(VALUE klass, const char *name, int read, int write)
920920int
921921rb_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