[Python-checkins] CVS: python/dist/src/Objects stringobject.c,2.103,2.104 unicodeobject.c,2.87,2.88

Tim Peters tim_one@users.sourceforge.net
Fri, 27 Apr 2001 22:38:29 -0700


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

Modified Files:
	stringobject.c unicodeobject.c 
Log Message:
A different approach to the problem reported in
Patch #419651: Metrowerks on Mac adds 0x itself
C std says %#x and %#X conversion of 0 do not add the 0x/0X base marker.
Metrowerks apparently does.  Mark Favas reported the same bug under a
Compaq compiler on Tru64 Unix, but no other libc broken in this respect
is known (known to be OK under MSVC and gcc).
So just try the damn thing at runtime and see what the platform does.
Note that we've always had bugs here, but never knew it before because
a relevant test case didn't exist before 2.1.


Index: stringobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v
retrieving revision 2.103
retrieving revision 2.104
diff -C2 -r2.103 -r2.104
*** stringobject.c	2001/04/20 19:13:02	2.103
--- stringobject.c	2001/04/28 05:38:26	2.104
***************
*** 142,147 ****
  {
      PyObject *buffer = NULL, *str;
!     
!     if (encoding == NULL) 
  	encoding = PyUnicode_GetDefaultEncoding();
  
--- 142,147 ----
  {
      PyObject *buffer = NULL, *str;
! 
!     if (encoding == NULL)
  	encoding = PyUnicode_GetDefaultEncoding();
  
***************
*** 170,174 ****
      Py_DECREF(buffer);
      return str;
!     
   onError:
      Py_XDECREF(buffer);
--- 170,174 ----
      Py_DECREF(buffer);
      return str;
! 
   onError:
      Py_XDECREF(buffer);
***************
*** 182,186 ****
  {
      PyObject *v, *str;
!     
      str = PyString_FromStringAndSize(s, size);
      if (str == NULL)
--- 182,186 ----
  {
      PyObject *v, *str;
! 
      str = PyString_FromStringAndSize(s, size);
      if (str == NULL)
***************
*** 196,200 ****
  {
      PyObject *v;
!     
      if (!PyString_Check(str)) {
          PyErr_BadArgument();
--- 196,200 ----
  {
      PyObject *v;
! 
      if (!PyString_Check(str)) {
          PyErr_BadArgument();
***************
*** 202,206 ****
      }
  
!     if (encoding == NULL) 
  	encoding = PyUnicode_GetDefaultEncoding();
  
--- 202,206 ----
      }
  
!     if (encoding == NULL)
  	encoding = PyUnicode_GetDefaultEncoding();
  
***************
*** 225,229 ****
      }
      return v;
!     
   onError:
      return NULL;
--- 225,229 ----
      }
      return v;
! 
   onError:
      return NULL;
***************
*** 273,277 ****
  
  /* Internal API needed by PyString_AsStringAndSize(): */
! extern 
  PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
  					    const char *errors);
--- 273,277 ----
  
  /* Internal API needed by PyString_AsStringAndSize(): */
! extern
  PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
  					    const char *errors);
***************
*** 416,420 ****
  		if (PyUnicode_Check(bb))
  		    return PyUnicode_Concat((PyObject *)a, bb);
! 		PyErr_Format(PyExc_TypeError, 
  			     "cannot add type \"%.200s\" to string",
  			     bb->ob_type->tp_name);
--- 416,420 ----
  		if (PyUnicode_Check(bb))
  		    return PyUnicode_Concat((PyObject *)a, bb);
! 		PyErr_Format(PyExc_TypeError,
  			     "cannot add type \"%.200s\" to string",
  			     bb->ob_type->tp_name);
***************
*** 909,913 ****
  	PyObject *subobj;
  
! 	if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", 
  		&subobj, _PyEval_SliceIndex, &i, _PyEval_SliceIndex, &last))
  		return -2;
--- 909,913 ----
  	PyObject *subobj;
  
! 	if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex",
  		&subobj, _PyEval_SliceIndex, &i, _PyEval_SliceIndex, &last))
  		return -2;
***************
*** 942,946 ****
  	else {
  		int j;
! 	    
          	if (n == 0 && i <= last)
  			return (long)last;
--- 942,946 ----
  	else {
  		int j;
! 
          	if (n == 0 && i <= last)
  			return (long)last;
***************
*** 949,953 ****
  				return (long)j;
  	}
! 	
  	return -1;
  }
