[Python-checkins] CVS: python/dist/src/Objects stringobject.c,2.149,2.150 unicodeobject.c,2.129,2.130

Andrew I MacIntyre aimacintyre@users.sourceforge.net
Thu, 28 Feb 2002 03:38:26 -0800


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv6793/dist/src/Objects

Modified Files:
	stringobject.c unicodeobject.c 
Log Message:
%#x/%#X format conversion cleanup (see patch #450267):
  Objects/
    stringobject.c
    unicodeobject.c


Index: stringobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v
retrieving revision 2.149
retrieving revision 2.150
diff -C2 -d -r2.149 -r2.150
*** stringobject.c	26 Feb 2002 11:36:35 -0000	2.149
--- stringobject.c	28 Feb 2002 11:38:24 -0000	2.150
***************
*** 3070,3082 ****
  	char fmt[64];	/* plenty big enough! */
  	long x;
  	if (!PyArg_Parse(v, "l;int argument required", &x))
  		return -1;
  	if (prec < 0)
  		prec = 1;
! 	PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
! 		      (flags&F_ALT) ? "#" : "", 
! 		      prec, type);
  	/* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec, len(x in octal))
! 	   worst case buf = '0x' + [0-9]*prec, where prec >= 11 */
  	if (buflen <= 13 || buflen <= (size_t)2 + (size_t)prec) {
  		PyErr_SetString(PyExc_OverflowError,
--- 3070,3113 ----
  	char fmt[64];	/* plenty big enough! */
  	long x;
+ 
  	if (!PyArg_Parse(v, "l;int argument required", &x))
  		return -1;
  	if (prec < 0)
  		prec = 1;
! 
! 	if ((flags & F_ALT) &&
! 	    (type == 'x' || type == 'X')) {
! 		/* When converting under %#x or %#X, there are a number 
! 		 * of issues that cause pain:
! 		 * - when 0 is being converted, the C standard leaves off
! 		 *   the '0x' or '0X', which is inconsistent with other
! 		 *   %#x/%#X conversions and inconsistent with Python's
! 		 *   hex() function
! 		 * - there are platforms that violate the standard and
! 		 *   convert 0 with the '0x' or '0X'
! 		 *   (Metrowerks, Compaq Tru64)
! 		 * - there are platforms that give '0x' when converting
! 		 *   under %#X, but convert 0 in accordance with the 
! 		 *   standard (OS/2 EMX)
! 		 * 
! 		 * We can achieve the desired consistency by inserting our
! 		 * own '0x' or '0X' prefix, and substituting %x/%X in place
! 		 * of %#x/%#X.
! 		 *
! 		 * Note that this is the same approach as used in
! 		 * formatint() in unicodeobject.c
! 		 */
! 		PyOS_snprintf(fmt, sizeof(fmt), "0%c%%.%dl%c", 
! 			      type, prec, type);
! 	}
! 	else {
! 		PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
! 			      (flags&F_ALT) ? "#" : "", 
! 			      prec, type);
! 	}
! 
  	/* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec, len(x in octal))
! 	 * worst case buf = '0x' + [0-9]*prec, where prec >= 11
! 	 */
  	if (buflen <= 13 || buflen <= (size_t)2 + (size_t)prec) {
  		PyErr_SetString(PyExc_OverflowError,
***************
*** 3085,3113 ****
  	}
  	PyOS_snprintf(buf, buflen, fmt, x);
- 	/* When converting 0 under %#x or %#X, C leaves off the base marker,
- 	 * but we want it (for consistency with other %#x conversions, and
- 	 * for consistency with Python's hex() function).
- 	 * BUG 28-Apr-2001 tim:  At least two platform Cs (Metrowerks &
- 	 * Compaq Tru64) violate the std by converting 0 w/ leading 0x anyway.
- 	 * So add it only if the platform didn't already.
- 	 */
- 	if (x == 0 &&
- 	   (flags & F_ALT) &&
- 	   (type == 'x' || type == 'X') &&
- 	    buf[1] != (char)type)  /* this last always true under std C */
- 		{
- 		memmove(buf+2, buf, strlen(buf) + 1);
- 		buf[0] = '0';
- 		buf[1] = (char)type;
- 	}
- #if defined(PYOS_OS2) && defined(PYCC_GCC)
- 	/* unfortunately, the EMX C runtime gives us '0x' as the base
- 	 * marker for %X when we expect/want '0X'
- 	 */
- 	else if ((flags & F_ALT) && (type == 'X')) {
- 		assert(buf[1] == 'x');
- 		buf[1] = (char)type;
- 	}
- #endif
  	return strlen(buf);
  }
--- 3116,3119 ----

Index: unicodeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v
retrieving revision 2.129
retrieving revision 2.130
diff -C2 -d -r2.129 -r2.130
*** unicodeobject.c	26 Feb 2002 11:36:35 -0000	2.129
--- unicodeobject.c	28 Feb 2002 11:38:24 -0000	2.130
***************
*** 5138,5188 ****
  {
      /* fmt = '%#.' + `prec` + 'l' + `type`
!        worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)
!        + 1 + 1 = 24*/
      char fmt[64]; /* plenty big enough! */
      long x;
-     int use_native_c_format = 1;
  
      x = PyInt_AsLong(v);
      if (x == -1 && PyErr_Occurred())
! 	return -1;
      if (prec < 0)
! 	prec = 1;
      /* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec,len(x in octal))
!        worst case buf = '0x' + [0-9]*prec, where prec >= 11 */
!     if (buflen <= 13 || buflen <= (size_t)2+(size_t)prec) {
          PyErr_SetString(PyExc_OverflowError,
!             "formatted integer is too long (precision too long?)");
          return -1;
      }
!     /* When converting 0 under %#x or %#X, C leaves off the base marker,
!      * but we want it (for consistency with other %#x conversions, and
!      * for consistency with Python's hex() function).
!      * BUG 28-Apr-2001 tim:  At least two platform Cs (Metrowerks &
!      * Compaq Tru64) violate the std by converting 0 w/ leading 0x anyway.
!      * So add it only if the platform doesn't already.
!      */
! #if defined(PYOS_OS2) && defined(PYCC_GCC)
!     if ((flags & F_ALT) && (type == 'x' || type == 'X')) {
!         /* the EMX runtime gives 0x as the base marker when we want 0X
!          * so we cover all bets by supplying our own for both cases.
           */
!         use_native_c_format = 0;
!         PyOS_snprintf(fmt, sizeof(fmt), "0%c%%.%dl%c", type, prec, type);
      }
! #else
!     if (x == 0 && (flags & F_ALT) && (type == 'x' || type == 'X')) {
!         /* Only way to know what the platform does is to try it. */
!         PyOS_snprintf(fmt, sizeof(fmt), type == 'x' ? "%#x" : "%#X", 0);
!         if (fmt[1] != (char)type) {
!             /* Supply our own leading 0x/0X -- needed under std C */
!             use_native_c_format = 0;
!             PyOS_snprintf(fmt, sizeof(fmt), "0%c%%#.%dl%c", type, prec, type);
!         }
      }
- #endif
-     if (use_native_c_format)
-          PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
- 		       (flags & F_ALT) ? "#" : "", prec, type);
      return usprintf(buf, fmt, x);
  }
