11/***********************************************************
2- Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
2+ Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
33Amsterdam, The Netherlands.
44
55 All Rights Reserved
@@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2626
2727#include "allobjects.h"
2828
29+ #include <ctype.h>
30+
2931#ifdef COUNT_ALLOCS
3032int null_strings , one_strings ;
3133#endif
@@ -428,11 +430,11 @@ string_hash(a)
428430}
429431
430432static sequence_methods string_as_sequence = {
431- string_length , /*sq_length*/
432- string_concat , /*sq_concat*/
433- string_repeat , /*sq_repeat*/
434- string_item , /*sq_item*/
435- string_slice , /*sq_slice*/
433+ ( inquiry ) string_length , /*sq_length*/
434+ ( binaryfunc ) string_concat , /*sq_concat*/
435+ ( intargfunc ) string_repeat , /*sq_repeat*/
436+ ( intargfunc ) string_item , /*sq_item*/
437+ ( intintargfunc ) string_slice , /*sq_slice*/
436438 0 , /*sq_ass_item*/
437439 0 , /*sq_ass_slice*/
438440};
@@ -443,16 +445,16 @@ typeobject Stringtype = {
443445 "string" ,
444446 sizeof (stringobject ),
445447 sizeof (char ),
446- string_dealloc , /*tp_dealloc*/
447- string_print , /*tp_print*/
448+ ( destructor ) string_dealloc , /*tp_dealloc*/
449+ ( printfunc ) string_print , /*tp_print*/
448450 0 , /*tp_getattr*/
449451 0 , /*tp_setattr*/
450- string_compare , /*tp_compare*/
451- string_repr , /*tp_repr*/
452+ ( cmpfunc ) string_compare , /*tp_compare*/
453+ ( reprfunc ) string_repr , /*tp_repr*/
452454 0 , /*tp_as_number*/
453455 & string_as_sequence , /*tp_as_sequence*/
454456 0 , /*tp_as_mapping*/
455- string_hash , /*tp_hash*/
457+ ( hashfunc ) string_hash , /*tp_hash*/
456458};
457459
458460void
@@ -461,13 +463,28 @@ joinstring(pv, w)
461463 register object * w ;
462464{
463465 register object * v ;
464- if (* pv == NULL || w == NULL || !is_stringobject (* pv ))
466+ if (* pv == NULL )
467+ return ;
468+ if (w == NULL || !is_stringobject (* pv )) {
469+ DECREF (* pv );
470+ * pv = NULL ;
465471 return ;
472+ }
466473 v = string_concat ((stringobject * ) * pv , w );
467474 DECREF (* pv );
468475 * pv = v ;
469476}
470477
478+ void
479+ joinstring_decref (pv , w )
480+ register object * * pv ;
481+ register object * w ;
482+ {
483+ joinstring (pv , w );
484+ XDECREF (w );
485+ }
486+
487+
471488/* The following function breaks the notion that strings are immutable:
472489 it changes the size of a string. We get away with this only if there
473490 is only one module referencing the object. You can also think of it
@@ -596,6 +613,27 @@ formatchar(v)
596613 return buf ;
597614}
598615
616+ /* XXX this could be moved to object.c */
617+ static object *
618+ get_mapping_item (mo , ko )
619+ object * mo ;
620+ object * ko ;
621+ {
622+ mapping_methods * mm = mo -> ob_type -> tp_as_mapping ;
623+ object * val ;
624+
625+ if (!mm || !mm -> mp_subscript ) {
626+ err_setstr (TypeError , "subscript not implemented" );
627+ return NULL ;
628+ }
629+
630+ val = (* mm -> mp_subscript )(mo , ko );
631+ XDECREF (val ); /* still in mapping */
632+
633+ return val ;
634+ }
635+
636+
599637/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
600638
601639object *
@@ -606,6 +644,7 @@ formatstring(format, args)
606644 char * fmt , * res ;
607645 int fmtcnt , rescnt , reslen , arglen , argidx ;
608646 object * result ;
647+ object * dict = NULL ;
609648 if (format == NULL || !is_stringobject (format ) || args == NULL ) {
610649 err_badcall ();
611650 return NULL ;
@@ -625,6 +664,8 @@ formatstring(format, args)
625664 arglen = -1 ;
626665 argidx = -2 ;
627666 }
667+ if (args -> ob_type -> tp_as_mapping )
668+ dict = args ;
628669 while (-- fmtcnt >= 0 ) {
629670 if (* fmt != '%' ) {
630671 if (-- rescnt < 0 ) {
@@ -633,6 +674,7 @@ formatstring(format, args)
633674 if (resizestring (& result , reslen ) < 0 )
634675 return NULL ;
635676 res = getstringvalue (result ) + reslen - rescnt ;
677+ -- rescnt ;
636678 }
637679 * res ++ = * fmt ++ ;
638680 }
@@ -646,9 +688,43 @@ formatstring(format, args)
646688 int c = '\0' ;
647689 int fill ;
648690 object * v ;
691+ object * temp = NULL ;
649692 char * buf ;
650693 int sign ;
651694 int len ;
695+ if (* fmt == '(' ) {
696+ char * keystart ;
697+ int keylen ;
698+ object * key ;
699+
700+ if (dict == NULL ) {
701+ err_setstr (TypeError ,
702+ "format requires a mapping" );
703+ goto error ;
704+ }
705+ ++ fmt ;
706+ -- fmtcnt ;
707+ keystart = fmt ;
708+ while (-- fmtcnt >= 0 && * fmt != ')' )
709+ fmt ++ ;
710+ keylen = fmt - keystart ;
711+ ++ fmt ;
712+ if (fmtcnt < 0 ) {
713+ err_setstr (ValueError ,
714+ "incomplete format key" );
715+ goto error ;
716+ }
717+ key = newsizedstringobject (keystart , keylen );
718+ if (key == NULL )
719+ goto error ;
720+ args = get_mapping_item (dict , key );
721+ DECREF (key );
722+ if (args == NULL ) {
723+ goto error ;
724+ }
725+ arglen = -1 ;
726+ argidx = -2 ;
727+ }
652728 while (-- fmtcnt >= 0 ) {
653729 switch (c = * fmt ++ ) {
654730 case '-' : flags |= F_LJUST ; continue ;
@@ -745,13 +821,11 @@ formatstring(format, args)
745821 len = 1 ;
746822 break ;
747823 case 's' :
748- if (!is_stringobject (v )) {
749- err_setstr (TypeError ,
750- "%s wants string" );
824+ temp = strobject (v );
825+ if (temp == NULL )
751826 goto error ;
752- }
753- buf = getstringvalue (v );
754- len = getstringsize (v );
827+ buf = getstringvalue (temp );
828+ len = getstringsize (temp );
755829 if (prec >= 0 && len > prec )
756830 len = prec ;
757831 break ;
@@ -839,6 +913,12 @@ formatstring(format, args)
839913 -- rescnt ;
840914 * res ++ = ' ' ;
841915 }
916+ if (dict && (argidx < arglen )) {
917+ err_setstr (TypeError ,
918+ "not all arguments converted" );
919+ goto error ;
920+ }
921+ XDECREF (temp );
842922 } /* '%' */
843923 } /* until end */
844924 if (argidx < arglen ) {
0 commit comments