@@ -67,6 +67,36 @@ initmodule(name, methods)
6767}
6868
6969
70+ /* Helper for getargs() and mkvalue() to scan the length of a format */
71+
72+ static int countformat PROTO ((char * format , int endchar ));
73+ static int countformat (format , endchar )
74+ char * format ;
75+ int endchar ;
76+ {
77+ int count = 0 ;
78+ int level = 0 ;
79+ while (level > 0 || * format != endchar ) {
80+ if (* format == '\0' ) {
81+ /* Premature end */
82+ err_setstr (SystemError , "unmatched paren in format" );
83+ return -1 ;
84+ }
85+ else if (* format == '(' ) {
86+ if (level == 0 )
87+ count ++ ;
88+ level ++ ;
89+ }
90+ else if (* format == ')' )
91+ level -- ;
92+ else if (level == 0 && * format != '#' )
93+ count ++ ;
94+ format ++ ;
95+ }
96+ return count ;
97+ }
98+
99+
70100/* Generic argument list parser */
71101
72102static int do_arg PROTO ((object * arg , char * * p_format , va_list * p_va ));
@@ -97,7 +127,16 @@ do_arg(arg, p_format, p_va)
97127 return 0 ;
98128 break ;
99129 }
100-
130+
131+ case 'b' : /* byte -- very short int */ {
132+ char * p = va_arg (va , char * );
133+ if (is_intobject (arg ))
134+ * p = getintvalue (arg );
135+ else
136+ return 0 ;
137+ break ;
138+ }
139+
101140 case 'h' : /* short int */ {
102141 short * p = va_arg (va , short * );
103142 if (is_intobject (arg ))
@@ -339,78 +378,76 @@ getshortlistarg(args, a, n)
339378 return 1 ;
340379}
341380
381+
382+ /* Generic function to create a value -- the inverse of getargs() */
383+ /* After an original idea and first implementation by Steven Miale */
384+
385+ static object * do_mktuple PROTO ((char * * , va_list * , int , int ) );
386+ static object * do_mkvalue PROTO ((char * * , va_list * ) );
387+
342388static object *
343- do_mkval (char * * p_format , va_list * p_va ) {
389+ do_mktuple (p_format , p_va , endchar , n )
390+ char * * p_format ;
391+ va_list * p_va ;
392+ int endchar ;
393+ int n ;
394+ {
344395 object * v ;
396+ int i ;
397+ if (n < 0 )
398+ return NULL ;
399+ if ((v = newtupleobject (n )) == NULL )
400+ return NULL ;
401+ for (i = 0 ; i < n ; i ++ ) {
402+ object * w = do_mkvalue (p_format , p_va );
403+ if (w == NULL ) {
404+ DECREF (v );
405+ return NULL ;
406+ }
407+ settupleitem (v , i , w );
408+ }
409+ if (v != NULL && * * p_format != endchar ) {
410+ DECREF (v );
411+ v = NULL ;
412+ err_setstr (SystemError , "Unmatched paren in format" );
413+ }
414+ else if (endchar )
415+ ++ * p_format ;
416+ return v ;
417+ }
418+
419+ static object *
420+ do_mkvalue (p_format , p_va ) {
345421
346422 switch (* (* p_format )++ ) {
347423
348424 case '(' :
349- {
350- int n = 0 ;
351- char * p = * p_format ;
352- int level = 0 ;
353- int i ;
354- while (level > 0 || * p != ')' ) {
355- if (* p == '\0' ) {
356- err_setstr (SystemError , "missing ')' in mkvalue format" );
357- return NULL ;
358- }
359- else if (* p == '(' ) {
360- if (level == 0 )
361- n ++ ;
362- level ++ ;
363- }
364- else if (* p == ')' )
365- level -- ;
366- else if (level == 0 && * p != '#' )
367- n ++ ;
368- p ++ ;
369- }
370- v = newtupleobject (n );
371- if (v == NULL )
372- break ;
373- for (i = 0 ; i < n ; i ++ ) {
374- object * w = do_mkval (p_format , p_va );
375- if (w == NULL ) {
376- DECREF (v );
377- v = NULL ;
378- break ;
379- }
380- settupleitem (v , i , w );
381- }
382- if (v != NULL && * (* p_format )++ != ')' ) {
383- /* "Cannot happen" */
384- err_setstr (SystemError , "inconsistent format in mkvalue???" );
385- DECREF (v );
386- v = NULL ;
387- }
388- }
389- break ;
390-
425+ return do_mktuple (p_format , p_va , ')' ,
426+ countformat (* p_format , ')' ));
427+
428+ case 'b' :
391429 case 'h' :
392- v = newintobject ((long )va_arg (* p_va , short ));
393- break ;
394-
395430 case 'i' :
396- v = newintobject ((long )va_arg (* p_va , int ));
397- break ;
431+ return newintobject ((long )va_arg (* p_va , int ));
398432
399433 case 'l' :
400- v = newintobject ((long )va_arg (* p_va , long ));
401- break ;
434+ return newintobject ((long )va_arg (* p_va , long ));
402435
403436 case 'f' :
404- v = newfloatobject ((double )va_arg (* p_va , float ));
405- break ;
406-
407437 case 'd' :
408- v = newfloatobject ((double )va_arg (* p_va , double ));
409- break ;
438+ return newfloatobject ((double )va_arg (* p_va , double ));
439+
440+ case 'c' :
441+ {
442+ char p [1 ];
443+ p [0 ] = va_arg (* p_va , int );
444+ return newsizedstringobject (p , 1 );
445+ }
410446
411447 case 's' :
412448 case 'z' :
413449 {
450+ object * v ;
414451 char * str = va_arg (* p_va , char * );
415452 int n ;
416453 if (* * p_format == '#' ) {
@@ -428,40 +465,69 @@ do_mkval(char **p_format, va_list *p_va) {
428465 n = strlen (str );
429466 v = newsizedstringobject (str , n );
430467 }
468+ return v ;
431469 }
432- break ;
433470
434471 case 'S' :
435472 case 'O' :
436- v = va_arg (* p_va , object * );
437- if (v == NULL ) {
438- if (!err_occurred ())
439- err_setstr (SystemError , "NULL object passed to mkvalue" );
473+ {
474+ object * v ;
475+ v = va_arg (* p_va , object * );
476+ if (v != NULL )
477+ INCREF (v );
478+ else if (!err_occurred ())
479+ /* If a NULL was passed because a call
480+ that should have constructed a value
481+ failed, that's OK, and we pass the error
482+ on; but if no error occurred it's not
483+ clear that the caller knew what she
484+ was doing. */
485+ err_setstr (SystemError ,
486+ "NULL object passed to mkvalue" );
487+ return v ;
440488 }
441- else
442- INCREF (v );
443- break ;
444489
445490 default :
446491 err_setstr (SystemError , "bad format char passed to mkvalue" );
447- v = NULL ;
448- break ;
492+ return NULL ;
449493
450494 }
451-
452- return v ;
453495}
454496
455- object *
456- mkvalue (char * format , ...)
497+ #ifdef USE_STDARG
498+ /* VARARGS 2 */
499+ object * mkvalue (char * format , ...)
500+ #else
501+ /* VARARGS */
502+ object * mkvalue (va_alist ) va_dcl
503+ #endif
457504{
458- char * fmt = format ;
459- object * v ;
460- va_list p ;
461- va_start (p , format );
462- v = do_mkval (& fmt , & p );
463- va_end (p );
464- if (v == NULL )
465- fprintf (stderr , "mkvalue: format = \"%s\" \"%s\"\n" , format , fmt );
466- return v ;
505+ int n ;
506+ char * f ;
507+ va_list va ;
508+ object * retval ;
509+ #ifdef USE_STDARG
510+ va_start (va , format );
511+ #else
512+ char * format ;
513+
514+ va_start (va );
515+ format = va_arg (va , char * );
516+ #endif
517+ f = format ;
518+ n = countformat (f , '\0' );
519+ if (n < 0 )
520+ retval = NULL ; /* Error in the format */
521+ else if (n == 0 ) {
522+ retval = None ;
523+ INCREF (retval );
524+ }
525+ else if (n == 1 )
526+ retval = do_mkvalue (& f , & va );
527+ else
528+ retval = do_mktuple (& f , & va , '\0' , n );
529+ va_end (va );
530+ if (retval == NULL )
531+ fprintf (stderr , "format \"%s\", f \"%s\"\n" , format , f );
532+ return retval ;
467533}
0 commit comments