@@ -29,6 +29,8 @@ extern char *strerror(int);
2929#include "winbase.h"
3030#endif
3131
32+ #include <ctype.h>
33+
3234void
3335PyErr_Restore (PyObject * type , PyObject * value , PyObject * traceback )
3436{
@@ -364,7 +366,6 @@ PyObject *PyErr_SetFromWindowsErrWithFilename(
364366PyObject * PyErr_SetFromWindowsErr (int ierr )
365367{
366368 return PyErr_SetFromWindowsErrWithFilename (ierr , NULL );
367-
368369}
369370#endif /* MS_WINDOWS */
370371
@@ -393,12 +394,131 @@ PyObject *
393394PyErr_Format (PyObject * exception , const char * format , ...)
394395{
395396 va_list vargs ;
396- char buffer [500 ]; /* Caller is responsible for limiting the format */
397+ int n , i ;
398+ const char * f ;
399+ char * s ;
400+ PyObject * string ;
397401
402+ /* step 1: figure out how large a buffer we need */
403+
404+ #ifdef HAVE_STDARG_PROTOTYPES
398405 va_start (vargs , format );
406+ #else
407+ va_start (vargs );
408+ #endif
399409
400- vsprintf (buffer , format , vargs );
401- PyErr_SetString (exception , buffer );
410+ n = 0 ;
411+ for (f = format ; * f ; f ++ ) {
412+ if (* f == '%' ) {
413+ const char * p = f ;
414+ while (* ++ f && * f != '%' && !isalpha (* f ))
415+ ;
416+ switch (* f ) {
417+ case 'c' :
418+ va_arg (vargs , int );
419+ /* fall through... */
420+ case '%' :
421+ n ++ ;
422+ break ;
423+ case 'd' : case 'i' : case 'x' :
424+ va_arg (vargs , int );
425+ /* 20 bytes should be enough to hold a 64-bit
426+ integer */
427+ n = n + 20 ;
428+ break ;
429+ case 's' :
430+ s = va_arg (vargs , char * );
431+ n = n + strlen (s );
432+ break ;
433+ default :
434+ /* if we stumble upon an unknown
435+ formatting code, copy the rest of
436+ the format string to the output
437+ string. (we cannot just skip the
438+ code, since there's no way to know
439+ what's in the argument list) */
440+ n = n + strlen (p );
441+ goto expand ;
442+ }
443+ } else
444+ n = n + 1 ;
445+ }
446+
447+ expand :
448+
449+ string = PyString_FromStringAndSize (NULL , n );
450+ if (!string )
451+ return NULL ;
452+
453+ #ifdef HAVE_STDARG_PROTOTYPES
454+ va_start (vargs , format );
455+ #else
456+ va_start (vargs );
457+ #endif
458+
459+ /* step 2: fill the buffer */
460+
461+ s = PyString_AsString (string );
462+
463+ for (f = format ; * f ; f ++ ) {
464+ if (* f == '%' ) {
465+ const char * p = f ++ ;
466+ /* parse the width.precision part (we're only
467+ interested in the precision value, if any) */
468+ n = 0 ;
469+ while (isdigit (* f ))
470+ n = (n * 10 ) + * f ++ - '0' ;
471+ if (* f == '.' ) {
472+ f ++ ;
473+ n = 0 ;
474+ while (isdigit (* f ))
475+ n = (n * 10 ) + * f ++ - '0' ;
476+ }
477+ while (* f && * f != '%' && !isalpha (* f ))
478+ f ++ ;
479+ switch (* f ) {
480+ case 'c' :
481+ * s ++ = va_arg (vargs , int );
482+ break ;
483+ case 'd' :
484+ sprintf (s , "%d" , va_arg (vargs , int ));
485+ s = s + strlen (s );
486+ break ;
487+ case 'i' :
488+ sprintf (s , "%i" , va_arg (vargs , int ));
489+ s = s + strlen (s );
490+ break ;
491+ case 'x' :
492+ sprintf (s , "%x" , va_arg (vargs , int ));
493+ s = s + strlen (s );
494+ break ;
495+ case 's' :
496+ p = va_arg (vargs , char * );
497+ i = strlen (p );
498+ if (n > 0 && i > n )
499+ i = n ;
500+ memcpy (s , p , i );
501+ s = s + i ;
502+ break ;
503+ case '%' :
504+ * s ++ = '%' ;
505+ break ;
506+ default :
507+ strcpy (s , p );
508+ s = s + strlen (s );
509+ goto end ;
510+ }
511+ } else
512+ * s ++ = * f ;
513+ }
514+
515+ end :
516+
517+ _PyString_Resize (& string , s - PyString_AsString (string ));
518+
519+ PyErr_SetObject (exception , string );
520+ Py_XDECREF (string );
521+
402522 return NULL ;
403523}
404524
0 commit comments