--- 949,953 ----
  				return (long)j;
  	}
! 
  	return -1;
  }
***************
*** 1365,1369 ****
  	}
  	else if (PyUnicode_Check(tableobj)) {
! 		/* Unicode .translate() does not support the deletechars 
  		   parameter; instead a mapping to None will cause characters
  		   to be deleted. */
--- 1365,1369 ----
  	}
  	else if (PyUnicode_Check(tableobj)) {
! 		/* Unicode .translate() does not support the deletechars
  		   parameter; instead a mapping to None will cause characters
  		   to be deleted. */
***************
*** 1461,1465 ****
    MEM, the function returns -1.
  */
! static int 
  mymemfind(const char *mem, int len, const char *pat, int pat_len)
  {
--- 1461,1465 ----
    MEM, the function returns -1.
  */
! static int
  mymemfind(const char *mem, int len, const char *pat, int pat_len)
  {
***************
*** 1484,1488 ****
             mem=11111 and pat==11 also return 2.
   */
! static int 
  mymemcnt(const char *mem, int len, const char *pat, int pat_len)
  {
--- 1484,1488 ----
             mem=11111 and pat==11 also return 2.
   */
! static int
  mymemcnt(const char *mem, int len, const char *pat, int pat_len)
  {
***************
*** 1606,1610 ****
  	}
  	else if (PyUnicode_Check(subobj))
! 		return PyUnicode_Replace((PyObject *)self, 
  					 subobj, replobj, count);
  	else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))
--- 1606,1610 ----
  	}
  	else if (PyUnicode_Check(subobj))
! 		return PyUnicode_Replace((PyObject *)self,
  					 subobj, replobj, count);
  	else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))
***************
*** 1616,1620 ****
  	}
  	else if (PyUnicode_Check(replobj))
! 		return PyUnicode_Replace((PyObject *)self, 
  					 subobj, replobj, count);
  	else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len))
--- 1616,1620 ----
  	}
  	else if (PyUnicode_Check(replobj))
! 		return PyUnicode_Replace((PyObject *)self,
  					 subobj, replobj, count);
  	else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len))