--- 5138,5193 ----
  {
      /* fmt = '%#.' + `prec` + 'l' + `type`
!      * worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)
!      *                     + 1 + 1
!      *                   = 24
!      */
      char fmt[64]; /* plenty big enough! */
      long x;
  
      x = PyInt_AsLong(v);
      if (x == -1 && PyErr_Occurred())
!         return -1;
      if (prec < 0)
!         prec = 1;
! 
      /* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec,len(x in octal))
!      * worst case buf = '0x' + [0-9]*prec, where prec >= 11
!      */
!     if (buflen <= 13 || buflen <= (size_t)2 + (size_t)prec) {
          PyErr_SetString(PyExc_OverflowError,
!     	        "formatted integer is too long (precision too large?)");
          return -1;
      }
! 
!     if ((flags & F_ALT) &&
!         (type == 'x' || type == 'X')) {
!         /* When converting under %#x or %#X, there are a number 
!          * of issues that cause pain:
!          * - when 0 is being converted, the C standard leaves off
!          *   the '0x' or '0X', which is inconsistent with other
!          *   %#x/%#X conversions and inconsistent with Python's
!          *   hex() function
!          * - there are platforms that violate the standard and
!          *   convert 0 with the '0x' or '0X'
!          *   (Metrowerks, Compaq Tru64)
!          * - there are platforms that give '0x' when converting
!          *   under %#X, but convert 0 in accordance with the 
!          *   standard (OS/2 EMX)
!          * 
!          * We can achieve the desired consistency by inserting our
!          * own '0x' or '0X' prefix, and substituting %x/%X in place
!          * of %#x/%#X.
!          *
!          * Note that this is the same approach as used in
!          * formatint() in stringobject.c
           */
!         PyOS_snprintf(fmt, sizeof(fmt), "0%c%%.%dl%c", 
!                       type, prec, type);
      }
!     else {
!         PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%dl%c",
!                       (flags&F_ALT) ? "#" : "", 
!                       prec, type);
      }
      return usprintf(buf, fmt, x);
  }