@@ -328,15 +328,67 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b
328328 kh_value (h , k ) = mrb_proc_ptr (body );
329329}
330330
331+ static mrb_value
332+ check_type (mrb_state * mrb , mrb_value val , enum mrb_vtype t , const char * c , const char * m )
333+ {
334+ mrb_value tmp ;
335+
336+ tmp = mrb_check_convert_type (mrb , val , t , c , m );
337+ if (mrb_nil_p (tmp )) {
338+ mrb_raise (mrb , E_TYPE_ERROR , "expected %s" , c );
339+ }
340+ return tmp ;
341+ }
342+
343+ static mrb_value
344+ to_str (mrb_state * mrb , mrb_value val )
345+ {
346+ return check_type (mrb , val , MRB_TT_STRING , "String" , "to_str" );
347+ }
348+
349+ static mrb_value
350+ to_ary (mrb_state * mrb , mrb_value val )
351+ {
352+ return check_type (mrb , val , MRB_TT_ARRAY , "Array" , "to_ary" );
353+ }
354+
355+ static mrb_value
356+ to_hash (mrb_state * mrb , mrb_value val )
357+ {
358+ return check_type (mrb , val , MRB_TT_HASH , "Hash" , "to_hash" );
359+ }
360+
361+ /*
362+ retrieve arguments from mrb_state.
363+
364+ mrb_get_args(mrb, format, ...)
365+
366+ returns number of arguments parsed.
367+
368+ fortmat specifiers:
369+
370+ o: Object [mrb_value]
371+ S: String [mrb_value]
372+ A: Array [mrb_value]
373+ H: Hash [mrb_value]
374+ s: String [char*,int]
375+ z: String [char*]
376+ a: Array [mrb_value*,int]
377+ f: Float [mrb_float]
378+ i: Integer [mrb_int]
379+ &: Block [mrb_value]
380+ *: rest argument [mrb_value*,int]
381+ |: optional
382+ */
331383int
332384mrb_get_args (mrb_state * mrb , const char * format , ...)
333385{
334386 char c ;
335- int i = 0 ;
387+ int i = 0 ;
336388 mrb_value * sp = mrb -> stack + 1 ;
337389 va_list ap ;
338390 int argc = mrb -> ci -> argc ;
339- int * argcp ;
391+ int opt = 0 ;
340392
341393 va_start (ap , format );
342394 if (argc < 0 ) {
@@ -346,39 +398,92 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
346398 sp = a -> buf ;
347399 }
348400 while ((c = * format ++ )) {
401+ if (argc < i ) {
402+ if (opt ) continue ;
403+ mrb_raise (mrb , E_ARGUMENT_ERROR , "wrong number of arguments" );
404+ }
349405 switch (c ) {
350406 case 'o' :
351407 {
352408 mrb_value * p ;
409+
353410 p = va_arg (ap , mrb_value * );
354411 * p = * sp ;
355412 i ++ ; sp ++ ;
356413 }
357414 break ;
358- case 'i ' :
415+ case 'S ' :
359416 {
360- mrb_int * p ;
417+ mrb_value * p ;
361418
362- p = va_arg (ap , mrb_int * );
363- switch (sp -> tt ) {
364- case MRB_TT_FIXNUM :
365- * p = mrb_fixnum (* sp );
366- break ;
367- case MRB_TT_FLOAT :
368- * p = (mrb_int )mrb_float (* sp );
369- break ;
370- case MRB_TT_FALSE :
371- * p = 0 ;
372- break ;
373- default :
374- {
375- mrb_value tmp ;
419+ p = va_arg (ap , mrb_value * );
420+ * p = to_str (mrb , * sp );
421+ i ++ ; sp ++ ;
422+ }
423+ break ;
424+ case 'A' :
425+ {
426+ mrb_value * p ;
376427
377- tmp = mrb_convert_type (mrb , * sp , MRB_TT_FIXNUM , "Integer" , "to_int" );
378- * p = mrb_fixnum (tmp );
379- }
380- break ;
381- }
428+ p = va_arg (ap , mrb_value * );
429+ * p = to_ary (mrb , * sp );
430+ i ++ ; sp ++ ;
431+ }
432+ break ;
433+ case 'H' :
434+ {
435+ mrb_value * p ;
436+
437+ p = va_arg (ap , mrb_value * );
438+ * p = to_hash (mrb , * sp );
439+ i ++ ; sp ++ ;
440+ }
441+ break ;
442+ case 's' :
443+ {
444+ mrb_value ss ;
445+ struct RString * s ;
446+ char * * ps = 0 ;
447+ int * pl = 0 ;
448+
449+ ss = to_str (mrb , * sp );
450+ s = mrb_str_ptr (ss );
451+ ps = va_arg (ap , char * * );
452+ * ps = s -> buf ;
453+ pl = va_arg (ap , int * );
454+ * pl = s -> len ;
455+ i ++ ; sp ++ ;
456+ }
457+ break ;
458+ case 'z' :
459+ {
460+ mrb_value ss ;
461+ struct RString * s ;
462+ char * * ps ;
463+
464+ ss = to_str (mrb , * sp );
465+ s = mrb_str_ptr (ss );
466+ if (strlen (s -> buf ) != s -> len ) {
467+ mrb_raise (mrb , E_ARGUMENT_ERROR , "String contains NUL" );
468+ }
469+ ps = va_arg (ap , char * * );
470+ * ps = s -> buf ;
471+ i ++ ; sp ++ ;
472+ }
473+ break ;
474+ case 'a' :
475+ {
476+ mrb_value aa ;
477+ struct RArray * a ;
478+ mrb_value * * pb ;
479+ int * pl ;
480+
481+ aa = to_ary (mrb , * sp );
482+ a = mrb_ary_ptr (aa );
483+ pb = va_arg (ap , mrb_value * * );
484+ * pb = a -> buf ;
485+ pl = va_arg (ap , int * );
486+ * pl = a -> len ;
382487 i ++ ; sp ++ ;
383488 }
384489 break ;
@@ -409,53 +514,34 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
409514 i ++ ; sp ++ ;
410515 }
411516 break ;
412- case 's ' :
517+ case 'i ' :
413518 {
414- char * * ps = 0 ;
415- size_t * pl = 0 ;
416- struct RString * s ;
519+ mrb_int * p ;
417520
418- if (argc > i ) {
419- s = mrb_str_ptr (* sp );
420- ps = va_arg (ap , char * * );
421- * ps = s -> buf ;
422- pl = va_arg (ap , size_t * );
423- * pl = s -> len ;
521+ p = va_arg (ap , mrb_int * );
522+ switch (sp -> tt ) {
523+ case MRB_TT_FIXNUM :
524+ * p = mrb_fixnum (* sp );
525+ break ;
526+ case MRB_TT_FLOAT :
527+ * p = (mrb_int )mrb_float (* sp );
528+ break ;
529+ case MRB_TT_FALSE :
530+ * p = 0 ;
531+ break ;
532+ default :
533+ {
534+ mrb_value tmp ;
535+
536+ tmp = mrb_convert_type (mrb , * sp , MRB_TT_FIXNUM , "Integer" , "to_int" );
537+ * p = mrb_fixnum (tmp );
538+ }
539+ break ;
424540 }
425541 i ++ ; sp ++ ;
426542 }
427543 break ;
428- case 'a' :
429- {
430- mrb_value * var ;
431- var = va_arg (ap , mrb_value * );
432- if (argc > i ) {
433- if (var ) {
434- memcpy (var , sp , sizeof (mrb_value )* (argc - i ));
435- }
436- //i = mrb->argc;
437- }
438- else {
439- if (var ) * var = mrb_ary_new (mrb );
440- }
441- argcp = va_arg (ap , int * );
442- * argcp = argc - i ;
443- goto last_var ;
444- }
445- break ;
446- case 'b' :
447- {
448- struct RProc * * p ;
449- mrb_value * bp = mrb -> stack + 1 ;
450544
451- p = va_arg (ap , struct RProc * * );
452- if (mrb -> ci -> argc > 0 ) {
453- bp += mrb -> ci -> argc ;
454- }
455- if (mrb_nil_p (* bp )) * p = 0 ;
456- else * p = mrb_proc_ptr (* bp );
457- }
458- break ;
459545 case '&' :
460546 {
461547 mrb_value * p , * bp = mrb -> stack + 1 ;
@@ -467,30 +553,34 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
467553 * p = * bp ;
468554 }
469555 break ;
556+ case '|' :
557+ opt = 1 ;
558+ break ;
470559 case '*' :
471560 {
472561 mrb_value * * var ;
562+ int * pl ;
563+
473564 var = va_arg (ap , mrb_value * * );
474- argcp = va_arg (ap , int * );
565+ pl = va_arg (ap , int * );
475566 if (argc > i ) {
476- * argcp = argc - i ;
477- if (* argcp > 0 ) {
478- if (var ) {
479- * var = sp ;
480- }
481- i += * argcp ;
567+ * pl = argc - i ;
568+ if (* pl > 0 ) {
569+ * var = sp ;
570+ i = argc ;
482571 }
483572 }
484573 else {
485- * argcp = 0 ;
574+ * pl = 0 ;
486575 * var = NULL ;
487576 }
488- goto last_var ;
489577 }
490578 break ;
491579 }
492580 }
493- last_var :
581+ if (!* format && argc > i ) {
582+ mrb_raise (mrb , E_ARGUMENT_ERROR , "wrong number of arguments" );
583+ }
494584 va_end (ap );
495585 return 0 ;
496586}
@@ -679,17 +769,17 @@ mrb_value
679769mrb_class_new_instance_m (mrb_state * mrb , mrb_value klass )
680770{
681771 mrb_value * argv ;
682- struct RProc * b ;
772+ mrb_value blk ;
683773 struct RClass * k = mrb_class_ptr (klass );
684774 struct RClass * c ;
685775 int argc ;
686776 mrb_value obj ;
687777
688- mrb_get_args (mrb , "b* " , & b , & argv , & argc );
778+ mrb_get_args (mrb , "*& " , & argv , & argc , & blk );
689779 c = (struct RClass * )mrb_obj_alloc (mrb , k -> tt , k );
690780 c -> super = k ;
691781 obj = mrb_obj_value (c );
692- mrb_funcall_with_block (mrb , obj , "initialize" , argc , argv , b );
782+ mrb_funcall_with_block (mrb , obj , "initialize" , argc , argv , blk );
693783
694784 return obj ;
695785}
@@ -698,18 +788,17 @@ mrb_value
698788mrb_instance_new (mrb_state * mrb , mrb_value cv )
699789{
700790 struct RClass * c = mrb_class_ptr (cv );
701- struct RProc * b ;
702791 struct RObject * o ;
703792 enum mrb_vtype ttype = MRB_INSTANCE_TT (c );
704- mrb_value obj ;
793+ mrb_value obj , blk ;
705794 mrb_value * argv ;
706795 int argc ;
707796
708797 if (ttype == 0 ) ttype = MRB_TT_OBJECT ;
709798 o = (struct RObject * )mrb_obj_alloc (mrb , ttype , c );
710799 obj = mrb_obj_value (o );
711- mrb_get_args (mrb , "b* " , & b , & argv , & argc );
712- mrb_funcall_with_block (mrb , obj , "initialize" , argc , argv , b );
800+ mrb_get_args (mrb , "*& " , & argv , & argc , & blk );
801+ mrb_funcall_with_block (mrb , obj , "initialize" , argc , argv , blk );
713802
714803 return obj ;
715804}
0 commit comments