***************
*** 1670,1674 ****
  	else if (PyUnicode_Check(subobj)) {
  	    	int rc;
! 		rc = PyUnicode_Tailmatch((PyObject *)self, 
  					  subobj, start, end, -1);
  		if (rc == -1)
--- 1670,1674 ----
  	else if (PyUnicode_Check(subobj)) {
  	    	int rc;
! 		rc = PyUnicode_Tailmatch((PyObject *)self,
  					  subobj, start, end, -1);
  		if (rc == -1)
***************
*** 1728,1732 ****
  	else if (PyUnicode_Check(subobj)) {
  	    	int rc;
! 		rc = PyUnicode_Tailmatch((PyObject *)self, 
  					  subobj, start, end, +1);
  		if (rc == -1)
--- 1728,1732 ----
  	else if (PyUnicode_Check(subobj)) {
  	    	int rc;
! 		rc = PyUnicode_Tailmatch((PyObject *)self,
  					  subobj, start, end, +1);
  		if (rc == -1)
***************
*** 1830,1836 ****
  }
  
! static 
! PyObject *pad(PyStringObject *self, 
! 	      int left, 
  	      int right,
  	      char fill)
--- 1830,1836 ----
  }
  
! static
! PyObject *pad(PyStringObject *self,
! 	      int left,
  	      int right,
  	      char fill)
***************
*** 1848,1858 ****
      }
  
!     u = PyString_FromStringAndSize(NULL, 
  				   left + PyString_GET_SIZE(self) + right);
      if (u) {
          if (left)
              memset(PyString_AS_STRING(u), fill, left);
!         memcpy(PyString_AS_STRING(u) + left, 
! 	       PyString_AS_STRING(self), 
  	       PyString_GET_SIZE(self));
          if (right)
--- 1848,1858 ----
      }
  
!     u = PyString_FromStringAndSize(NULL,
  				   left + PyString_GET_SIZE(self) + right);
      if (u) {
          if (left)
              memset(PyString_AS_STRING(u), fill, left);
!         memcpy(PyString_AS_STRING(u) + left,
! 	       PyString_AS_STRING(self),
  	       PyString_GET_SIZE(self));
          if (right)
***************
*** 2309,2313 ****
  
  
! static PyMethodDef 
  string_methods[] = {
  	/* Counterparts of the obsolete stropmodule functions; except
--- 2309,2313 ----
  
  
! static PyMethodDef
  string_methods[] = {
  	/* Counterparts of the obsolete stropmodule functions; except
***************
*** 2495,2499 ****
  	     fmt = %#.<prec>g
  	     buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
! 	        for any double rep.) 
  	     len = 1 + prec + 1 + 2 + 5 = 9 + prec
  	   If prec=0 the effective precision is 1 (the leading digit is
--- 2495,2499 ----
  	     fmt = %#.<prec>g
  	     buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
! 	        for any double rep.)
  	     len = 1 + prec + 1 + 2 + 5 = 9 + prec
  	   If prec=0 the effective precision is 1 (the leading digit is
***************
*** 2518,2522 ****
   *         "-"? ("0x" | "0X")? digit+
   *     "0x"/"0X" are present only for x and X conversions, with F_ALT
!  *         set in flags.  The case of hex digits will be correct, 
   *     There will be at least prec digits, zero-filled on the left if
   *         necessary to get that many.
--- 2518,2522 ----
   *         "-"? ("0x" | "0X")? digit+
   *     "0x"/"0X" are present only for x and X conversions, with F_ALT
!  *         set in flags.  The case of hex digits will be correct,
   *     There will be at least prec digits, zero-filled on the left if
   *         necessary to get that many.
***************
*** 2674,2680 ****
  	 * but we want it (for consistency with other %#x conversions, and
  	 * for consistency with Python's hex() function).
  	 */
! 	if (x == 0 && (flags & F_ALT) && (type == 'x' || type == 'X')) {
! 		assert(buf[1] != type);  /* else this C *is* adding 0x/0X */
  		memmove(buf+2, buf, strlen(buf) + 1);
  		buf[0] = '0';
--- 2674,2686 ----
  	 * 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';
***************
*** 2769,2773 ****
  			char formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */
  			char *fmt_start = fmt;
! 			
  			fmt++;
  			if (*fmt == '(') {
--- 2775,2779 ----
  			char formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */
  			char *fmt_start = fmt;
! 
  			fmt++;
  			if (*fmt == '(') {
***************
*** 2779,2783 ****
  				if (dict == NULL) {
  					PyErr_SetString(PyExc_TypeError,
! 						 "format requires a mapping"); 
  					goto error;
  				}
--- 2785,2789 ----
  				if (dict == NULL) {
  					PyErr_SetString(PyExc_TypeError,
! 						 "format requires a mapping");
  					goto error;
  				}
***************
*** 3126,3130 ****
  	Py_DECREF(args);
  	return w;
! 	
   error:
  	Py_DECREF(result);
--- 3132,3136 ----
  	Py_DECREF(args);
  	return w;
! 
   error:
  	Py_DECREF(result);

Index: unicodeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v
retrieving revision 2.87
retrieving revision 2.88
diff -C2 -r2.87 -r2.88
*** unicodeobject.c	2001/04/23 14:44:21	2.87
--- unicodeobject.c	2001/04/28 05:38:26	2.88
***************
*** 4738,4741 ****
--- 4738,4742 ----
      char fmt[64]; /* plenty big enough! */
      long x;
+     int use_native_c_format = 1;
  
      x = PyInt_AsLong(v);
***************
*** 4754,4762 ****
       * but we want it (for consistency with other %#x conversions, and
       * for consistency with Python's hex() function).
       */
!     if (x == 0 && (flags & F_ALT) && (type == 'x' || type == 'X'))
!         sprintf(fmt, "0%c%%%s.%dl%c", type, "#", prec, type);
!     else
!         sprintf(fmt, "%%%s.%dl%c", (flags & F_ALT) ? "#" : "", prec, type);
      return usprintf(buf, fmt, x);
  }
--- 4755,4773 ----
       * 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 (x == 0 && (flags & F_ALT) && (type == 'x' || type == 'X')) {
!         /* Only way to know what the platform does is to try it. */
!         sprintf(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;
!             sprintf(fmt, "0%c%%#.%dl%c", type, prec, type);
!         }
!     }
!     if (use_native_c_format)
!          sprintf(fmt, "%%%s.%dl%c", (flags & F_ALT) ? "#" : "", prec, type);
      return usprintf(buf, fmt, x);
  }