[Python-checkins] CVS: python/dist/src/Objects abstract.c,2.60.2.4,2.60.2.5 classobject.c,2.127.2.8,2.127.2.9 dictobject.c,2.80.2.14,2.80.2.15 fileobject.c,2.112.2.3,2.112.2.4 floatobject.c,2.81.6.4,2.81.6.5 frameobject.c,2.49.4.4,2.49.4.5 intobject.c,2.56.6.5,2.56.6.6 iterobject.c,1.3.2.2,1.3.2.3 listobject.c,2.92.6.9,2.92.6.10 longobject.c,1.71.6.3,1.71.6.4 object.c,2.124.4.22,2.124.4.23 rangeobject.c,2.24.6.3,2.24.6.4 stringobject.c,2.103.2.6,2.103.2.7 tupleobject.c,2.48.6.3,2.48.6.4 typeobject.c,2.16.8.62,2.16.8.63 unicodectype.c,2.7,2.7.8.1 unicodeobject.c,2.87.2.4,2.87.2.5

Tim Peters tim_one@users.sourceforge.net
Sat, 07 Jul 2001 15:55:33 -0700


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

Modified Files:
      Tag: descr-branch
	abstract.c classobject.c dictobject.c fileobject.c 
	floatobject.c frameobject.c intobject.c iterobject.c 
	listobject.c longobject.c object.c rangeobject.c 
	stringobject.c tupleobject.c typeobject.c unicodectype.c 
	unicodeobject.c 
Log Message:
Merge of trunk tag date2001-07-06 into descr-branch.


Index: abstract.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v
retrieving revision 2.60.2.4
retrieving revision 2.60.2.5
diff -C2 -r2.60.2.4 -r2.60.2.5
*** abstract.c	2001/06/11 19:09:46	2.60.2.4
--- abstract.c	2001/07/07 22:55:30	2.60.2.5
***************
*** 1177,1235 ****
  PySequence_Tuple(PyObject *v)
  {
! 	PySequenceMethods *m;
  
  	if (v == NULL)
  		return null_error();
  
  	if (PyTuple_Check(v)) {
  		Py_INCREF(v);
  		return v;
  	}
- 
  	if (PyList_Check(v))
  		return PyList_AsTuple(v);
- 
- 	/* There used to be code for strings here, but tuplifying strings is
- 	   not a common activity, so I nuked it.  Down with code bloat! */
  
! 	/* Generic sequence object */
! 	m = v->ob_type->tp_as_sequence;
! 	if (m && m->sq_item) {
! 		int i;
! 		PyObject *t;
! 		int n = PySequence_Size(v);
! 		if (n < 0)
! 			return NULL;
! 		t = PyTuple_New(n);
! 		if (t == NULL)
! 			return NULL;
! 		for (i = 0; ; i++) {
! 			PyObject *item = (*m->sq_item)(v, i);
! 			if (item == NULL) {
! 				if (PyErr_ExceptionMatches(PyExc_IndexError))
! 					PyErr_Clear();
! 				else {
! 					Py_DECREF(t);
! 					t = NULL;
! 				}
! 				break;
! 			}
! 			if (i >= n) {
! 				if (n < 500)
! 					n += 10;
! 				else
! 					n += 100;
! 				if (_PyTuple_Resize(&t, n, 0) != 0)
! 					break;
  			}
- 			PyTuple_SET_ITEM(t, i, item);
  		}
! 		if (i < n && t != NULL)
! 			_PyTuple_Resize(&t, i, 0);
! 		return t;
  	}
  
! 	/* None of the above */
! 	return type_error("tuple() argument must be a sequence");
  }
  
--- 1177,1244 ----
  PySequence_Tuple(PyObject *v)
  {
! 	PyObject *it;  /* iter(v) */
! 	int n;         /* guess for result tuple size */
! 	PyObject *result;
! 	int j;
  
  	if (v == NULL)
  		return null_error();
  
+ 	/* Special-case the common tuple and list cases, for efficiency. */
  	if (PyTuple_Check(v)) {
  		Py_INCREF(v);
  		return v;
  	}
  	if (PyList_Check(v))
  		return PyList_AsTuple(v);
  
! 	/* Get iterator. */
! 	it = PyObject_GetIter(v);
! 	if (it == NULL)
! 		return type_error("tuple() argument must support iteration");
! 
! 	/* Guess result size and allocate space. */
! 	n = PySequence_Size(v);
! 	if (n < 0) {
! 		PyErr_Clear();
! 		n = 10;  /* arbitrary */
! 	}
! 	result = PyTuple_New(n);
! 	if (result == NULL)
! 		goto Fail;
! 
! 	/* Fill the tuple. */
! 	for (j = 0; ; ++j) {
! 		PyObject *item = PyIter_Next(it);
! 		if (item == NULL) {
! 			if (PyErr_Occurred())
! 				goto Fail;
! 			break;
! 		}
! 		if (j >= n) {
! 			if (n < 500)
! 				n += 10;
! 			else
! 				n += 100;
! 			if (_PyTuple_Resize(&result, n) != 0) {
! 				Py_DECREF(item);
! 				goto Fail;
  			}
  		}
! 		PyTuple_SET_ITEM(result, j, item);
  	}
  
! 	/* Cut tuple back if guess was too large. */
! 	if (j < n &&
! 	    _PyTuple_Resize(&result, j) != 0)
! 		goto Fail;
! 
! 	Py_DECREF(it);
! 	return result;
! 
! Fail:
! 	Py_XDECREF(result);
! 	Py_DECREF(it);
! 	return NULL;
  }
  
***************
*** 1237,1243 ****
  PySequence_List(PyObject *v)
  {
  	if (v == NULL)
  		return null_error();
! 	return PyObject_CallFunction((PyObject *) &PyList_Type, "(O)", v);
  }
  
--- 1246,1317 ----
  PySequence_List(PyObject *v)
  {
+ 	PyObject *it;      /* iter(v) */
+ 	PyObject *result;  /* result list */
+ 	int n;		   /* guess for result list size */
+ 	int i;
+ 
  	if (v == NULL)
  		return null_error();
! 
! 	/* Special-case list(a_list), for speed. */
! 	if (PyList_Check(v))
! 		return PyList_GetSlice(v, 0, PyList_GET_SIZE(v));
! 
! 	/* Get iterator.  There may be some low-level efficiency to be gained
! 	 * by caching the tp_iternext slot instead of using PyIter_Next()
! 	 * later, but premature optimization is the root etc.
! 	 */
! 	it = PyObject_GetIter(v);
! 	if (it == NULL)
! 		return NULL;
! 
! 	/* Guess a result list size. */
! 	n = -1;	 /* unknown */
! 	if (PySequence_Check(v) &&
! 	    v->ob_type->tp_as_sequence->sq_length) {
! 		n = PySequence_Size(v);
! 		if (n < 0)
! 			PyErr_Clear();
! 	}
! 	if (n < 0)
! 		n = 8;	/* arbitrary */
! 	result = PyList_New(n);
! 	if (result == NULL) {
! 		Py_DECREF(it);
! 		return NULL;
! 	}
! 
! 	/* Run iterator to exhaustion. */
! 	for (i = 0; ; i++) {
! 		PyObject *item = PyIter_Next(it);
! 		if (item == NULL) {
! 			if (PyErr_Occurred()) {
! 				Py_DECREF(result);
! 				result = NULL;
! 			}
! 			break;
! 		}
! 		if (i < n)
! 			PyList_SET_ITEM(result, i, item); /* steals ref */
! 		else {
! 			int status = PyList_Append(result, item);
! 			Py_DECREF(item);  /* append creates a new ref */
! 			if (status < 0) {
! 				Py_DECREF(result);
! 				result = NULL;
! 				break;
! 			}
! 		}
! 	}
! 
! 	/* Cut back result list if initial guess was too large. */
! 	if (i < n && result != NULL) {
! 		if (PyList_SetSlice(result, i, n, (PyObject *)NULL) != 0) {
! 			Py_DECREF(result);
! 			result = NULL;
! 		}
! 	}
! 	Py_DECREF(it);
! 	return result;
  }
  
***************
*** 1260,1268 ****
  }
  
  int
  PySequence_Count(PyObject *s, PyObject *o)
  {
! 	int l, i, n, cmp, err;
! 	PyObject *item;
  
  	if (s == NULL || o == NULL) {
--- 1334,1343 ----
  }
  
+ /* Return # of times o appears in s. */
  int
  PySequence_Count(PyObject *s, PyObject *o)
  {
! 	int n;  /* running count of o hits */
! 	PyObject *it;  /* iter(s) */
  
  	if (s == NULL || o == NULL) {
***************
*** 1270,1333 ****
  		return -1;
  	}
! 	
! 	l = PySequence_Size(s);
! 	if (l < 0)
  		return -1;
  
  	n = 0;
! 	for (i = 0; i < l; i++) {
! 		item = PySequence_GetItem(s, i);
! 		if (item == NULL)
! 			return -1;
! 		err = PyObject_Cmp(item, o, &cmp);
  		Py_DECREF(item);
! 		if (err < 0)
! 			return err;
! 		if (cmp == 0)
  			n++;
  	}
  	return n;
  }
  
  int
! PySequence_Contains(PyObject *w, PyObject *v) /* v in w */
  {
! 	int i, cmp;
! 	PyObject *x;
! 	PySequenceMethods *sq;
! 
! 	if(PyType_HasFeature(w->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
! 		sq = w->ob_type->tp_as_sequence;
! 	        if(sq != NULL && sq->sq_contains != NULL)
! 			return (*sq->sq_contains)(w, v);
! 	}
! 	
! 	/* If there is no better way to check whether an item is is contained,
! 	   do it the hard way */
! 	sq = w->ob_type->tp_as_sequence;
! 	if (sq == NULL || sq->sq_item == NULL) {
  		PyErr_SetString(PyExc_TypeError,
! 			"'in' or 'not in' needs sequence right argument");
  		return -1;
  	}
  
! 	for (i = 0; ; i++) {
! 		x = (*sq->sq_item)(w, i);
! 		if (x == NULL) {
! 			if (PyErr_ExceptionMatches(PyExc_IndexError)) {
! 				PyErr_Clear();
! 				break;
! 			}
! 			return -1;
  		}
! 		cmp = PyObject_RichCompareBool(v, x, Py_EQ);
! 		Py_XDECREF(x);
! 		if (cmp > 0)
! 			return 1;
! 		if (cmp < 0)
! 			return -1;
  	}
  
! 	return 0;
  }
  
--- 1345,1429 ----
  		return -1;
  	}
! 
! 	it = PyObject_GetIter(s);
! 	if (it == NULL) {
! 		type_error(".count() requires iterable argument");
  		return -1;
+ 	}
  
  	n = 0;
! 	for (;;) {
! 		int cmp;
! 		PyObject *item = PyIter_Next(it);
! 		if (item == NULL) {
! 			if (PyErr_Occurred())
! 				goto Fail;
! 			break;
! 		}
! 		cmp = PyObject_RichCompareBool(o, item, Py_EQ);
  		Py_DECREF(item);
! 		if (cmp < 0)
! 			goto Fail;
! 		if (cmp > 0) {
! 			if (n == INT_MAX) {
! 				PyErr_SetString(PyExc_OverflowError,
! 				                "count exceeds C int size");
! 				goto Fail;
! 			}
  			n++;
+ 		}
  	}
+ 	Py_DECREF(it);
  	return n;
+ 
+ Fail:
+ 	Py_DECREF(it);
+ 	return -1;
  }
  
+ /* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
+  * Always uses the iteration protocol, and only Py_EQ comparison.
+  */
  int
! _PySequence_IterContains(PyObject *seq, PyObject *ob)
  {
! 	int result;
! 	PyObject *it = PyObject_GetIter(seq);
! 	if (it == NULL) {
  		PyErr_SetString(PyExc_TypeError,
! 			"'in' or 'not in' needs iterable right argument");
  		return -1;
  	}
  
! 	for (;;) {
! 		int cmp;
! 		PyObject *item = PyIter_Next(it);
! 		if (item == NULL) {
! 			result = PyErr_Occurred() ? -1 : 0;
! 			break;
  		}
! 		cmp = PyObject_RichCompareBool(ob, item, Py_EQ);
! 		Py_DECREF(item);
! 		if (cmp == 0)
! 			continue;
! 		result = cmp > 0 ? 1 : -1;
! 		break;
  	}
+ 	Py_DECREF(it);
+ 	return result;
+ }
  
! /* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
!  * Use sq_contains if possible, else defer to _PySequence_IterContains().
!  */
! int
! PySequence_Contains(PyObject *seq, PyObject *ob)
! {
! 	if (PyType_HasFeature(seq->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
! 		PySequenceMethods *sqm = seq->ob_type->tp_as_sequence;
! 	        if (sqm != NULL && sqm->sq_contains != NULL)
! 			return (*sqm->sq_contains)(seq, ob);
! 	}
! 	return _PySequence_IterContains(seq, ob);
  }
  

Index: classobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v
retrieving revision 2.127.2.8
retrieving revision 2.127.2.9
diff -C2 -r2.127.2.8 -r2.127.2.9
*** classobject.c	2001/07/03 09:56:52	2.127.2.8
--- classobject.c	2001/07/07 22:55:30	2.127.2.9
***************
*** 1165,1173 ****
  }
  
! static int instance_contains(PyInstanceObject *inst, PyObject *member)
  {
  	static PyObject *__contains__;
! 	PyObject *func, *arg, *res;
! 	int ret;
  
  	if(__contains__ == NULL) {
--- 1165,1177 ----
  }
  
! static int
! instance_contains(PyInstanceObject *inst, PyObject *member)
  {
  	static PyObject *__contains__;
! 	PyObject *func;
! 
! 	/* Try __contains__ first.
! 	 * If that can't be done, try iterator-based searching.
! 	 */
  
  	if(__contains__ == NULL) {
***************
*** 1177,1219 ****
  	}
  	func = instance_getattr(inst, __contains__);
! 	if(func == NULL) {
! 		/* fall back to previous behavior */
! 		int i, cmp_res;
! 
! 		if(!PyErr_ExceptionMatches(PyExc_AttributeError))
  			return -1;
- 		PyErr_Clear();
- 		for(i=0;;i++) {
- 			PyObject *obj = instance_item(inst, i);
- 			int ret = 0;
- 
- 			if(obj == NULL) {
- 				if(!PyErr_ExceptionMatches(PyExc_IndexError))
- 					return -1;
- 				PyErr_Clear();
- 				return 0;
- 			}
- 			if(PyObject_Cmp(obj, member, &cmp_res) == -1)
- 				ret = -1;
- 			if(cmp_res == 0) 
- 				ret = 1;
- 			Py_DECREF(obj);
- 			if(ret)
- 				return ret;
  		}
! 	}
! 	arg = Py_BuildValue("(O)", member);
! 	if(arg == NULL) {
  		Py_DECREF(func);
! 		return -1;
  	}
! 	res = PyEval_CallObject(func, arg);
! 	Py_DECREF(func);
! 	Py_DECREF(arg);
! 	if(res == NULL) 
  		return -1;
- 	ret = PyObject_IsTrue(res);
- 	Py_DECREF(res);
- 	return ret;
  }
  
--- 1181,1212 ----
  	}
  	func = instance_getattr(inst, __contains__);
! 	if (func) {
! 		PyObject *res;
! 		int ret;
! 		PyObject *arg = Py_BuildValue("(O)", member);
! 		if(arg == NULL) {
! 			Py_DECREF(func);
  			return -1;
  		}
! 		res = PyEval_CallObject(func, arg);
  		Py_DECREF(func);
! 		Py_DECREF(arg);
! 		if(res == NULL) 
! 			return -1;
! 		ret = PyObject_IsTrue(res);
! 		Py_DECREF(res);
! 		return ret;
  	}
! 
! 	/* Couldn't find __contains__. */
! 	if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
! 		/* Assume the failure was simply due to that there is no
! 		 * __contains__ attribute, and try iterating instead.
! 		 */
! 		PyErr_Clear();
! 		return _PySequence_IterContains((PyObject *)inst, member);
! 	}
! 	else
  		return -1;
  }
  
***************
*** 1692,1708 ****
  
  /* Map rich comparison operators to their __xx__ namesakes */
! static char *name_op[] = {
! 	"__lt__",
! 	"__le__",
! 	"__eq__",
! 	"__ne__",
! 	"__gt__",
! 	"__ge__",
! };
  
  static PyObject *
  half_richcompare(PyObject *v, PyObject *w, int op)
  {
- 	PyObject *name;
  	PyObject *method;
  	PyObject *args;
--- 1685,1718 ----
  
  /* Map rich comparison operators to their __xx__ namesakes */
! #define NAME_OPS 6
! static PyObject **name_op = NULL;
! 
! static int 
! init_name_op(void)
! {
! 	int i;
! 	char *_name_op[] = {
! 		"__lt__",
! 		"__le__",
! 		"__eq__",
! 		"__ne__",
! 		"__gt__",
! 		"__ge__",
! 	};
  
+ 	name_op = (PyObject **)malloc(sizeof(PyObject *) * NAME_OPS);
+ 	if (name_op == NULL)
+ 		return -1;
+ 	for (i = 0; i < NAME_OPS; ++i) {
+ 		name_op[i] = PyString_InternFromString(_name_op[i]);
+ 		if (name_op[i] == NULL)
+ 			return -1;
+ 	}
+ 	return 0;
+ }
+ 
  static PyObject *
  half_richcompare(PyObject *v, PyObject *w, int op)
  {
  	PyObject *method;
  	PyObject *args;
***************
*** 1710,1727 ****
  
  	assert(PyInstance_Check(v));
- 
- 	name = PyString_InternFromString(name_op[op]);
- 	if (name == NULL)
- 		return NULL;
  
! 	method = PyObject_GetAttr(v, name);
! 	Py_DECREF(name);
! 	if (method == NULL) {
! 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
  			return NULL;
! 		PyErr_Clear();
! 		res = Py_NotImplemented;
! 		Py_INCREF(res);
! 		return res;
  	}
  
--- 1720,1750 ----
  
  	assert(PyInstance_Check(v));
  
! 	if (name_op == NULL) {
! 		if (init_name_op() < 0)
  			return NULL;
! 	}
! 	/* If the instance doesn't define an __getattr__ method, use
! 	   instance_getattr2 directly because it will not set an
! 	   exception on failure. */
! 	if (((PyInstanceObject *)v)->in_class->cl_getattr == NULL) {
! 		method = instance_getattr2((PyInstanceObject *)v, 
! 					   name_op[op]);
! 		if (method == NULL) {
! 			assert(!PyErr_Occurred());
! 			res = Py_NotImplemented;
! 			Py_INCREF(res);
! 			return res;
! 		}
! 	} else {
! 		method = PyObject_GetAttr(v, name_op[op]);
! 		if (method == NULL) {
! 			if (!PyErr_ExceptionMatches(PyExc_AttributeError))
! 				return NULL;
! 			PyErr_Clear();
! 			res = Py_NotImplemented;
! 			Py_INCREF(res);
! 			return res;
! 		}
  	}
  
***************
*** 2184,2188 ****
  	(setattrofunc)instancemethod_setattro,	/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC,
  	0,					/* tp_doc */
  	(traverseproc)instancemethod_traverse,	/* tp_traverse */
--- 2207,2211 ----
  	(setattrofunc)instancemethod_setattro,	/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC,     /* tp_flags */
  	0,					/* tp_doc */
  	(traverseproc)instancemethod_traverse,	/* tp_traverse */

Index: dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.80.2.14
retrieving revision 2.80.2.15
diff -C2 -r2.80.2.14 -r2.80.2.15
*** dictobject.c	2001/06/28 16:36:53	2.80.2.14
--- dictobject.c	2001/07/07 22:55:30	2.80.2.15
***************
*** 7,55 ****
  typedef PyDictObject dictobject;
  
! /*
!  * MINSIZE is the minimum size of a dictionary.
!  */
! 
! #define MINSIZE 4
! 
! /* define this out if you don't want conversion statistics on exit */
  #undef SHOW_CONVERSION_COUNTS
[...1830 lines suppressed...]
  	}
! 	if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, NULL)) {
! 		Py_INCREF(key);
! 		return key;
  	}
  	return NULL;
--- 1842,1854 ----
  static PyObject *dictiter_iternext(dictiterobject *di)
  {
! 	PyObject *key, *value;
  
! 	if (di->di_used != di->di_dict->ma_used) {
  		PyErr_SetString(PyExc_RuntimeError,
  				"dictionary changed size during iteration");
  		return NULL;
  	}
! 	if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, &value)) {
! 		return (*di->di_select)(key, value);
  	}
  	return NULL;

Index: fileobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v
retrieving revision 2.112.2.3
retrieving revision 2.112.2.4
diff -C2 -r2.112.2.3 -r2.112.2.4
*** fileobject.c	2001/06/06 14:27:54	2.112.2.3
--- fileobject.c	2001/07/07 22:55:30	2.112.2.4
***************
*** 1285,1300 ****
  
  static PyObject *
! file_getiter(PyFileObject *f)
  {
! 	static PyObject *es;
! 	PyObject *iter;
! 	PyObject *rl = Py_FindMethod(file_methods, (PyObject *)f, "readline");
! 	if (rl == NULL)
! 		return NULL;
! 	if (es == NULL)
! 		es = PyString_FromString("");
! 	iter = PyCallIter_New(rl, es);
! 	Py_DECREF(rl);
! 	return iter;
  }
  
--- 1285,1291 ----
  
  static PyObject *
! file_getiter(PyObject *f)
  {
! 	return PyObject_CallMethod(f, "xreadlines", "");
  }
  
***************
*** 1326,1330 ****
  	0,					/* tp_richcompare */
  	0,					/* tp_weaklistoffset */
! 	(getiterfunc)file_getiter,		/* tp_iter */
  	0,					/* tp_iternext */
  	file_methods,				/* tp_methods */
--- 1317,1321 ----
  	0,					/* tp_richcompare */
  	0,					/* tp_weaklistoffset */
! 	file_getiter,				/* tp_iter */
  	0,					/* tp_iternext */
  	file_methods,				/* tp_methods */

Index: floatobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v
retrieving revision 2.81.6.4
retrieving revision 2.81.6.5
diff -C2 -r2.81.6.4 -r2.81.6.5
*** floatobject.c	2001/06/14 01:01:16	2.81.6.4
--- floatobject.c	2001/07/07 22:55:30	2.81.6.5
***************
*** 312,315 ****
--- 312,321 ----
  }
  
+ void
+ PyFloat_AsReprString(char *buf, PyFloatObject *v)
+ {
+ 	PyFloat_AsStringEx(buf, v, PREC_REPR);
+ }
+ 
  /* ARGSUSED */
  static int

Index: frameobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/frameobject.c,v
retrieving revision 2.49.4.4
retrieving revision 2.49.4.5
diff -C2 -r2.49.4.4 -r2.49.4.5
*** frameobject.c	2001/06/11 18:40:38	2.49.4.4
--- frameobject.c	2001/07/07 22:55:30	2.49.4.5
***************
*** 66,69 ****
--- 66,70 ----
  	int i, slots;
  	PyObject **fastlocals;
+ 	PyObject **p;
  
  	Py_TRASHCAN_SAFE_BEGIN(f)
***************
*** 75,78 ****
--- 76,85 ----
  	}
  
+ 	/* Free stack */
+ 	if (f->f_stacktop != NULL) {
+ 		for (p = f->f_valuestack; p < f->f_stacktop; p++)
+ 			Py_XDECREF(*p);
+ 	}
+ 	
  	Py_XDECREF(f->f_back);
  	Py_XDECREF(f->f_code);
***************
*** 239,242 ****
--- 246,250 ----
  
  	f->f_valuestack = f->f_localsplus + (f->f_nlocals + ncells + nfrees);
+ 	f->f_stacktop = f->f_valuestack;
  
  	return f;
***************
*** 301,310 ****
  		Py_XINCREF(value);
  		if (deref) {
! 			if (value) {
  				if (PyCell_Set(values[j], value) < 0)
  					PyErr_Clear();
- 			} else if (clear) {
- 				Py_XDECREF(values[j]);
- 				values[j] = value;
  			}
  		} else if (value != NULL || clear) {
--- 309,315 ----
  		Py_XINCREF(value);
  		if (deref) {
! 			if (value || clear) {
  				if (PyCell_Set(values[j], value) < 0)
  					PyErr_Clear();
  			}
  		} else if (value != NULL || clear) {
***************
*** 388,395 ****
  		dict_to_map(f->f_code->co_cellvars, 
  			    PyTuple_GET_SIZE(f->f_code->co_cellvars),
! 			    locals, fast, 1, clear);
  		dict_to_map(f->f_code->co_freevars, 
  			    PyTuple_GET_SIZE(f->f_code->co_freevars),
! 			    locals, fast, 1, clear);
  	}
  	PyErr_Restore(error_type, error_value, error_traceback);
--- 393,400 ----
  		dict_to_map(f->f_code->co_cellvars, 
  			    PyTuple_GET_SIZE(f->f_code->co_cellvars),
! 			    locals, fast + f->f_nlocals, 1, clear);
  		dict_to_map(f->f_code->co_freevars, 
  			    PyTuple_GET_SIZE(f->f_code->co_freevars),
! 			    locals, fast + f->f_nlocals + f->f_ncells, 1, clear);
  	}
  	PyErr_Restore(error_type, error_value, error_traceback);

Index: intobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v
retrieving revision 2.56.6.5
retrieving revision 2.56.6.6
diff -C2 -r2.56.6.5 -r2.56.6.6
*** intobject.c	2001/06/14 00:53:34	2.56.6.5
--- intobject.c	2001/07/07 22:55:30	2.56.6.6
***************
*** 435,470 ****
  
  static int
! i_divmod(register long xi, register long yi,
           long *p_xdivy, long *p_xmody)
  {
  	long xdivy, xmody;
  	
! 	if (yi == 0) {
  		PyErr_SetString(PyExc_ZeroDivisionError,
  				"integer division or modulo by zero");
  		return -1;
  	}
! 	if (yi < 0) {
! 		if (xi < 0) {
! 			if (yi == -1 && -xi < 0) {
! 				/* most negative / -1 */
! 				err_ovf("integer division");
! 				return -1;
! 			}
! 			xdivy = -xi / -yi;
! 		}
! 		else
! 			xdivy = - (xi / -yi);
! 	}
! 	else {
! 		if (xi < 0)
! 			xdivy = - (-xi / yi);
! 		else
! 			xdivy = xi / yi;
  	}
! 	xmody = xi - xdivy*yi;
! 	if ((xmody < 0 && yi > 0) || (xmody > 0 && yi < 0)) {
! 		xmody += yi;
! 		xdivy -= 1;
  	}
  	*p_xdivy = xdivy;
--- 435,464 ----
  
  static int
! i_divmod(register long x, register long y,
           long *p_xdivy, long *p_xmody)
  {
  	long xdivy, xmody;
  	
! 	if (y == 0) {
  		PyErr_SetString(PyExc_ZeroDivisionError,
  				"integer division or modulo by zero");
  		return -1;
  	}
! 	/* (-sys.maxint-1)/-1 is the only overflow case. */
! 	if (y == -1 && x < 0 && x == -x) {
! 		err_ovf("integer division");
! 		return -1;
  	}
! 	xdivy = x / y;
! 	xmody = x - xdivy * y;
! 	/* If the signs of x and y differ, and the remainder is non-0,
! 	 * C89 doesn't define whether xdivy is now the floor or the
! 	 * ceiling of the infinitely precise quotient.  We want the floor,
! 	 * and we have it iff the remainder's sign matches y's.
! 	 */
! 	if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
! 		xmody += y;
! 		--xdivy;
! 		assert(xmody && ((y ^ xmody) >= 0));
  	}
  	*p_xdivy = xdivy;

Index: iterobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/iterobject.c,v
retrieving revision 1.3.2.2
retrieving revision 1.3.2.3
diff -C2 -r1.3.2.2 -r1.3.2.3
*** iterobject.c	2001/06/06 14:27:54	1.3.2.2
--- iterobject.c	2001/07/07 22:55:30	1.3.2.3
***************
*** 46,50 ****
  }
  
- /* Return (value, 0) if OK; (NULL, 0) at end; (NULL, -1) if exception */
  static PyObject *
  iter_iternext(PyObject *iterator)
--- 46,49 ----

Index: listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.92.6.9
retrieving revision 2.92.6.10
diff -C2 -r2.92.6.9 -r2.92.6.10
*** listobject.c	2001/06/17 23:18:19	2.92.6.9
--- listobject.c	2001/07/07 22:55:30	2.92.6.10
***************
*** 10,25 ****
  #endif
  
- #define ROUNDUP(n, PyTryBlock) \
- 	((((n)+(PyTryBlock)-1)/(PyTryBlock))*(PyTryBlock))
- 
  static int
  roundupsize(int n)
  {
! 	if (n < 500)
! 		return ROUNDUP(n, 10);
! 	else
! 		return ROUNDUP(n, 100);
! }
  
  #define NRESIZE(var, type, nitems) PyMem_RESIZE(var, type, roundupsize(nitems))
  
--- 10,48 ----
  #endif
  
  static int
  roundupsize(int n)
  {
! 	unsigned int nbits = 0;
! 	unsigned int n2 = (unsigned int)n >> 5;
  
+ 	/* Round up: 
+ 	 * If n <       256, to a multiple of        8.
+ 	 * If n <      2048, to a multiple of       64.
+ 	 * If n <     16384, to a multiple of      512.
+ 	 * If n <    131072, to a multiple of     4096.
+ 	 * If n <   1048576, to a multiple of    32768.
+ 	 * If n <   8388608, to a multiple of   262144.
+ 	 * If n <  67108864, to a multiple of  2097152.
+ 	 * If n < 536870912, to a multiple of 16777216.
+ 	 * ...
+ 	 * If n < 2**(5+3*i), to a multiple of 2**(3*i).
+ 	 *
+ 	 * This over-allocates proportional to the list size, making room
+ 	 * for additional growth.  The over-allocation is mild, but is
+ 	 * enough to give linear-time amortized behavior over a long
+ 	 * sequence of appends() in the presence of a poorly-performing
+ 	 * system realloc() (which is a reality, e.g., across all flavors
+ 	 * of Windows, with Win9x behavior being particularly bad -- and
+ 	 * we've still got address space fragmentation problems on Win9x
+ 	 * even with this scheme, although it requires much longer lists to
+ 	 * provoke them than it used to).
+ 	 */
+ 	do {
+ 		n2 >>= 3;
+ 		nbits += 3;
+ 	} while (n2);
+ 	return ((n >> nbits) + 1) << nbits;
+  }
+ 
  #define NRESIZE(var, type, nitems) PyMem_RESIZE(var, type, roundupsize(nitems))
  
***************
*** 224,247 ****
  list_repr(PyListObject *v)
  {
- 	PyObject *s, *comma;
  	int i;
  
  	i = Py_ReprEnter((PyObject*)v);
  	if (i != 0) {
! 		if (i > 0)
! 			return PyString_FromString("[...]");
! 		return NULL;
  	}
! 	s = PyString_FromString("[");
! 	comma = PyString_FromString(", ");
! 	for (i = 0; i < v->ob_size && s != NULL; i++) {
! 		if (i > 0)
! 			PyString_Concat(&s, comma);
! 		PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i]));
  	}
! 	Py_XDECREF(comma);
! 	PyString_ConcatAndDel(&s, PyString_FromString("]"));
  	Py_ReprLeave((PyObject *)v);
! 	return s;
  }
  
--- 247,312 ----
  list_repr(PyListObject *v)
  {
  	int i;
+ 	PyObject *s, *temp;
+ 	PyObject *pieces = NULL, *result = NULL;
  
  	i = Py_ReprEnter((PyObject*)v);
  	if (i != 0) {
! 		return i > 0 ? PyString_FromString("[...]") : NULL;
  	}
! 
! 	if (v->ob_size == 0) {
! 		result = PyString_FromString("[]");
! 		goto Done;
  	}
! 
! 	pieces = PyList_New(0);
! 	if (pieces == NULL)
! 		goto Done;
! 
! 	/* Do repr() on each element.  Note that this may mutate the list,
! 	   so must refetch the list size on each iteration. */
! 	for (i = 0; i < v->ob_size; ++i) {
! 		int status;
! 		s = PyObject_Repr(v->ob_item[i]);
! 		if (s == NULL)
! 			goto Done;
! 		status = PyList_Append(pieces, s);
! 		Py_DECREF(s);  /* append created a new ref */
! 		if (status < 0)
! 			goto Done;
! 	}
! 
! 	/* Add "[]" decorations to the first and last items. */
! 	assert(PyList_GET_SIZE(pieces) > 0);
! 	s = PyString_FromString("[");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyList_GET_ITEM(pieces, 0);
! 	PyString_ConcatAndDel(&s, temp);
! 	PyList_SET_ITEM(pieces, 0, s);
! 	if (s == NULL)
! 		goto Done;
! 
! 	s = PyString_FromString("]");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
! 	PyString_ConcatAndDel(&temp, s);
! 	PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
! 	if (temp == NULL)
! 		goto Done;
! 
! 	/* Paste them all together with ", " between. */
! 	s = PyString_FromString(", ");
! 	if (s == NULL)
! 		goto Done;
! 	result = _PyString_Join(s, pieces);
! 	Py_DECREF(s);	
! 
! Done:
! 	Py_XDECREF(pieces);
  	Py_ReprLeave((PyObject *)v);
! 	return result;
  }
  
***************
*** 558,580 ****
  }
  
- /* Define NO_STRICT_LIST_APPEND to enable multi-argument append() */
- 
- #ifndef NO_STRICT_LIST_APPEND
- #define PyArg_ParseTuple_Compat1 PyArg_ParseTuple
- #else
- #define PyArg_ParseTuple_Compat1(args, format, ret) \
- ( \
- 	PyTuple_GET_SIZE(args) > 1 ? (*ret = args, 1) : \
- 	PyTuple_GET_SIZE(args) == 1 ? (*ret = PyTuple_GET_ITEM(args, 0), 1) : \
- 	PyArg_ParseTuple(args, format, ret) \
- )
- #endif
- 
- 
  static PyObject *
  listappend(PyListObject *self, PyObject *args)
  {
  	PyObject *v;
! 	if (!PyArg_ParseTuple_Compat1(args, "O:append", &v))
  		return NULL;
  	return ins(self, (int) self->ob_size, v);
--- 623,631 ----
  }
  
  static PyObject *
  listappend(PyListObject *self, PyObject *args)
  {
  	PyObject *v;
! 	if (!PyArg_ParseTuple(args, "O:append", &v))
  		return NULL;
  	return ins(self, (int) self->ob_size, v);
***************
*** 640,644 ****
  list_inplace_concat(PyListObject *self, PyObject *other)
  {
! 	other = PySequence_Fast(other, "argument to += must be a sequence");
  	if (!other)
  		return NULL;
--- 691,695 ----
  list_inplace_concat(PyListObject *self, PyObject *other)
  {
! 	other = PySequence_Fast(other, "argument to += must be iterable");
  	if (!other)
  		return NULL;
***************
*** 660,664 ****
  		return NULL;
  
! 	b = PySequence_Fast(b, "list.extend() argument must be a sequence");
  	if (!b)
  		return NULL;
--- 711,715 ----
  		return NULL;
  
! 	b = PySequence_Fast(b, "list.extend() argument must be iterable");
  	if (!b)
  		return NULL;
***************
*** 1345,1349 ****
  	PyObject *v;
  
! 	if (!PyArg_ParseTuple_Compat1(args, "O:index", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {
--- 1396,1400 ----
  	PyObject *v;
  
! 	if (!PyArg_ParseTuple(args, "O:index", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {
***************
*** 1365,1369 ****
  	PyObject *v;
  
! 	if (!PyArg_ParseTuple_Compat1(args, "O:count", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {
--- 1416,1420 ----
  	PyObject *v;
  
! 	if (!PyArg_ParseTuple(args, "O:count", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {
***************
*** 1383,1387 ****
  	PyObject *v;
  
! 	if (!PyArg_ParseTuple_Compat1(args, "O:remove", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {
--- 1434,1438 ----
  	PyObject *v;
  
! 	if (!PyArg_ParseTuple(args, "O:remove", &v))
  		return NULL;
  	for (i = 0; i < self->ob_size; i++) {

Index: longobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v
retrieving revision 1.71.6.3
retrieving revision 1.71.6.4
diff -C2 -r1.71.6.3 -r1.71.6.4
*** longobject.c	2001/06/14 01:01:16	1.71.6.3
--- longobject.c	2001/07/07 22:55:30	1.71.6.4
***************
*** 58,76 ****
  PyLong_FromLong(long ival)
  {
! 	/* Assume a C long fits in at most 5 'digits' */
! 	/* Works on both 32- and 64-bit machines */
! 	PyLongObject *v = _PyLong_New(5);
  	if (v != NULL) {
! 		unsigned long t = ival;
! 		int i;
! 		if (ival < 0) {
! 			t = -ival;
! 			v->ob_size = -(v->ob_size);
!   		}
! 		for (i = 0; i < 5; i++) {
! 			v->ob_digit[i] = (digit) (t & MASK);
  			t >>= SHIFT;
  		}
- 		v = long_normalize(v);
  	}
  	return (PyObject *)v;
--- 58,89 ----
  PyLong_FromLong(long ival)
  {
! 	PyLongObject *v;
! 	unsigned long t;  /* unsigned so >> doesn't propagate sign bit */
! 	int ndigits = 0;
! 	int negative = 0;
! 
! 	if (ival < 0) {
! 		ival = -ival;
! 		negative = 1;
! 	}
! 
! 	/* Count the number of Python digits.
! 	   We used to pick 5 ("big enough for anything"), but that's a
! 	   waste of time and space given that 5*15 = 75 bits are rarely
! 	   needed. */
! 	t = (unsigned long)ival;
! 	while (t) {
! 		++ndigits;
! 		t >>= SHIFT;
! 	}
! 	v = _PyLong_New(ndigits);
  	if (v != NULL) {
! 		digit *p = v->ob_digit;
! 		v->ob_size = negative ? -ndigits : ndigits;
! 		t = (unsigned long)ival;
! 		while (t) {
! 			*p++ = (digit)(t & MASK);
  			t >>= SHIFT;
  		}
  	}
  	return (PyObject *)v;
***************
*** 82,96 ****
  PyLong_FromUnsignedLong(unsigned long ival)
  {
! 	/* Assume a C long fits in at most 5 'digits' */
! 	/* Works on both 32- and 64-bit machines */
! 	PyLongObject *v = _PyLong_New(5);
  	if (v != NULL) {
! 		unsigned long t = ival;
! 		int i;
! 		for (i = 0; i < 5; i++) {
! 			v->ob_digit[i] = (digit) (t & MASK);
! 			t >>= SHIFT;
  		}
- 		v = long_normalize(v);
  	}
  	return (PyObject *)v;
--- 95,116 ----
  PyLong_FromUnsignedLong(unsigned long ival)
  {
! 	PyLongObject *v;
! 	unsigned long t;
! 	int ndigits = 0;
! 
! 	/* Count the number of Python digits. */
! 	t = (unsigned long)ival;
! 	while (t) {
! 		++ndigits;
! 		t >>= SHIFT;
! 	}
! 	v = _PyLong_New(ndigits);
  	if (v != NULL) {
! 		digit *p = v->ob_digit;
! 		v->ob_size = ndigits;
! 		while (ival) {
! 			*p++ = (digit)(ival & MASK);
! 			ival >>= SHIFT;
  		}
  	}
  	return (PyObject *)v;
***************
*** 212,215 ****
--- 232,479 ----
  }
  
+ PyObject *
+ _PyLong_FromByteArray(const unsigned char* bytes, size_t n,
+ 		      int little_endian, int is_signed)
+ {
+ 	const unsigned char* pstartbyte;/* LSB of bytes */
+ 	int incr;			/* direction to move pstartbyte */
+ 	const unsigned char* pendbyte;	/* MSB of bytes */
+ 	size_t numsignificantbytes;	/* number of bytes that matter */
+ 	size_t ndigits;			/* number of Python long digits */
+ 	PyLongObject* v;		/* result */
+ 	int idigit = 0;  		/* next free index in v->ob_digit */
+ 
+ 	if (n == 0)
+ 		return PyLong_FromLong(0L);
+ 
+ 	if (little_endian) {
+ 		pstartbyte = bytes;
+ 		pendbyte = bytes + n - 1;
+ 		incr = 1;
+ 	}
+ 	else {
+ 		pstartbyte = bytes + n - 1;
+ 		pendbyte = bytes;
+ 		incr = -1;
+ 	}
+ 
+ 	if (is_signed)
+ 		is_signed = *pendbyte >= 0x80;
+ 
+ 	/* Compute numsignificantbytes.  This consists of finding the most
+ 	   significant byte.  Leading 0 bytes are insignficant if the number
+ 	   is positive, and leading 0xff bytes if negative. */
+ 	{
+ 		size_t i;
+ 		const unsigned char* p = pendbyte;
+ 		const int pincr = -incr;  /* search MSB to LSB */
+ 		const unsigned char insignficant = is_signed ? 0xff : 0x00;
+ 
+ 		for (i = 0; i < n; ++i, p += pincr) {
+ 			if (*p != insignficant)
+ 				break;
+ 		}
+ 		numsignificantbytes = n - i;
+ 		/* 2's-comp is a bit tricky here, e.g. 0xff00 == -0x0100, so
+ 		   actually has 2 significant bytes.  OTOH, 0xff0001 ==
+ 		   -0x00ffff, so we wouldn't *need* to bump it there; but we
+ 		   do for 0xffff = -0x0001.  To be safe without bothering to
+ 		   check every case, bump it regardless. */
+ 		if (is_signed && numsignificantbytes < n)
+ 			++numsignificantbytes;
+ 	}
+ 
+ 	/* How many Python long digits do we need?  We have
+ 	   8*numsignificantbytes bits, and each Python long digit has SHIFT
+ 	   bits, so it's the ceiling of the quotient. */
+ 	ndigits = (numsignificantbytes * 8 + SHIFT - 1) / SHIFT;
+ 	if (ndigits > (size_t)INT_MAX)
+ 		return PyErr_NoMemory();
+ 	v = _PyLong_New((int)ndigits);
+ 	if (v == NULL)
+ 		return NULL;
+ 
+ 	/* Copy the bits over.  The tricky parts are computing 2's-comp on
+ 	   the fly for signed numbers, and dealing with the mismatch between
+ 	   8-bit bytes and (probably) 15-bit Python digits.*/
+ 	{
+ 		size_t i;
+ 		twodigits carry = 1;		/* for 2's-comp calculation */
+ 		twodigits accum = 0;		/* sliding register */
+ 		unsigned int accumbits = 0; 	/* number of bits in accum */
+ 		const unsigned char* p = pstartbyte;
+ 
+ 		for (i = 0; i < numsignificantbytes; ++i, p += incr) {
+ 			twodigits thisbyte = *p;
+ 			/* Compute correction for 2's comp, if needed. */
+ 			if (is_signed) {
+ 				thisbyte = (0xff ^ thisbyte) + carry;
+ 				carry = thisbyte >> 8;
+ 				thisbyte &= 0xff;
+ 			}
+ 			/* Because we're going LSB to MSB, thisbyte is
+ 			   more significant than what's already in accum,
+ 			   so needs to be prepended to accum. */
+ 			accum |= thisbyte << accumbits;
+ 			accumbits += 8;
+ 			if (accumbits >= SHIFT) {
+ 				/* There's enough to fill a Python digit. */
+ 				assert(idigit < (int)ndigits);
+ 				v->ob_digit[idigit] = (digit)(accum & MASK);
+ 				++idigit;
+ 				accum >>= SHIFT;
+ 				accumbits -= SHIFT;
+ 				assert(accumbits < SHIFT);
+ 			}
+ 		}
+ 		assert(accumbits < SHIFT);
+ 		if (accumbits) {
+ 			assert(idigit < (int)ndigits);
+ 			v->ob_digit[idigit] = (digit)accum;
+ 			++idigit;
+ 		}
+ 	}
+ 
+ 	v->ob_size = is_signed ? -idigit : idigit;
+ 	return (PyObject *)long_normalize(v);
+ }
+ 
+ int
+ _PyLong_AsByteArray(PyLongObject* v,
+ 		    unsigned char* bytes, size_t n,
+ 		    int little_endian, int is_signed)
+ {
+ 	int i;			/* index into v->ob_digit */
+ 	int ndigits;		/* |v->ob_size| */
+ 	twodigits accum;	/* sliding register */
+ 	unsigned int accumbits; /* # bits in accum */
+ 	int do_twos_comp;	/* store 2's-comp?  is_signed and v < 0 */
+ 	twodigits carry;	/* for computing 2's-comp */
+ 	size_t j;		/* # bytes filled */
+ 	unsigned char* p;	/* pointer to next byte in bytes */
+ 	int pincr;		/* direction to move p */
+ 
+ 	assert(v != NULL && PyLong_Check(v));
+ 
+ 	if (v->ob_size < 0) {
+ 		ndigits = -(v->ob_size);
+ 		if (!is_signed) {
+ 			PyErr_SetString(PyExc_TypeError,
+ 				"can't convert negative long to unsigned");
+ 			return -1;
+ 		}
+ 		do_twos_comp = 1;
+ 	}
+ 	else {
+ 		ndigits = v->ob_size;
+ 		do_twos_comp = 0;
+ 	}
+ 
+ 	if (little_endian) {
+ 		p = bytes;
+ 		pincr = 1;
+ 	}
+ 	else {
+ 		p = bytes + n - 1;
+ 		pincr = -1;
+ 	}
+ 
+ 	/* Copy over all the Python digits.
+ 	   It's crucial that every Python digit except for the MSD contribute
+ 	   exactly SHIFT bits to the total, so first assert that the long is
+ 	   normalized. */
+ 	assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
+ 	j = 0;
+ 	accum = 0;
+ 	accumbits = 0;
+ 	carry = do_twos_comp ? 1 : 0;
+ 	for (i = 0; i < ndigits; ++i) {
+ 		twodigits thisdigit = v->ob_digit[i];
+ 		if (do_twos_comp) {
+ 			thisdigit = (thisdigit ^ MASK) + carry;
+ 			carry = thisdigit >> SHIFT;
+ 			thisdigit &= MASK;
+ 		}
+ 		/* Because we're going LSB to MSB, thisdigit is more
+ 		   significant than what's already in accum, so needs to be
+ 		   prepended to accum. */
+ 		accum |= thisdigit << accumbits;
+ 		accumbits += SHIFT;
+ 
+ 		/* The most-significant digit may be (probably is) at least
+ 		   partly empty. */
+ 		if (i == ndigits - 1) {
+ 			/* Count # of sign bits -- they needn't be stored,
+ 			 * although for signed conversion we need later to
+ 			 * make sure at least one sign bit gets stored.
+ 			 * First shift conceptual sign bit to real sign bit.
+ 			 */
+ 			stwodigits s = (stwodigits)(thisdigit <<
+ 				(8*sizeof(stwodigits) - SHIFT));
+ 			unsigned int nsignbits = 0;
+ 			while ((s < 0) == do_twos_comp && nsignbits < SHIFT) {
+ 				++nsignbits;
+ 				s <<= 1;
+ 			}
+ 			accumbits -= nsignbits;
+ 		}
+ 
+ 		/* Store as many bytes as possible. */
+ 		while (accumbits >= 8) {
+ 			if (j >= n)
+ 				goto Overflow;
+ 			++j;
+ 			*p = (unsigned char)(accum & 0xff);
+ 			p += pincr;
+ 			accumbits -= 8;
+ 			accum >>= 8;
+ 		}
+ 	}
+ 
+ 	/* Store the straggler (if any). */
+ 	assert(accumbits < 8);
+ 	assert(carry == 0);  /* else do_twos_comp and *every* digit was 0 */
+ 	if (accumbits > 0) {
+ 		if (j >= n)
+ 			goto Overflow;
+ 		++j;
+ 		if (do_twos_comp) {
+ 			/* Fill leading bits of the byte with sign bits
+ 			   (appropriately pretending that the long had an
+ 			   infinite supply of sign bits). */
+ 			accum |= (~(twodigits)0) << accumbits;
+ 		}
+ 		*p = (unsigned char)(accum & 0xff);
+ 		p += pincr;
+ 	}
+ 	else if (j == n && n > 0 && is_signed) {
+ 		/* The main loop filled the byte array exactly, so the code
+ 		   just above didn't get to ensure there's a sign bit, and the
+ 		   loop below wouldn't add one either.  Make sure a sign bit
+ 		   exists. */
+ 		unsigned char msb = *(p - pincr);
+ 		int sign_bit_set = msb >= 0x80;
+ 		assert(accumbits == 0);
+ 		if (sign_bit_set == do_twos_comp)
+ 			return 0;
+ 		else
+ 			goto Overflow;
+ 	}
+ 
+ 	/* Fill remaining bytes with copies of the sign bit. */
+ 	{
+ 		unsigned char signbyte = do_twos_comp ? 0xffU : 0U;
+ 		for ( ; j < n; ++j, p += pincr)
+ 			*p = signbyte;
+ 	}
+ 
+ 	return 0;
+ 
+ Overflow:
+ 	PyErr_SetString(PyExc_OverflowError, "long too big to convert");
+ 	return -1;
+ 	
+ }
+ 
  /* Get a C double from a long int object. */
  
***************
*** 245,260 ****
  PyLong_FromVoidPtr(void *p)
  {
! #if SIZEOF_VOID_P == SIZEOF_LONG
  	return PyInt_FromLong((long)p);
  #else
  	/* optimize null pointers */
! 	if ( p == NULL )
  		return PyInt_FromLong(0);
- 
- 	/* we can assume that HAVE_LONG_LONG is true. if not, then the
- 	   configuration process should have bailed (having big pointers
- 	   without long longs seems non-sensical) */
  	return PyLong_FromLongLong((LONG_LONG)p);
! #endif /* SIZEOF_VOID_P == SIZEOF_LONG */
  }
  
--- 509,528 ----
  PyLong_FromVoidPtr(void *p)
  {
! #if SIZEOF_VOID_P <= SIZEOF_LONG
  	return PyInt_FromLong((long)p);
  #else
+ 
+ #ifndef HAVE_LONG_LONG
+ #   error "PyLong_FromVoidPtr: sizeof(void*) > sizeof(long), but no long long"
+ #endif
+ #if SIZEOF_LONG_LONG < SIZEOF_VOID_P
+ #   error "PyLong_FromVoidPtr: sizeof(LONG_LONG) < sizeof(void*)"
+ #endif
  	/* optimize null pointers */
! 	if (p == NULL)
  		return PyInt_FromLong(0);
  	return PyLong_FromLongLong((LONG_LONG)p);
! 
! #endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
  }
  
***************
*** 268,291 ****
  	   PyExc_SystemError, "bad argument to internal function"
  	*/
! 
! #if SIZEOF_VOID_P == SIZEOF_LONG
  	long x;
  
! 	if ( PyInt_Check(vv) )
  		x = PyInt_AS_LONG(vv);
  	else
  		x = PyLong_AsLong(vv);
  #else
! 	/* we can assume that HAVE_LONG_LONG is true. if not, then the
! 	   configuration process should have bailed (having big pointers
! 	   without long longs seems non-sensical) */
  	LONG_LONG x;
  
! 	if ( PyInt_Check(vv) )
  		x = PyInt_AS_LONG(vv);
  	else
  		x = PyLong_AsLongLong(vv);
- #endif /* SIZEOF_VOID_P == SIZEOF_LONG */
  
  	if (x == -1 && PyErr_Occurred())
  		return NULL;
--- 536,563 ----
  	   PyExc_SystemError, "bad argument to internal function"
  	*/
! #if SIZEOF_VOID_P <= SIZEOF_LONG
  	long x;
  
! 	if (PyInt_Check(vv))
  		x = PyInt_AS_LONG(vv);
  	else
  		x = PyLong_AsLong(vv);
  #else
! 
! #ifndef HAVE_LONG_LONG
! #   error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long"
! #endif
! #if SIZEOF_LONG_LONG < SIZEOF_VOID_P
! #   error "PyLong_AsVoidPtr: sizeof(LONG_LONG) < sizeof(void*)"
! #endif
  	LONG_LONG x;
  
! 	if (PyInt_Check(vv))
  		x = PyInt_AS_LONG(vv);
  	else
  		x = PyLong_AsLongLong(vv);
  
+ #endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
+ 
  	if (x == -1 && PyErr_Occurred())
  		return NULL;
***************
*** 294,391 ****
  
  #ifdef HAVE_LONG_LONG
! /*
!  * LONG_LONG support by Chris Herborth (chrish@qnx.com)
!  *
!  * For better or worse :-), I tried to follow the coding style already
!  * here.
   */
  
! /* Create a new long int object from a C LONG_LONG int */
  
  PyObject *
  PyLong_FromLongLong(LONG_LONG ival)
  {
! #if SIZEOF_LONG_LONG == SIZEOF_LONG
! 	/* In case the compiler is faking it. */
! 	return PyLong_FromLong( (long)ival );
! #else
! 	if ((LONG_LONG)LONG_MIN <= ival && ival <= (LONG_LONG)LONG_MAX) {
! 		return PyLong_FromLong( (long)ival );
! 	}
! 	else if (0 <= ival && ival <= (unsigned LONG_LONG)ULONG_MAX) {
! 		return PyLong_FromUnsignedLong( (unsigned long)ival );
! 	}
! 	else {
! 		/* Assume a C LONG_LONG fits in at most 10 'digits'.
! 		 * Should be OK if we're assuming long fits in 5.
! 		 */
! 		PyLongObject *v = _PyLong_New(10);
! 
! 		if (v != NULL) {
! 			unsigned LONG_LONG t = ival;
! 			int i;
! 			if (ival < 0) {
! 				t = -ival;
! 				v->ob_size = -(v->ob_size);
!   			}
! 
! 			for (i = 0; i < 10; i++) {
! 				v->ob_digit[i] = (digit) (t & MASK);
! 				t >>= SHIFT;
! 			}
! 
! 			v = long_normalize(v);
! 		}
! 
! 		return (PyObject *)v;
! 	}
! #endif
  }
  
! /* Create a new long int object from a C unsigned LONG_LONG int */
  PyObject *
  PyLong_FromUnsignedLongLong(unsigned LONG_LONG ival)
  {
! #if SIZEOF_LONG_LONG == SIZEOF_LONG
! 	/* In case the compiler is faking it. */
! 	return PyLong_FromUnsignedLong( (unsigned long)ival );
! #else
! 	if( ival <= (unsigned LONG_LONG)ULONG_MAX ) {
! 		return PyLong_FromUnsignedLong( (unsigned long)ival );
! 	}
! 	else {
! 		/* Assume a C long fits in at most 10 'digits'. */
! 		PyLongObject *v = _PyLong_New(10);
! 
! 		if (v != NULL) {
! 			unsigned LONG_LONG t = ival;
! 			int i;
! 			for (i = 0; i < 10; i++) {
! 				v->ob_digit[i] = (digit) (t & MASK);
! 				t >>= SHIFT;
! 			}
! 
! 			v = long_normalize(v);
! 		}
! 
! 		return (PyObject *)v;
! 	}
! #endif
  }
  
  /* Get a C LONG_LONG int from a long int object.
!    Returns -1 and sets an error condition if overflow occurs. */
  
  LONG_LONG
  PyLong_AsLongLong(PyObject *vv)
  {
! #if SIZEOF_LONG_LONG == SIZEOF_LONG
! 	/* In case the compiler is faking it. */
! 	return (LONG_LONG)PyLong_AsLong( vv );
! #else
! 	register PyLongObject *v;
! 	LONG_LONG x, prev;
! 	int i, sign;
! 	
  	if (vv == NULL || !PyLong_Check(vv)) {
  		PyErr_BadInternalCall();
--- 566,610 ----
  
  #ifdef HAVE_LONG_LONG
! 
! /* Initial LONG_LONG support by Chris Herborth (chrish@qnx.com), later
!  * rewritten to use the newer PyLong_{As,From}ByteArray API.
   */
  
! #define IS_LITTLE_ENDIAN (int)*(unsigned char*)&one
  
+ /* Create a new long int object from a C LONG_LONG int. */
+ 
  PyObject *
  PyLong_FromLongLong(LONG_LONG ival)
  {
! 	LONG_LONG bytes = ival;
! 	int one = 1;
! 	return _PyLong_FromByteArray(
! 			(unsigned char *)&bytes,
! 			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
  }
  
! /* Create a new long int object from a C unsigned LONG_LONG int. */
! 
  PyObject *
  PyLong_FromUnsignedLongLong(unsigned LONG_LONG ival)
  {
! 	unsigned LONG_LONG bytes = ival;
! 	int one = 1;
! 	return _PyLong_FromByteArray(
! 			(unsigned char *)&bytes,
! 			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
  }
  
  /* Get a C LONG_LONG int from a long int object.
!    Return -1 and set an error if overflow occurs. */
  
  LONG_LONG
  PyLong_AsLongLong(PyObject *vv)
  {
! 	LONG_LONG bytes;
! 	int one = 1;
! 	int res;
! 
  	if (vv == NULL || !PyLong_Check(vv)) {
  		PyErr_BadInternalCall();
***************
*** 393,459 ****
  	}
  
! 	v = (PyLongObject *)vv;
! 	i = v->ob_size;
! 	sign = 1;
! 	x = 0;
  
! 	if (i < 0) {
! 		sign = -1;
! 		i = -(i);
! 	}
! 
! 	while (--i >= 0) {
! 		prev = x;
! 		x = (x << SHIFT) + v->ob_digit[i];
! 		if ((x >> SHIFT) != prev) {
! 			PyErr_SetString(PyExc_OverflowError,
! 				"long int too long to convert");
! 			return -1;
! 		}
! 	}
! 
! 	return x * sign;
! #endif
  }
  
  unsigned LONG_LONG
  PyLong_AsUnsignedLongLong(PyObject *vv)
  {
! #if SIZEOF_LONG_LONG == 4
! 	/* In case the compiler is faking it. */
! 	return (unsigned LONG_LONG)PyLong_AsUnsignedLong( vv );
! #else
! 	register PyLongObject *v;
! 	unsigned LONG_LONG x, prev;
! 	int i;
! 	
  	if (vv == NULL || !PyLong_Check(vv)) {
  		PyErr_BadInternalCall();
! 		return (unsigned LONG_LONG) -1;
  	}
  
! 	v = (PyLongObject *)vv;
! 	i = v->ob_size;
! 	x = 0;
  
! 	if (i < 0) {
! 		PyErr_SetString(PyExc_OverflowError,
! 			   "can't convert negative value to unsigned long");
! 		return (unsigned LONG_LONG) -1;
! 	}
  
! 	while (--i >= 0) {
! 		prev = x;
! 		x = (x << SHIFT) + v->ob_digit[i];
! 		if ((x >> SHIFT) != prev) {
! 			PyErr_SetString(PyExc_OverflowError,
! 				"long int too long to convert");
! 			return (unsigned LONG_LONG) -1;
! 		}
! 	}
  
- 	return x;
- #endif
- }
  #endif /* HAVE_LONG_LONG */
  
--- 612,646 ----
  	}
  
! 	res = _PyLong_AsByteArray(
! 			(PyLongObject *)vv, (unsigned char *)&bytes,
! 			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
  
! 	return res < 0 ? (LONG_LONG)res : bytes;
  }
  
+ /* Get a C unsigned LONG_LONG int from a long int object.
+    Return -1 and set an error if overflow occurs. */
+ 
  unsigned LONG_LONG
  PyLong_AsUnsignedLongLong(PyObject *vv)
  {
! 	unsigned LONG_LONG bytes;
! 	int one = 1;
! 	int res;
! 
  	if (vv == NULL || !PyLong_Check(vv)) {
  		PyErr_BadInternalCall();
! 		return -1;
  	}
  
! 	res = _PyLong_AsByteArray(
! 			(PyLongObject *)vv, (unsigned char *)&bytes,
! 			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
  
! 	return res < 0 ? (unsigned LONG_LONG)res : bytes;
! }
  
! #undef IS_LITTLE_ENDIAN
  
  #endif /* HAVE_LONG_LONG */
  

Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.124.4.22
retrieving revision 2.124.4.23
diff -C2 -r2.124.4.22 -r2.124.4.23
*** object.c	2001/07/03 00:48:14	2.124.4.22
--- object.c	2001/07/07 22:55:30	2.124.4.23
***************
*** 438,442 ****
  		switch (try_rich_compare_bool(v, w, tries[i].op)) {
  		case -1:
! 			return -1;
  		case 1:
  			return tries[i].outcome;
--- 438,442 ----
  		switch (try_rich_compare_bool(v, w, tries[i].op)) {
  		case -1:
! 			return -2;
  		case 1:
  			return tries[i].outcome;
***************
*** 468,481 ****
  		return (*w->ob_type->tp_compare)(v, w);
  
- 	/* If the types are equal, don't bother with coercions etc. */
- 	if (v->ob_type == w->ob_type) {
- 		if ((f = v->ob_type->tp_compare) == NULL)
- 			return 2;
- 		c = (*f)(v, w);
- 		if (PyErr_Occurred())
- 			return -2;
- 		return c < 0 ? -1 : c > 0 ? 1 : 0;
- 	}
- 
  	/* Try coercion; if it fails, give up */
  	c = PyNumber_CoerceEx(&v, &w);
--- 468,471 ----
***************
*** 490,494 ****
  		Py_DECREF(v);
  		Py_DECREF(w);
! 		if (PyErr_Occurred())
  			return -2;
  		return c < 0 ? -1 : c > 0 ? 1 : 0;
--- 480,484 ----
  		Py_DECREF(v);
  		Py_DECREF(w);
! 		if (c < 0 && PyErr_Occurred())
  			return -2;
  		return c < 0 ? -1 : c > 0 ? 1 : 0;
***************
*** 500,504 ****
  		Py_DECREF(v);
  		Py_DECREF(w);
! 		if (PyErr_Occurred())
  			return -2;
  		return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */
--- 490,494 ----
  		Py_DECREF(v);
  		Py_DECREF(w);
! 		if (c < 0 && PyErr_Occurred())
  			return -2;
  		return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */
***************
*** 576,584 ****
--- 566,586 ----
  #define CHECK_TYPES(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_CHECKTYPES)
  
+ /* Do a 3-way comparison, by hook or by crook.  Return:
+    -2 for an exception;
+    -1 if v < w;
+     0 if v == w;
+     1 if v > w;
+    If the object implements a tp_compare function, it returns
+    whatever this function returns (whether with an exception or not).
+ */
  static int
  do_cmp(PyObject *v, PyObject *w)
  {
  	int c;
+ 	cmpfunc f;
  
+ 	if (v->ob_type == w->ob_type
+ 	    && (f = v->ob_type->tp_compare) != NULL)
+ 		return (*f)(v, w);
  	c = try_rich_to_3way_compare(v, w);
  	if (c < 2)
***************
*** 745,758 ****
  
  static PyObject *
! try_3way_to_rich_compare(PyObject *v, PyObject *w, int op)
  {
- 	int c;
  	PyObject *result;
- 
- 	c = try_3way_compare(v, w);
- 	if (c >= 2)
- 		c = default_3way_compare(v, w);
- 	if (c <= -2)
- 		return NULL;
  	switch (op) {
  	case Py_LT: c = c <  0; break;
--- 747,753 ----
  
  static PyObject *
! convert_3way_to_object(int op, int c)
  {
  	PyObject *result;
  	switch (op) {
  	case Py_LT: c = c <  0; break;
***************
*** 767,775 ****
--- 762,810 ----
  	return result;
  }
+ 	
  
  static PyObject *
+ try_3way_to_rich_compare(PyObject *v, PyObject *w, int op)
+ {
+ 	int c;
+ 
+ 	c = try_3way_compare(v, w);
+ 	if (c >= 2)
+ 		c = default_3way_compare(v, w);
+ 	if (c <= -2)
+ 		return NULL;
+ 	return convert_3way_to_object(op, c);
+ }
+ 
+ static PyObject *
  do_richcmp(PyObject *v, PyObject *w, int op)
  {
  	PyObject *res;
+ 	cmpfunc f;
+ 
+ 	/* If the types are equal, don't bother with coercions etc. 
+ 	   Instances are special-cased in try_3way_compare, since
+ 	   a result of 2 does *not* mean one value being greater
+ 	   than the other. */
+ 	if (v->ob_type == w->ob_type
+ 	    && (f = v->ob_type->tp_compare) != NULL
+ 	    && !PyInstance_Check(v)) {
+ 		int c;
+ 		richcmpfunc f1;
+ 		if ((f1 = RICHCOMPARE(v->ob_type)) != NULL) {
+ 			/* If the type has richcmp, try it first.
+ 			   try_rich_compare would try it two-sided,
+ 			   which is not needed since we've a single
+ 			   type only. */
+ 			res = (*f1)(v, w, op);
+ 			if (res != Py_NotImplemented)
+ 				return res;
+ 			Py_DECREF(res);
+ 		}
+ 		c = (*f)(v, w);
+ 		if (c < 0 && PyErr_Occurred())
+ 			return NULL;
+ 		return convert_3way_to_object(op, c);
+ 	}
  
  	res = try_rich_compare(v, w, op);
***************
*** 826,829 ****
--- 861,865 ----
  }
  
+ /* Return -1 if error; 1 if v op w; 0 if not (v op w). */
  int
  PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)

Index: rangeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/rangeobject.c,v
retrieving revision 2.24.6.3
retrieving revision 2.24.6.4
diff -C2 -r2.24.6.3 -r2.24.6.4
*** rangeobject.c	2001/06/06 14:27:54	2.24.6.3
--- rangeobject.c	2001/07/07 22:55:30	2.24.6.4
***************
*** 11,55 ****
  	long	step;
  	long	len;
- 	int	reps;
- 	long	totlen;
  } rangeobject;
  
- static int
- long_mul(long i, long j, long *kk)
- {
- 	PyObject *a;
- 	PyObject *b;
- 	PyObject *c;
- 	
- 	if ((a = PyInt_FromLong(i)) == NULL)
- 		return 0;
- 	
- 	if ((b = PyInt_FromLong(j)) == NULL)
- 		return 0;
- 	
- 	c = PyNumber_Multiply(a, b);
- 	
- 	Py_DECREF(a);
- 	Py_DECREF(b);
- 	
- 	if (c == NULL)
- 		return 0;
- 
- 	*kk = PyInt_AS_LONG(c);
- 	Py_DECREF(c);
- 
- 	if (*kk > INT_MAX) {
- 		PyErr_SetString(PyExc_OverflowError,
- 				"integer multiplication");
- 		return 0;
- 	}
- 	else
- 		return 1;
- }
- 
  PyObject *
! PyRange_New(long start, long len, long step, int reps)
  {
- 	long totlen = -1;
  	rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type);
  
--- 11,19 ----
  	long	step;
  	long	len;
  } rangeobject;
  
  PyObject *
! PyRange_New(long start, long len, long step)
  {
  	rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type);
  
***************
*** 57,66 ****
  		return NULL;
  
! 	if (len == 0 || reps <= 0) {
  		start = 0;
  		len = 0;
  		step = 1;
- 		reps = 1;
- 		totlen = 0;
  	}
  	else {
--- 21,28 ----
  		return NULL;
  
! 	if (len == 0) {
  		start = 0;
  		len = 0;
  		step = 1;
  	}
  	else {
***************
*** 72,81 ****
  					"integer addition");
  			return NULL;
- 		}			
- 		if (! long_mul(len, (long) reps, &totlen)) {
- 			if(!PyErr_ExceptionMatches(PyExc_OverflowError))
- 				return NULL;
- 			PyErr_Clear();
- 			totlen = -1;
  		}
  	}
--- 34,37 ----
***************
*** 84,89 ****
  	obj->len   = len;
  	obj->step  = step;
- 	obj->reps  = reps;
- 	obj->totlen = totlen;
  
  	return (PyObject *) obj;
--- 40,43 ----
***************
*** 99,108 ****
  range_item(rangeobject *r, int i)
  {
! 	if (i < 0 || i >= r->totlen)
! 		if (r->totlen!=-1) {
! 			PyErr_SetString(PyExc_IndexError,
  				"xrange object index out of range");
! 			return NULL;
! 		}
  
  	return PyInt_FromLong(r->start + (i % r->len) * r->step);
--- 53,61 ----
  range_item(rangeobject *r, int i)
  {
! 	if (i < 0 || i >= r->len) {
! 		PyErr_SetString(PyExc_IndexError,
  				"xrange object index out of range");
! 		return NULL;
! 	}
  
  	return PyInt_FromLong(r->start + (i % r->len) * r->step);
***************
*** 112,119 ****
  range_length(rangeobject *r)
  {
! 	if (r->totlen == -1)
! 		PyErr_SetString(PyExc_OverflowError,
! 				"xrange object has too many items");
! 	return r->totlen;
  }
  
--- 65,69 ----
  range_length(rangeobject *r)
  {
! 	return r->len;
  }
  
***************
*** 125,129 ****
  	 */
  	char buf1[250];
- 	char buf2[250];
  
  	if (r->start == 0 && r->step == 1)
--- 75,78 ----
***************
*** 140,306 ****
  			r->start + r->len * r->step,
  			r->step);
- 
- 	if (r->reps != 1)
- 		sprintf(buf2, "(%s * %d)", buf1, r->reps);
- 
- 	return PyString_FromString(r->reps == 1 ? buf1 : buf2);
- }
- 
- static PyObject *
- range_concat(rangeobject *r, PyObject *obj)
- {
- 	PyErr_SetString(PyExc_TypeError, "cannot concatenate xrange objects");
- 	return NULL;
- }
- 
- static PyObject *
- range_repeat(rangeobject *r, int n)
- {
- 	long lreps = 0;
- 
- 	if (n <= 0)
- 		return (PyObject *) PyRange_New(0, 0, 1, 1);
- 
- 	else if (n == 1) {
- 		Py_INCREF(r);
- 		return (PyObject *) r;
- 	}
- 
- 	else if (! long_mul((long) r->reps, (long) n, &lreps))
- 		return NULL;
- 	
- 	else
- 		return (PyObject *) PyRange_New(
- 						r->start,
- 						r->len,
- 						r->step,
- 						(int) lreps);
- }
  
! static int
! range_compare(rangeobject *r1, rangeobject *r2)
! {
! 	if (r1->start != r2->start)
! 		return r1->start - r2->start;
! 
! 	else if (r1->step != r2->step)
! 		return r1->step - r2->step;
! 
! 	else if (r1->len != r2->len)
! 		return r1->len - r2->len;
! 
! 	else
! 		return r1->reps - r2->reps;
! }
! 
! static PyObject *
! range_slice(rangeobject *r, int low, int high)
! {
! 	if (r->reps != 1) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"cannot slice a replicated xrange");
! 		return NULL;
! 	}
! 	if (low < 0)
! 		low = 0;
! 	else if (low > r->len)
! 		low = r->len;
! 	if (high < 0)
! 		high = 0;
! 	if (high < low)
! 		high = low;
! 	else if (high > r->len)
! 		high = r->len;
! 
! 	if (low == 0 && high == r->len) {
! 		Py_INCREF(r);
! 		return (PyObject *) r;
! 	}
! 
! 	return (PyObject *) PyRange_New(
! 				low * r->step + r->start,
! 				high - low,
! 				r->step,
! 				1);
! }
! 
! static PyObject *
! range_tolist(rangeobject *self, PyObject *args)
! {
! 	PyObject *thelist;
! 	int j;
! 
! 	if (! PyArg_ParseTuple(args, ":tolist"))
! 		return NULL;
! 
! 	if (self->totlen == -1)
! 		return PyErr_NoMemory();
! 
! 	if ((thelist = PyList_New(self->totlen)) == NULL)
! 		return NULL;
! 
! 	for (j = 0; j < self->totlen; ++j)
! 		if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong(
! 			self->start + (j % self->len) * self->step))) < 0)
! 			return NULL;
! 
! 	return thelist;
! }
! 
! static PyObject *
! range_getstop(rangeobject *r, void *closure)
! {
! 	return PyInt_FromLong(r->start + (r->len * r->step));
! }
! 
! static PyMethodDef range_methods[] = {
! 	{"tolist",	(PyCFunction)range_tolist, METH_VARARGS,
! 	 "tolist() -> list\n"
! 	 "Return a list object with the same values."},
! 	{NULL,		NULL}
! };
! static struct memberlist range_members[] = {
! 	{"step",  T_LONG, offsetof(rangeobject, step), RO},
! 	{"start", T_LONG, offsetof(rangeobject, start), RO},
! 	{NULL, 0, 0, 0}
! };
! 
! static struct getsetlist range_getsets[] = {
! 	{"stop", (getter)range_getstop, NULL, NULL},
! 	{0}
! };
! 
! static int
! range_contains(rangeobject *r, PyObject *obj)
! {
! 	long num = PyInt_AsLong(obj);
! 
! 	if (num < 0 && PyErr_Occurred())
! 		return -1;
! 
! 	if (r->step > 0) {
! 		if ((num < r->start) || ((num - r->start) % r->step))
! 			return 0;
! 		if (num >= (r->start + (r->len * r->step)))
! 			return 0;
! 	}
! 	else {
! 		if ((num > r->start) || ((num - r->start) % r->step))
! 			return 0;
! 		if (num <= (r->start + (r->len * r->step)))
! 			return 0;
! 	}
! 	return 1;
  }
  
  static PySequenceMethods range_as_sequence = {
  	(inquiry)range_length,	/*sq_length*/
! 	(binaryfunc)range_concat, /*sq_concat*/
! 	(intargfunc)range_repeat, /*sq_repeat*/
! 	(intargfunc)range_item, /*sq_item*/
! 	(intintargfunc)range_slice, /*sq_slice*/
  	0,			/*sq_ass_item*/
  	0,			/*sq_ass_slice*/
! 	(objobjproc)range_contains, /*sq_contains*/
  };
  
--- 89,105 ----
  			r->start + r->len * r->step,
  			r->step);
  
! 	return PyString_FromString(buf1);
  }
  
  static PySequenceMethods range_as_sequence = {
  	(inquiry)range_length,	/*sq_length*/
! 	0,			/*sq_concat*/
! 	0,			/*sq_repeat*/
! 	(intargfunc)range_item,	/*sq_item*/
! 	0,			/*sq_slice*/
  	0,			/*sq_ass_item*/
  	0,			/*sq_ass_slice*/
! 	0,			/*sq_contains*/
  };
  
***************
*** 315,319 ****
  	0, 					/* tp_getattr */
  	0,					/* tp_setattr */
! 	(cmpfunc)range_compare,			/* tp_compare */
  	(reprfunc)range_repr,			/* tp_repr */
  	0,					/* tp_as_number */
--- 114,118 ----
  	0, 					/* tp_getattr */
  	0,					/* tp_setattr */
! 	0,					/* tp_compare */
  	(reprfunc)range_repr,			/* tp_repr */
  	0,					/* tp_as_number */
***************
*** 334,340 ****
  	0,					/* tp_iter */
  	0,					/* tp_iternext */
! 	range_methods,				/* tp_methods */
! 	range_members,				/* tp_members */
! 	range_getsets,				/* tp_getset */
  	0,					/* tp_base */
  	0,					/* tp_dict */
--- 133,139 ----
  	0,					/* tp_iter */
  	0,					/* tp_iternext */
! 	0,					/* tp_methods */
! 	0,					/* tp_members */
! 	0,					/* tp_getset */
  	0,					/* tp_base */
  	0,					/* tp_dict */

Index: stringobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/stringobject.c,v
retrieving revision 2.103.2.6
retrieving revision 2.103.2.7
diff -C2 -r2.103.2.6 -r2.103.2.7
*** stringobject.c	2001/06/16 14:38:37	2.103.2.6
--- stringobject.c	2001/07/07 22:55:30	2.103.2.7
***************
*** 74,80 ****
--- 74,86 ----
  #ifndef DONT_SHARE_SHORT_STRINGS
  	if (size == 0) {
+ 		PyObject *t = (PyObject *)op;
+ 		PyString_InternInPlace(&t);
+ 		op = (PyStringObject *)t;
  		nullstring = op;
  		Py_INCREF(op);
  	} else if (size == 1 && str != NULL) {
+ 		PyObject *t = (PyObject *)op;
+ 		PyString_InternInPlace(&t);
+ 		op = (PyStringObject *)t;
  		characters[*str & UCHAR_MAX] = op;
  		Py_INCREF(op);
***************
*** 126,132 ****
--- 132,144 ----
  #ifndef DONT_SHARE_SHORT_STRINGS
  	if (size == 0) {
+ 		PyObject *t = (PyObject *)op;
+ 		PyString_InternInPlace(&t);
+ 		op = (PyStringObject *)t;
  		nullstring = op;
  		Py_INCREF(op);
  	} else if (size == 1) {
+ 		PyObject *t = (PyObject *)op;
+ 		PyString_InternInPlace(&t);
+ 		op = (PyStringObject *)t;
  		characters[*str & UCHAR_MAX] = op;
  		Py_INCREF(op);
***************
*** 141,176 ****
  			  const char *errors)
  {
!     PyObject *buffer = NULL, *str;
!     
!     if (encoding == NULL) 
  	encoding = PyUnicode_GetDefaultEncoding();
  
      /* Decode via the codec registry */
!     buffer = PyBuffer_FromMemory((void *)s, size);
!     if (buffer == NULL)
          goto onError;
!     str = PyCodec_Decode(buffer, encoding, errors);
!     if (str == NULL)
          goto onError;
      /* Convert Unicode to a string using the default encoding */
!     if (PyUnicode_Check(str)) {
! 	PyObject *temp = str;
! 	str = PyUnicode_AsEncodedString(str, NULL, NULL);
  	Py_DECREF(temp);
! 	if (str == NULL)
  	    goto onError;
      }
!     if (!PyString_Check(str)) {
          PyErr_Format(PyExc_TypeError,
                       "decoder did not return a string object (type=%.400s)",
!                      str->ob_type->tp_name);
!         Py_DECREF(str);
          goto onError;
      }
!     Py_DECREF(buffer);
!     return str;
!     
   onError:
-     Py_XDECREF(buffer);
      return NULL;
  }
--- 153,220 ----
  			  const char *errors)
  {
!     PyObject *v, *str;
! 
!     str = PyString_FromStringAndSize(s, size);
!     if (str == NULL)
! 	return NULL;
!     v = PyString_AsDecodedString(str, encoding, errors);
!     Py_DECREF(str);
!     return v;
! }
! 
! PyObject *PyString_AsDecodedObject(PyObject *str,
! 				   const char *encoding,
! 				   const char *errors)
! {
!     PyObject *v;
! 
!     if (!PyString_Check(str)) {
!         PyErr_BadArgument();
!         goto onError;
!     }
! 
!     if (encoding == NULL)
  	encoding = PyUnicode_GetDefaultEncoding();
  
      /* Decode via the codec registry */
!     v = PyCodec_Decode(str, encoding, errors);
!     if (v == NULL)
          goto onError;
! 
!     return v;
! 
!  onError:
!     return NULL;
! }
! 
! PyObject *PyString_AsDecodedString(PyObject *str,
! 				   const char *encoding,
! 				   const char *errors)
! {
!     PyObject *v;
! 
!     v = PyString_AsDecodedObject(str, encoding, errors);
!     if (v == NULL)
          goto onError;
+ 
      /* Convert Unicode to a string using the default encoding */
!     if (PyUnicode_Check(v)) {
! 	PyObject *temp = v;
! 	v = PyUnicode_AsEncodedString(v, NULL, NULL);
  	Py_DECREF(temp);
! 	if (v == NULL)
  	    goto onError;
      }
!     if (!PyString_Check(v)) {
          PyErr_Format(PyExc_TypeError,
                       "decoder did not return a string object (type=%.400s)",
!                      v->ob_type->tp_name);
!         Py_DECREF(v);
          goto onError;
      }
! 
!     return v;
! 
   onError:
      return NULL;
  }
***************
*** 182,186 ****
  {
      PyObject *v, *str;
!     
      str = PyString_FromStringAndSize(s, size);
      if (str == NULL)
--- 226,230 ----
  {
      PyObject *v, *str;
! 
      str = PyString_FromStringAndSize(s, size);
      if (str == NULL)
***************
*** 191,200 ****
  }
  
! PyObject *PyString_AsEncodedString(PyObject *str,
  				   const char *encoding,
  				   const char *errors)
  {
      PyObject *v;
!     
      if (!PyString_Check(str)) {
          PyErr_BadArgument();
--- 235,244 ----
  }
  
! PyObject *PyString_AsEncodedObject(PyObject *str,
  				   const char *encoding,
  				   const char *errors)
  {
      PyObject *v;
! 
      if (!PyString_Check(str)) {
          PyErr_BadArgument();
***************
*** 202,206 ****
      }
  
!     if (encoding == NULL) 
  	encoding = PyUnicode_GetDefaultEncoding();
  
--- 246,250 ----
      }
  
!     if (encoding == NULL)
  	encoding = PyUnicode_GetDefaultEncoding();
  
***************
*** 209,212 ****
--- 253,273 ----
      if (v == NULL)
          goto onError;
+ 
+     return v;
+ 
+  onError:
+     return NULL;
+ }
+ 
+ PyObject *PyString_AsEncodedString(PyObject *str,
+ 				   const char *encoding,
+ 				   const char *errors)
+ {
+     PyObject *v;
+ 
+     v = PyString_AsEncodedObject(str, encoding, errors);
+     if (v == NULL)
+         goto onError;
+ 
      /* Convert Unicode to a string using the default encoding */
      if (PyUnicode_Check(v)) {
***************
*** 224,229 ****
          goto onError;
      }
      return v;
!     
   onError:
      return NULL;
--- 285,291 ----
          goto onError;
      }
+ 
      return v;
! 
   onError:
      return NULL;
***************
*** 273,277 ****
  
  /* Internal API needed by PyString_AsStringAndSize(): */
! extern 
  PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
  					    const char *errors);
--- 335,339 ----
  
  /* Internal API needed by PyString_AsStringAndSize(): */
! extern
  PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
  					    const char *errors);
***************
*** 423,427 ****
  		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);
--- 485,489 ----
  		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);
***************
*** 550,592 ****
  string_item(PyStringObject *a, register int i)
  {
- 	int c;
  	PyObject *v;
  	if (i < 0 || i >= a->ob_size) {
  		PyErr_SetString(PyExc_IndexError, "string index out of range");
  		return NULL;
  	}
! 	c = a->ob_sval[i] & UCHAR_MAX;
! 	v = (PyObject *) characters[c];
  #ifdef COUNT_ALLOCS
- 	if (v != NULL)
  		one_strings++;
  #endif
! 	if (v == NULL) {
! 		v = PyString_FromStringAndSize((char *)NULL, 1);
! 		if (v == NULL)
! 			return NULL;
! 		characters[c] = (PyStringObject *) v;
! 		((PyStringObject *)v)->ob_sval[0] = c;
  	}
- 	Py_INCREF(v);
  	return v;
  }
  
! static int
! string_compare(PyStringObject *a, PyStringObject *b)
  {
! 	int len_a = a->ob_size, len_b = b->ob_size;
! 	int min_len = (len_a < len_b) ? len_a : len_b;
! 	int cmp;
  	if (min_len > 0) {
! 		cmp = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
! 		if (cmp == 0)
! 			cmp = memcmp(a->ob_sval, b->ob_sval, min_len);
! 		if (cmp != 0)
! 			return cmp;
  	}
! 	return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
  }
  
  static long
  string_hash(PyStringObject *a)
--- 612,709 ----
  string_item(PyStringObject *a, register int i)
  {
  	PyObject *v;
+ 	char *pchar;
  	if (i < 0 || i >= a->ob_size) {
  		PyErr_SetString(PyExc_IndexError, "string index out of range");
  		return NULL;
  	}
! 	pchar = a->ob_sval + i;
! 	v = (PyObject *)characters[*pchar & UCHAR_MAX];
! 	if (v == NULL)
! 		v = PyString_FromStringAndSize(pchar, 1);
! 	else {
  #ifdef COUNT_ALLOCS
  		one_strings++;
  #endif
! 		Py_INCREF(v);
  	}
  	return v;
  }
  
! static PyObject*
! string_richcompare(PyStringObject *a, PyStringObject *b, int op)
  {
! 	int c;
! 	int len_a, len_b;
! 	int min_len;
! 	PyObject *result;
! 
! 	/* One of the objects is a string object. Make sure the
! 	   other one is one, too.  */
! 	if (a->ob_type != b->ob_type) {
! 		result = Py_NotImplemented;
! 		goto out;
! 	}
! 	if (a == b) {
! 		switch (op) {
! 		case Py_EQ:case Py_LE:case Py_GE:
! 			result = Py_True;
! 			goto out;
! 		case Py_NE:case Py_LT:case Py_GT:
! 			result = Py_False;
! 			goto out;
! 		}
! 	}
! 	if (op == Py_EQ) {
! 		/* Supporting Py_NE here as well does not save
! 		   much time, since Py_NE is rarely used.  */
! 		if (a->ob_size == b->ob_size
! 		    && (a->ob_sval[0] == b->ob_sval[0]
! 			&& memcmp(a->ob_sval, b->ob_sval, 
! 				  a->ob_size) == 0)) {
! 			result = Py_True;
! 		} else {
! 			result = Py_False;
! 		}
! 		goto out;
! 	}
! 	len_a = a->ob_size; len_b = b->ob_size;
! 	min_len = (len_a < len_b) ? len_a : len_b;
  	if (min_len > 0) {
! 		c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
! 		if (c==0)
! 			c = memcmp(a->ob_sval, b->ob_sval, min_len);
! 	}else
! 		c = 0;
! 	if (c == 0)
! 		c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
! 	switch (op) {
! 	case Py_LT: c = c <  0; break;
! 	case Py_LE: c = c <= 0; break;
! 	case Py_EQ: assert(0);  break; /* unreachable */
! 	case Py_NE: c = c != 0; break;
! 	case Py_GT: c = c >  0; break;
! 	case Py_GE: c = c >= 0; break;
! 	default:
! 		result = Py_NotImplemented;
! 		goto out;
  	}
! 	result = c ? Py_True : Py_False;
!   out:
! 	Py_INCREF(result);
! 	return result;
  }
  
+ int
+ _PyString_Eq(PyObject *o1, PyObject *o2)
+ {
+ 	PyStringObject *a, *b;
+ 	a = (PyStringObject*)o1;
+ 	b = (PyStringObject*)o2;
+         return a->ob_size == b->ob_size
+           && *a->ob_sval == *b->ob_sval
+           && memcmp(a->ob_sval, b->ob_sval, a->ob_size) == 0;
+ }
+ 
  static long
  string_hash(PyStringObject *a)
***************
*** 862,867 ****
  		if (!PyString_Check(item)){
  			if (PyUnicode_Check(item)) {
  				Py_DECREF(seq);
! 				return PyUnicode_Join((PyObject *)self, orig);
  			}
  			PyErr_Format(PyExc_TypeError,
--- 979,991 ----
  		if (!PyString_Check(item)){
  			if (PyUnicode_Check(item)) {
+ 				/* Defer to Unicode join.
+ 				 * CAUTION:  There's no gurantee that the
+ 				 * original sequence can be iterated over
+ 				 * again, so we must pass seq here.
+ 				 */
+ 				PyObject *result;
+ 				result = PyUnicode_Join((PyObject *)self, seq);
  				Py_DECREF(seq);
! 				return result;
  			}
  			PyErr_Format(PyExc_TypeError,
***************
*** 908,911 ****
--- 1032,1053 ----
  }
  
+ PyObject *
+ _PyString_Join(PyObject *sep, PyObject *x)
+ {
+ 	PyObject* args;
+ 	PyObject* result = NULL;
+ 
+ 	assert(sep != NULL && PyString_Check(sep));
+ 	assert(x != NULL);
+ 	args = PyTuple_New(1);
+ 	if (args != NULL) {
+ 		Py_INCREF(x);
+ 		PyTuple_SET_ITEM(args, 0, x);
+ 		result = string_join((PyStringObject *)sep, args);
+ 		Py_DECREF(args);
+ 	}
+ 	return result;
+ }
+ 
  static long
  string_find_internal(PyStringObject *self, PyObject *args, int dir)
***************
*** 916,920 ****
  	PyObject *subobj;
  
! 	if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", 
  		&subobj, _PyEval_SliceIndex, &i, _PyEval_SliceIndex, &last))
  		return -2;
--- 1058,1062 ----
  	PyObject *subobj;
  
! 	if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex",
  		&subobj, _PyEval_SliceIndex, &i, _PyEval_SliceIndex, &last))
  		return -2;
***************
*** 949,953 ****
  	else {
  		int j;
! 	    
          	if (n == 0 && i <= last)
  			return (long)last;
--- 1091,1095 ----
  	else {
  		int j;
! 
          	if (n == 0 && i <= last)
  			return (long)last;
***************
*** 956,960 ****
  				return (long)j;
  	}
! 	
  	return -1;
  }
--- 1098,1102 ----
  				return (long)j;
  	}
! 
  	return -1;
  }
***************
*** 1372,1376 ****
  	}
  	else if (PyUnicode_Check(tableobj)) {
! 		/* Unicode .translate() does not support the deletechars 
  		   parameter; instead a mapping to None will cause characters
  		   to be deleted. */
--- 1514,1518 ----
  	}
  	else if (PyUnicode_Check(tableobj)) {
! 		/* Unicode .translate() does not support the deletechars
  		   parameter; instead a mapping to None will cause characters
  		   to be deleted. */
***************
*** 1468,1472 ****
    MEM, the function returns -1.
  */
! static int 
  mymemfind(const char *mem, int len, const char *pat, int pat_len)
  {
--- 1610,1614 ----
    MEM, the function returns -1.
  */
! static int
  mymemfind(const char *mem, int len, const char *pat, int pat_len)
  {
***************
*** 1491,1495 ****
             mem=11111 and pat==11 also return 2.
   */
! static int 
  mymemcnt(const char *mem, int len, const char *pat, int pat_len)
  {
--- 1633,1637 ----
             mem=11111 and pat==11 also return 2.
   */
! static int
  mymemcnt(const char *mem, int len, const char *pat, int pat_len)
  {
***************
*** 1532,1536 ****
               const char *sub, int sub_len,	/* substitution string */
               int count,				/* number of replacements */
!              int *out_len)
  {
  	char *out_s;
--- 1674,1678 ----
               const char *sub, int sub_len,	/* substitution string */
               int count,				/* number of replacements */
! 	     int *out_len)
  {
  	char *out_s;
***************
*** 1549,1587 ****
  	if (nfound == 0)
  		goto return_same;
  	new_len = len + nfound*(sub_len - pat_len);
  
! 	new_s = (char *)PyMem_MALLOC(new_len);
! 	if (new_s == NULL) return NULL;
  
  	*out_len = new_len;
- 	out_s = new_s;
- 
- 	while (len > 0) {
- 		/* find index of next instance of pattern */
- 		offset = mymemfind(str, len, pat, pat_len);
- 		/* if not found,  break out of loop */
- 		if (offset == -1) break;
- 
- 		/* copy non matching part of input string */
- 		memcpy(new_s, str, offset); /* copy part of str before pat */
- 		str += offset + pat_len; /* move str past pattern */
- 		len -= offset + pat_len; /* reduce length of str remaining */
- 
- 		/* copy substitute into the output string */
- 		new_s += offset; /* move new_s to dest for sub string */
- 		memcpy(new_s, sub, sub_len); /* copy substring into new_s */
- 		new_s += sub_len; /* offset new_s past sub string */
- 
- 		/* break when we've done count replacements */
- 		if (--count == 0) break;
- 	}
- 	/* copy any remaining values into output string */
- 	if (len > 0)
- 		memcpy(new_s, str, len);
  	return out_s;
  
    return_same:
  	*out_len = -1;
! 	return (char*)str;	/* have to cast away constness here */
  }
  
--- 1691,1736 ----
  	if (nfound == 0)
  		goto return_same;
+ 
  	new_len = len + nfound*(sub_len - pat_len);
+ 	if (new_len == 0) {
+ 		/* Have to allocate something for the caller to free(). */
+ 		out_s = (char *)PyMem_MALLOC(1);
+ 		if (out_s == NULL)
+ 			return NULL;
+ 		out_s[0] = '\0';
+ 	}
+ 	else {
+ 		assert(new_len > 0);
+ 		new_s = (char *)PyMem_MALLOC(new_len);
+ 		if (new_s == NULL)
+ 			return NULL;
+ 		out_s = new_s;
  
! 		for (; count > 0 && len > 0; --count) {
! 			/* find index of next instance of pattern */
! 			offset = mymemfind(str, len, pat, pat_len);
! 			if (offset == -1)
! 				break;
  
+ 			/* copy non matching part of input string */
+ 			memcpy(new_s, str, offset);
+ 			str += offset + pat_len;
+ 			len -= offset + pat_len;
+ 
+ 			/* copy substitute into the output string */
+ 			new_s += offset;
+ 			memcpy(new_s, sub, sub_len);
+ 			new_s += sub_len;
+ 		}
+ 		/* copy any remaining values into output string */
+ 		if (len > 0)
+ 			memcpy(new_s, str, len);
+ 	}
  	*out_len = new_len;
  	return out_s;
  
    return_same:
  	*out_len = -1;
! 	return (char *)str; /* cast away const */
  }
  
***************
*** 1613,1617 ****
  	}
  	else if (PyUnicode_Check(subobj))
! 		return PyUnicode_Replace((PyObject *)self, 
  					 subobj, replobj, count);
  	else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))
--- 1762,1766 ----
  	}
  	else if (PyUnicode_Check(subobj))
! 		return PyUnicode_Replace((PyObject *)self,
  					 subobj, replobj, count);
  	else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))
***************
*** 1623,1627 ****
  	}
  	else if (PyUnicode_Check(replobj))
! 		return PyUnicode_Replace((PyObject *)self, 
  					 subobj, replobj, count);
  	else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len))
--- 1772,1776 ----
  	}
  	else if (PyUnicode_Check(replobj))
! 		return PyUnicode_Replace((PyObject *)self,
  					 subobj, replobj, count);
  	else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len))
***************
*** 1677,1681 ****
  	else if (PyUnicode_Check(subobj)) {
  	    	int rc;
! 		rc = PyUnicode_Tailmatch((PyObject *)self, 
  					  subobj, start, end, -1);
  		if (rc == -1)
--- 1826,1830 ----
  	else if (PyUnicode_Check(subobj)) {
  	    	int rc;
! 		rc = PyUnicode_Tailmatch((PyObject *)self,
  					  subobj, start, end, -1);
  		if (rc == -1)
***************
*** 1735,1739 ****
  	else if (PyUnicode_Check(subobj)) {
  	    	int rc;
! 		rc = PyUnicode_Tailmatch((PyObject *)self, 
  					  subobj, start, end, +1);
  		if (rc == -1)
--- 1884,1888 ----
  	else if (PyUnicode_Check(subobj)) {
  	    	int rc;
! 		rc = PyUnicode_Tailmatch((PyObject *)self,
  					  subobj, start, end, +1);
  		if (rc == -1)
***************
*** 1758,1765 ****
  
  static char encode__doc__[] =
! "S.encode([encoding[,errors]]) -> string\n\
  \n\
! Return an encoded string version of S. Default encoding is the current\n\
! default string encoding. errors may be given to set a different error\n\
  handling scheme. Default is 'strict' meaning that encoding errors raise\n\
  a ValueError. Other possible values are 'ignore' and 'replace'.";
--- 1907,1914 ----
  
  static char encode__doc__[] =
! "S.encode([encoding[,errors]]) -> object\n\
  \n\
! Encodes S using the codec registered for encoding. encoding defaults\n\
! to the default encoding. errors may be given to set a different error\n\
  handling scheme. Default is 'strict' meaning that encoding errors raise\n\
  a ValueError. Other possible values are 'ignore' and 'replace'.";
***************
*** 1772,1779 ****
      if (!PyArg_ParseTuple(args, "|ss:encode", &encoding, &errors))
          return NULL;
!     return PyString_AsEncodedString((PyObject *)self, encoding, errors);
  }
  
  
  static char expandtabs__doc__[] =
  "S.expandtabs([tabsize]) -> string\n\
--- 1921,1947 ----
      if (!PyArg_ParseTuple(args, "|ss:encode", &encoding, &errors))
          return NULL;
!     return PyString_AsEncodedObject((PyObject *)self, encoding, errors);
  }
  
  
+ static char decode__doc__[] =
+ "S.decode([encoding[,errors]]) -> object\n\
+ \n\
+ Decodes S using the codec registered for encoding. encoding defaults\n\
+ to the default encoding. errors may be given to set a different error\n\
+ handling scheme. Default is 'strict' meaning that encoding errors raise\n\
+ a ValueError. Other possible values are 'ignore' and 'replace'.";
+ 
+ static PyObject *
+ string_decode(PyStringObject *self, PyObject *args)
+ {
+     char *encoding = NULL;
+     char *errors = NULL;
+     if (!PyArg_ParseTuple(args, "|ss:decode", &encoding, &errors))
+         return NULL;
+     return PyString_AsDecodedObject((PyObject *)self, encoding, errors);
+ }
+ 
+ 
  static char expandtabs__doc__[] =
  "S.expandtabs([tabsize]) -> string\n\
***************
*** 1837,1843 ****
  }
  
! static 
! PyObject *pad(PyStringObject *self, 
! 	      int left, 
  	      int right,
  	      char fill)
--- 2005,2011 ----
  }
  
! static
! PyObject *pad(PyStringObject *self,
! 	      int left,
  	      int right,
  	      char fill)
***************
*** 1855,1865 ****
      }
  
!     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)
--- 2023,2033 ----
      }
  
!     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)
***************
*** 2316,2320 ****
  
  
! static PyMethodDef 
  string_methods[] = {
  	/* Counterparts of the obsolete stropmodule functions; except
--- 2484,2488 ----
  
  
! static PyMethodDef
  string_methods[] = {
  	/* Counterparts of the obsolete stropmodule functions; except
***************
*** 2350,2353 ****
--- 2518,2522 ----
  	{"center",      (PyCFunction)string_center,      1, center__doc__},
  	{"encode",      (PyCFunction)string_encode,      1, encode__doc__},
+ 	{"decode",      (PyCFunction)string_decode,      1, decode__doc__},
  	{"expandtabs",  (PyCFunction)string_expandtabs,  1, expandtabs__doc__},
  	{"splitlines",  (PyCFunction)string_splitlines,  1, splitlines__doc__},
***************
*** 2388,2392 ****
  	0,					/* tp_getattr */
  	0,					/* tp_setattr */
! 	(cmpfunc)string_compare, 		/* tp_compare */
  	(reprfunc)string_repr, 			/* tp_repr */
  	0,					/* tp_as_number */
--- 2557,2561 ----
  	0,					/* tp_getattr */
  	0,					/* tp_setattr */
! 	0,					/* tp_compare */
  	(reprfunc)string_repr, 			/* tp_repr */
  	0,					/* tp_as_number */
***************
*** 2403,2407 ****
  	0,					/* tp_traverse */
  	0,					/* tp_clear */
! 	0,					/* tp_richcompare */
  	0,					/* tp_weaklistoffset */
  	0,					/* tp_iter */
--- 2572,2576 ----
  	0,					/* tp_traverse */
  	0,					/* tp_clear */
! 	(richcmpfunc)string_richcompare,	/* tp_richcompare */
  	0,					/* tp_weaklistoffset */
  	0,					/* tp_iter */
***************
*** 2532,2536 ****
  	     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
--- 2701,2705 ----
  	     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
***************
*** 2555,2559 ****
   *         "-"? ("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.
--- 2724,2728 ----
   *         "-"? ("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.
***************
*** 2711,2717 ****
  	 * 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';
--- 2880,2892 ----
  	 * 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';
***************
*** 2796,2800 ****
  			int width = -1;
  			int prec = -1;
- 			int size = 0;
  			int c = '\0';
  			int fill;
--- 2971,2974 ----
***************
*** 2806,2810 ****
  			char formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */
  			char *fmt_start = fmt;
! 			
  			fmt++;
  			if (*fmt == '(') {
--- 2980,2985 ----
  			char formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */
  			char *fmt_start = fmt;
! 		        int argidx_start = argidx;
! 
  			fmt++;
  			if (*fmt == '(') {
***************
*** 2816,2820 ****
  				if (dict == NULL) {
  					PyErr_SetString(PyExc_TypeError,
! 						 "format requires a mapping"); 
  					goto error;
  				}
--- 2991,2995 ----
  				if (dict == NULL) {
  					PyErr_SetString(PyExc_TypeError,
! 						 "format requires a mapping");
  					goto error;
  				}
***************
*** 2933,2937 ****
  			if (fmtcnt >= 0) {
  				if (c == 'h' || c == 'l' || c == 'L') {
- 					size = c;
  					if (--fmtcnt >= 0)
  						c = *fmt++;
--- 3108,3111 ----
***************
*** 2959,2962 ****
--- 3133,3137 ----
  				if (PyUnicode_Check(v)) {
  					fmt = fmt_start;
+ 					argidx = argidx_start;
  					goto unicode;
  				}
***************
*** 3123,3128 ****
  		args_owned = 0;
  	}
! 	/* Fiddle args right (remove the first argidx-1 arguments) */
! 	--argidx;
  	if (PyTuple_Check(orig_args) && argidx > 0) {
  		PyObject *v;
--- 3298,3302 ----
  		args_owned = 0;
  	}
! 	/* Fiddle args right (remove the first argidx arguments) */
  	if (PyTuple_Check(orig_args) && argidx > 0) {
  		PyObject *v;
***************
*** 3163,3167 ****
  	Py_DECREF(args);
  	return w;
! 	
   error:
  	Py_DECREF(result);
--- 3337,3341 ----
  	Py_DECREF(args);
  	return w;
! 
   error:
  	Py_DECREF(result);

Index: tupleobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v
retrieving revision 2.48.6.3
retrieving revision 2.48.6.4
diff -C2 -r2.48.6.3 -r2.48.6.4
*** tupleobject.c	2001/06/14 01:01:16	2.48.6.3
--- tupleobject.c	2001/07/07 22:55:30	2.48.6.4
***************
*** 185,202 ****
  tuplerepr(PyTupleObject *v)
  {
! 	PyObject *s, *comma;
! 	int i;
  	s = PyString_FromString("(");
! 	comma = PyString_FromString(", ");
! 	for (i = 0; i < v->ob_size && s != NULL; i++) {
! 		if (i > 0)
! 			PyString_Concat(&s, comma);
! 		PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i]));
! 	}
! 	Py_DECREF(comma);
! 	if (v->ob_size == 1)
! 		PyString_ConcatAndDel(&s, PyString_FromString(","));
! 	PyString_ConcatAndDel(&s, PyString_FromString(")"));
! 	return s;
  }
  
--- 185,238 ----
  tuplerepr(PyTupleObject *v)
  {
! 	int i, n;
! 	PyObject *s, *temp;
! 	PyObject *pieces, *result = NULL;
! 
! 	n = v->ob_size;
! 	if (n == 0)
! 		return PyString_FromString("()");
! 
! 	pieces = PyTuple_New(n);
! 	if (pieces == NULL)
! 		return NULL;
! 
! 	/* Do repr() on each element. */
! 	for (i = 0; i < n; ++i) {
! 		s = PyObject_Repr(v->ob_item[i]);
! 		if (s == NULL)
! 			goto Done;
! 		PyTuple_SET_ITEM(pieces, i, s);
! 	}
! 
! 	/* Add "()" decorations to the first and last items. */
! 	assert(n > 0);
  	s = PyString_FromString("(");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyTuple_GET_ITEM(pieces, 0);
! 	PyString_ConcatAndDel(&s, temp);
! 	PyTuple_SET_ITEM(pieces, 0, s);
! 	if (s == NULL)
! 		goto Done;
! 
! 	s = PyString_FromString(n == 1 ? ",)" : ")");
! 	if (s == NULL)
! 		goto Done;
! 	temp = PyTuple_GET_ITEM(pieces, n-1);
! 	PyString_ConcatAndDel(&temp, s);
! 	PyTuple_SET_ITEM(pieces, n-1, temp);
! 	if (temp == NULL)
! 		goto Done;
! 
! 	/* Paste them all together with ", " between. */
! 	s = PyString_FromString(", ");
! 	if (s == NULL)
! 		goto Done;
! 	result = _PyString_Join(s, pieces);
! 	Py_DECREF(s);	
! 
! Done:
! 	Py_DECREF(pieces);
! 	return result;
  }
  
***************
*** 377,380 ****
--- 413,417 ----
  	PyTupleObject *vt, *wt;
  	int i;
+ 	int vlen, wlen;
  
  	if (!PyTuple_Check(v) || !PyTuple_Check(w)) {
***************
*** 386,402 ****
  	wt = (PyTupleObject *)w;
  
! 	if (vt->ob_size != wt->ob_size && (op == Py_EQ || op == Py_NE)) {
! 		/* Shortcut: if the lengths differ, the tuples differ */
! 		PyObject *res;
! 		if (op == Py_EQ)
! 			res = Py_False;
! 		else
! 			res = Py_True;
! 		Py_INCREF(res);
! 		return res;
! 	}
  
! 	/* Search for the first index where items are different */
! 	for (i = 0; i < vt->ob_size && i < wt->ob_size; i++) {
  		int k = PyObject_RichCompareBool(vt->ob_item[i],
  						 wt->ob_item[i], Py_EQ);
--- 423,441 ----
  	wt = (PyTupleObject *)w;
  
! 	vlen = vt->ob_size;
! 	wlen = wt->ob_size;
  
! 	/* Note:  the corresponding code for lists has an "early out" test
! 	 * here when op is EQ or NE and the lengths differ.  That pays there,
! 	 * but Tim was unable to find any real code where EQ/NE tuple
! 	 * compares don't have the same length, so testing for it here would
! 	 * have cost without benefit.
! 	 */
! 
! 	/* Search for the first index where items are different.
! 	 * Note that because tuples are immutable, it's safe to reuse
! 	 * vlen and wlen across the comparison calls.
! 	 */
! 	for (i = 0; i < vlen && i < wlen; i++) {
  		int k = PyObject_RichCompareBool(vt->ob_item[i],
  						 wt->ob_item[i], Py_EQ);
***************
*** 407,423 ****
  	}
  
! 	if (i >= vt->ob_size || i >= wt->ob_size) {
  		/* No more items to compare -- compare sizes */
- 		int vs = vt->ob_size;
- 		int ws = wt->ob_size;
  		int cmp;
  		PyObject *res;
  		switch (op) {
! 		case Py_LT: cmp = vs <  ws; break;
! 		case Py_LE: cmp = ws <= ws; break;
! 		case Py_EQ: cmp = vs == ws; break;
! 		case Py_NE: cmp = vs != ws; break;
! 		case Py_GT: cmp = vs >  ws; break;
! 		case Py_GE: cmp = vs >= ws; break;
  		default: return NULL; /* cannot happen */
  		}
--- 446,460 ----
  	}
  
! 	if (i >= vlen || i >= wlen) {
  		/* No more items to compare -- compare sizes */
  		int cmp;
  		PyObject *res;
  		switch (op) {
! 		case Py_LT: cmp = vlen <  wlen; break;
! 		case Py_LE: cmp = vlen <= wlen; break;
! 		case Py_EQ: cmp = vlen == wlen; break;
! 		case Py_NE: cmp = vlen != wlen; break;
! 		case Py_GT: cmp = vlen >  wlen; break;
! 		case Py_GE: cmp = vlen >= wlen; break;
  		default: return NULL; /* cannot happen */
  		}
***************
*** 524,532 ****
     as creating a new tuple object and destroying the old one, only more
     efficiently.  In any case, don't use this if the tuple may already be
!    known to some other part of the code.  The last_is_sticky is not used
!    and must always be false. */
  
  int
! _PyTuple_Resize(PyObject **pv, int newsize, int last_is_sticky)
  {
  	register PyTupleObject *v;
--- 561,568 ----
     as creating a new tuple object and destroying the old one, only more
     efficiently.  In any case, don't use this if the tuple may already be
!    known to some other part of the code. */
  
  int
! _PyTuple_Resize(PyObject **pv, int newsize)
  {
  	register PyTupleObject *v;
***************
*** 536,541 ****
  
  	v = (PyTupleObject *) *pv;
! 	if (v == NULL || !PyTuple_Check(v) || v->ob_refcnt != 1 ||
!              last_is_sticky) {
  		*pv = 0;
  		Py_XDECREF(v);
--- 572,577 ----
  
  	v = (PyTupleObject *) *pv;
! 	if (v == NULL || !PyTuple_Check(v) ||
! 	    (v->ob_size != 0 && v->ob_refcnt != 1)) {
  		*pv = 0;
  		Py_XDECREF(v);
***************
*** 546,549 ****
--- 582,594 ----
  	if (sizediff == 0)
  		return 0;
+ 
+ 	if (v->ob_size == 0) {
+ 		/* Empty tuples are often shared, so we should never 
+ 		   resize them in-place even if we do own the only
+ 		   (current) reference */
+ 		Py_DECREF(v);
+ 		*pv = PyTuple_New(newsize);
+ 		return *pv == NULL ? -1 : 0;
+ 	}
  
  	/* XXX UNREF/NEWREF interface should be more symmetrical */

Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.62
retrieving revision 2.16.8.63
diff -C2 -r2.16.8.62 -r2.16.8.63
*** typeobject.c	2001/07/05 21:39:52	2.16.8.62
--- typeobject.c	2001/07/07 22:55:30	2.16.8.63
***************
*** 75,78 ****
--- 75,88 ----
  };
  
+ static int
+ type_compare(PyObject *v, PyObject *w)
+ {
+ 	/* This is called with type objects only. So we
+ 	   can just compare the addresses. */
+ 	Py_uintptr_t vv = (Py_uintptr_t)v;
+ 	Py_uintptr_t ww = (Py_uintptr_t)w;
+ 	return (vv < ww) ? -1 : (vv > ww) ? 1 : 0;
+ }
+ 
  static PyObject *
  type_repr(PyTypeObject *type)
***************
*** 774,783 ****
  	0,			 		/* tp_getattr */
  	0,					/* tp_setattr */
! 	0,					/* tp_compare */
  	(reprfunc)type_repr,			/* tp_repr */
  	0,					/* tp_as_number */
  	0,					/* tp_as_sequence */
  	0,					/* tp_as_mapping */
! 	0,					/* tp_hash */
  	(ternaryfunc)type_call,			/* tp_call */
  	0,					/* tp_str */
--- 784,793 ----
  	0,			 		/* tp_getattr */
  	0,					/* tp_setattr */
! 	type_compare,				/* tp_compare */
  	(reprfunc)type_repr,			/* tp_repr */
  	0,					/* tp_as_number */
  	0,					/* tp_as_sequence */
  	0,					/* tp_as_mapping */
! 	(hashfunc)_Py_HashPointer,		/* tp_hash */
  	(ternaryfunc)type_call,			/* tp_call */
  	0,					/* tp_str */

Index: unicodectype.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/unicodectype.c,v
retrieving revision 2.7
retrieving revision 2.7.8.1
diff -C2 -r2.7 -r2.7.8.1
*** unicodectype.c	2000/09/25 21:48:13	2.7
--- unicodectype.c	2001/07/07 22:55:30	2.7.8.1
***************
*** 33,41 ****
  
  static const _PyUnicode_TypeRecord *
! gettyperecord(int code)
  {
      int index;
  
!     if (code < 0 || code >= 65536)
          index = 0;
      else {
--- 33,41 ----
  
  static const _PyUnicode_TypeRecord *
! gettyperecord(Py_UNICODE code)
  {
      int index;
  
!     if (code >= 65536)
          index = 0;
      else {
***************
*** 43,46 ****
--- 43,47 ----
          index = index2[(index<<SHIFT)+(code&((1<<SHIFT)-1))];
      }
+ 
      return &_PyUnicode_TypeRecords[index];
  }
***************
*** 49,53 ****
     'B', 0 otherwise. */
  
! int _PyUnicode_IsLinebreak(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
--- 50,54 ----
     'B', 0 otherwise. */
  
! int _PyUnicode_IsLinebreak(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
***************
*** 59,70 ****
     ch if no titlecase mapping is known. */
  
! Py_UNICODE _PyUnicode_ToTitlecase(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
  
      if (ctype->title)
!         return ch + ctype->title;
! 
!     return ch + ctype->upper;
  }
  
--- 60,78 ----
     ch if no titlecase mapping is known. */
  
! Py_UNICODE _PyUnicode_ToTitlecase(register Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
  
      if (ctype->title)
!         ch += ctype->title;
!     else
! 	ch += ctype->upper;
! 
! #ifdef Py_UNICODE_WIDE
!     /* The database assumes that the values wrap around at 0x10000. */
!     if (ch > 0x10000)
! 	ch -= 0x10000;
! #endif
!     return ch;
  }
  
***************
*** 72,76 ****
     otherwise. */
  
! int _PyUnicode_IsTitlecase(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
--- 80,84 ----
     otherwise. */
  
! int _PyUnicode_IsTitlecase(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
***************
*** 82,86 ****
     this property, -1 otherwise. */
  
! int _PyUnicode_ToDecimalDigit(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
--- 90,94 ----
     this property, -1 otherwise. */
  
! int _PyUnicode_ToDecimalDigit(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
***************
*** 89,93 ****
  }
  
! int _PyUnicode_IsDecimalDigit(register const Py_UNICODE ch)
  {
      if (_PyUnicode_ToDecimalDigit(ch) < 0)
--- 97,101 ----
  }
  
! int _PyUnicode_IsDecimalDigit(Py_UNICODE ch)
  {
      if (_PyUnicode_ToDecimalDigit(ch) < 0)
***************
*** 99,103 ****
     this property, -1 otherwise. */
  
! int _PyUnicode_ToDigit(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
--- 107,111 ----
     this property, -1 otherwise. */
  
! int _PyUnicode_ToDigit(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
***************
*** 106,110 ****
  }
  
! int _PyUnicode_IsDigit(register const Py_UNICODE ch)
  {
      if (_PyUnicode_ToDigit(ch) < 0)
--- 114,118 ----
  }
  
! int _PyUnicode_IsDigit(Py_UNICODE ch)
  {
      if (_PyUnicode_ToDigit(ch) < 0)
***************
*** 118,122 ****
  /* TODO: replace with unicodetype_db.h table */
  
! double _PyUnicode_ToNumeric(register const Py_UNICODE ch)
  {
      switch (ch) {
--- 126,130 ----
  /* TODO: replace with unicodetype_db.h table */
  
! double _PyUnicode_ToNumeric(Py_UNICODE ch)
  {
      switch (ch) {
***************
*** 306,310 ****
  }
  
! int _PyUnicode_IsNumeric(register const Py_UNICODE ch)
  {
      if (_PyUnicode_ToNumeric(ch) < 0.0)
--- 314,318 ----
  }
  
! int _PyUnicode_IsNumeric(Py_UNICODE ch)
  {
      if (_PyUnicode_ToNumeric(ch) < 0.0)
***************
*** 318,322 ****
     'WS', 'B' or 'S' or the category 'Zs', 0 otherwise. */
  
! int _PyUnicode_IsWhitespace(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
--- 326,330 ----
     'WS', 'B' or 'S' or the category 'Zs', 0 otherwise. */
  
! int _PyUnicode_IsWhitespace(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
***************
*** 328,332 ****
     otherwise. */
  
! int _PyUnicode_IsLowercase(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
--- 336,340 ----
     otherwise. */
  
! int _PyUnicode_IsLowercase(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
***************
*** 338,342 ****
     otherwise. */
  
! int _PyUnicode_IsUppercase(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
--- 346,350 ----
     otherwise. */
  
! int _PyUnicode_IsUppercase(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
***************
*** 348,356 ****
     ch if no uppercase mapping is known. */
  
! Py_UNICODE _PyUnicode_ToUppercase(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
  
!     return ch + ctype->upper;
  }
  
--- 356,370 ----
     ch if no uppercase mapping is known. */
  
! Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
  
!     ch += ctype->upper;
! #ifdef Py_UNICODE_WIDE
!     /* The database assumes that the values wrap around at 0x10000. */
!     if (ch > 0x10000)
! 	ch -= 0x10000;
! #endif
!     return ch;
  }
  
***************
*** 358,366 ****
     ch if no lowercase mapping is known. */
  
! Py_UNICODE _PyUnicode_ToLowercase(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
  
!     return ch + ctype->lower;
  }
  
--- 372,386 ----
     ch if no lowercase mapping is known. */
  
! Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
  
!     ch += ctype->lower;
! #ifdef Py_UNICODE_WIDE
!     /* The database assumes that the values wrap around at 0x10000. */
!     if (ch > 0x10000)
! 	ch -= 0x10000;
! #endif
!     return ch;
  }
  
***************
*** 368,372 ****
     'Lo' or 'Lm',  0 otherwise. */
  
! int _PyUnicode_IsAlpha(register const Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
--- 388,392 ----
     'Lo' or 'Lm',  0 otherwise. */
  
! int _PyUnicode_IsAlpha(Py_UNICODE ch)
  {
      const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
***************
*** 380,409 ****
     reasons:  */
  
! int _PyUnicode_IsWhitespace(register const Py_UNICODE ch)
  {
      return iswspace(ch);
  }
  
! int _PyUnicode_IsLowercase(register const Py_UNICODE ch)
  {
      return iswlower(ch);
  }
  
! int _PyUnicode_IsUppercase(register const Py_UNICODE ch)
  {
      return iswupper(ch);
  }
  
! Py_UNICODE _PyUnicode_ToLowercase(register const Py_UNICODE ch)
  {
      return towlower(ch);
  }
  
! Py_UNICODE _PyUnicode_ToUppercase(register const Py_UNICODE ch)
  {
      return towupper(ch);
  }
  
! int _PyUnicode_IsAlpha(register const Py_UNICODE ch)
  {
      return iswalpha(ch);
--- 400,429 ----
     reasons:  */
  
! int _PyUnicode_IsWhitespace(Py_UNICODE ch)
  {
      return iswspace(ch);
  }
  
! int _PyUnicode_IsLowercase(Py_UNICODE ch)
  {
      return iswlower(ch);
  }
  
! int _PyUnicode_IsUppercase(Py_UNICODE ch)
  {
      return iswupper(ch);
  }
  
! Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch)
  {
      return towlower(ch);
  }
  
! Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch)
  {
      return towupper(ch);
  }
  
! int _PyUnicode_IsAlpha(Py_UNICODE ch)
  {
      return iswalpha(ch);

Index: unicodeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/unicodeobject.c,v
retrieving revision 2.87.2.4
retrieving revision 2.87.2.5
diff -C2 -r2.87.2.4 -r2.87.2.5
*** unicodeobject.c	2001/06/14 18:12:02	2.87.2.4
--- unicodeobject.c	2001/07/07 22:55:30	2.87.2.5
***************
*** 104,107 ****
--- 104,119 ----
  static char unicode_default_encoding[100];
  
+ Py_UNICODE
+ PyUnicode_GetMax()
+ {
+ #ifdef Py_UNICODE_WIDE
+ 	return 0x10FFFF;
+ #else
+ 	/* This is actually an illegal character, so it should
+ 	   not be passed to unichr. */
+ 	return 0xFFFF;
+ #endif
+ }
+ 
  /* --- Unicode Object ----------------------------------------------------- */
  
***************
*** 184,191 ****
  	    }
  	}
! 	else {
  	    unicode->str = PyMem_NEW(Py_UNICODE, length + 1);
! 	}
! 	PyObject_INIT(unicode, &PyUnicode_Type);
      }
      else {
--- 196,203 ----
  	    }
  	}
!         else {
  	    unicode->str = PyMem_NEW(Py_UNICODE, length + 1);
!         }
!         PyObject_INIT(unicode, &PyUnicode_Type);
      }
      else {
***************
*** 298,304 ****
  	    if (!unicode) {
  		unicode = _PyUnicode_New(1);
- 		unicode->str[0] = *u;
  		if (!unicode)
  		    return NULL;
  		unicode_latin1[*u] = unicode;
  	    }
--- 310,316 ----
  	    if (!unicode) {
  		unicode = _PyUnicode_New(1);
  		if (!unicode)
  		    return NULL;
+ 		unicode->str[0] = *u;
  		unicode_latin1[*u] = unicode;
  	    }
***************
*** 530,534 ****
      if (errors == NULL) {
  	if (strcmp(encoding, "utf-8") == 0)
!         return PyUnicode_AsUTF8String(unicode);
  	else if (strcmp(encoding, "latin-1") == 0)
  	    return PyUnicode_AsLatin1String(unicode);
--- 542,546 ----
      if (errors == NULL) {
  	if (strcmp(encoding, "utf-8") == 0)
! 	    return PyUnicode_AsUTF8String(unicode);
  	else if (strcmp(encoding, "latin-1") == 0)
  	    return PyUnicode_AsLatin1String(unicode);
***************
*** 772,782 ****
                   ((s[2] & 0x3f) << 6) + (s[3] & 0x3f);
              /* validate and convert to UTF-16 */
!             if ((ch < 0x10000) ||   /* minimum value allowed for 4
                                         byte encoding */
!                 (ch > 0x10ffff)) {  /* maximum value allowed for
                                         UTF-16 */
                  errmsg = "illegal encoding";
  		goto utf8Error;
  	    }
              /*  compute and append the two surrogates: */
              
--- 784,798 ----
                   ((s[2] & 0x3f) << 6) + (s[3] & 0x3f);
              /* validate and convert to UTF-16 */
!             if ((ch < 0x10000)        /* minimum value allowed for 4
                                         byte encoding */
!                 || (ch > 0x10ffff))   /* maximum value allowed for
                                         UTF-16 */
+ 	    {
                  errmsg = "illegal encoding";
  		goto utf8Error;
  	    }
+ #ifdef Py_UNICODE_WIDE
+ 	    *p++ = (Py_UNICODE)ch;
+ #else
              /*  compute and append the two surrogates: */
              
***************
*** 788,792 ****
                      
              /*  low surrogate = bottom 10 bits added to DC00 */
!             *p++ = (Py_UNICODE)(0xDC00 + (ch & ~0xFC00));
              break;
  
--- 804,809 ----
                      
              /*  low surrogate = bottom 10 bits added to DC00 */
!             *p++ = (Py_UNICODE)(0xDC00 + (ch & 0x03FF));
! #endif
              break;
  
***************
*** 879,883 ****
              cbWritten += 2;
          }
!         else {
              /* Check for high surrogate */
              if (0xD800 <= ch && ch <= 0xDBFF) {
--- 896,900 ----
              cbWritten += 2;
          }
!         else if (ch < 0x10000) {
              /* Check for high surrogate */
              if (0xD800 <= ch && ch <= 0xDBFF) {
***************
*** 910,914 ****
              *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
              *p++ = (char)(0x80 | (ch & 0x3f));
!         }
      }
      *p = '\0';
--- 927,937 ----
              *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
              *p++ = (char)(0x80 | (ch & 0x3f));
!         } else {
!             *p++ = 0xf0 | (ch>>18);
!             *p++ = 0x80 | ((ch>>12) & 0x3f);
!             *p++ = 0x80 | ((ch>>6) & 0x3f);
!             *p++ = 0x80 | (ch & 0x3f);
!             cbWritten += 4;
! 	}
      }
      *p = '\0';
***************
*** 936,940 ****
  
  static
! int utf16_decoding_error(const Py_UNICODE **source,
  			 Py_UNICODE **dest,
  			 const char *errors,
--- 959,963 ----
  
  static
! int utf16_decoding_error(const Py_UCS2 **source,
  			 Py_UNICODE **dest,
  			 const char *errors,
***************
*** 974,983 ****
      PyUnicodeObject *unicode;
      Py_UNICODE *p;
!     const Py_UNICODE *q, *e;
      int bo = 0;
      const char *errmsg = "";
  
      /* size should be an even number */
!     if (size % sizeof(Py_UNICODE) != 0) {
  	if (utf16_decoding_error(NULL, NULL, errors, "truncated data"))
  	    return NULL;
--- 997,1006 ----
      PyUnicodeObject *unicode;
      Py_UNICODE *p;
!     const Py_UCS2 *q, *e;
      int bo = 0;
      const char *errmsg = "";
  
      /* size should be an even number */
!     if (size % sizeof(Py_UCS2) != 0) {
  	if (utf16_decoding_error(NULL, NULL, errors, "truncated data"))
  	    return NULL;
***************
*** 996,1030 ****
      /* Unpack UTF-16 encoded data */
      p = unicode->str;
!     q = (Py_UNICODE *)s;
!     e = q + (size / sizeof(Py_UNICODE));
  
      if (byteorder)
  	bo = *byteorder;
- 
-     while (q < e) {
- 	register Py_UNICODE ch = *q++;
  
! 	/* Check for BOM marks (U+FEFF) in the input and adjust
! 	   current byte order setting accordingly. Swap input
! 	   bytes if needed. (This assumes sizeof(Py_UNICODE) == 2
! 	   !) */
  #ifdef BYTEORDER_IS_LITTLE_ENDIAN
! 	if (ch == 0xFEFF) {
  	    bo = -1;
! 	    continue;
! 	} else if (ch == 0xFFFE) {
  	    bo = 1;
- 	    continue;
  	}
- 	if (bo == 1)
- 	    ch = (ch >> 8) | (ch << 8);
  #else    
! 	if (ch == 0xFEFF) {
  	    bo = 1;
! 	    continue;
! 	} else if (ch == 0xFFFE) {
  	    bo = -1;
- 	    continue;
  	}
  	if (bo == -1)
  	    ch = (ch >> 8) | (ch << 8);
--- 1019,1061 ----
      /* Unpack UTF-16 encoded data */
      p = unicode->str;
!     q = (Py_UCS2 *)s;
!     e = q + (size / sizeof(Py_UCS2));
  
      if (byteorder)
  	bo = *byteorder;
  
!     /* Check for BOM marks (U+FEFF) in the input and adjust current
!        byte order setting accordingly. In native mode, the leading BOM
!        mark is skipped, in all other modes, it is copied to the output
!        stream as-is (giving a ZWNBSP character). */
!     if (bo == 0) {
  #ifdef BYTEORDER_IS_LITTLE_ENDIAN
! 	if (*q == 0xFEFF) {
! 	    q++;
  	    bo = -1;
! 	} else if (*q == 0xFFFE) {
! 	    q++;
  	    bo = 1;
  	}
  #else    
! 	if (*q == 0xFEFF) {
! 	    q++;
  	    bo = 1;
! 	} else if (*q == 0xFFFE) {
! 	    q++;
  	    bo = -1;
  	}
+ #endif
+     }
+     
+     while (q < e) {
+ 	register Py_UCS2 ch = *q++;
+ 
+ 	/* Swap input bytes if needed. (This assumes
+ 	   sizeof(Py_UNICODE) == 2 !) */
+ #ifdef BYTEORDER_IS_LITTLE_ENDIAN
+ 	if (bo == 1)
+ 	    ch = (ch >> 8) | (ch << 8);
+ #else    
  	if (bo == -1)
  	    ch = (ch >> 8) | (ch << 8);
***************
*** 1040,1046 ****
  	    goto utf16Error;
  	}
! 	if (0xDC00 <= *q && *q <= 0xDFFF) {
! 	    q++;
! 	    if (0xD800 <= *q && *q <= 0xDBFF) {
  		/* This is valid data (a UTF-16 surrogate pair), but
  		   we are not able to store this information since our
--- 1071,1085 ----
  	    goto utf16Error;
  	}
! 	if (0xD800 <= ch && ch <= 0xDBFF) {
! 	    Py_UCS2 ch2 = *q++;
! #ifdef BYTEORDER_IS_LITTLE_ENDIAN
! 	    if (bo == 1)
! 		    ch2 = (ch2 >> 8) | (ch2 << 8);
! #else    
! 	    if (bo == -1)
! 		    ch2 = (ch2 >> 8) | (ch2 << 8);
! #endif
! 	    if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
! #ifndef Py_UNICODE_WIDE
  		/* This is valid data (a UTF-16 surrogate pair), but
  		   we are not able to store this information since our
***************
*** 1049,1055 ****
  		errmsg = "code pairs are not supported";
  		goto utf16Error;
! 	    }
! 	    else
  		continue;
  	}
  	errmsg = "illegal encoding";
--- 1088,1102 ----
  		errmsg = "code pairs are not supported";
  		goto utf16Error;
! #else
! 		*p++ = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000;
  		continue;
+ #endif
+ 		
+ 	    }
+ 	    else {
+                 errmsg = "illegal UTF-16 surrogate";
+ 		goto utf16Error;
+ 	    }
+ 
  	}
  	errmsg = "illegal encoding";
***************
*** 1083,1097 ****
  {
      PyObject *v;
!     Py_UNICODE *p;
      char *q;
  
!     /* We don't create UTF-16 pairs... */
      v = PyString_FromStringAndSize(NULL, 
! 			sizeof(Py_UNICODE) * (size + (byteorder == 0)));
      if (v == NULL)
          return NULL;
  
      q = PyString_AS_STRING(v);
!     p = (Py_UNICODE *)q;
      if (byteorder == 0)
  	*p++ = 0xFEFF;
--- 1130,1147 ----
  {
      PyObject *v;
!     Py_UCS2 *p;
      char *q;
+     int i, pairs, doswap = 1;
  
!     for (i = pairs = 0; i < size; i++)
! 	if (s[i] >= 0x10000)
! 	    pairs++;
      v = PyString_FromStringAndSize(NULL, 
! 		  sizeof(Py_UCS2) * (size + pairs + (byteorder == 0)));
      if (v == NULL)
          return NULL;
  
      q = PyString_AS_STRING(v);
!     p = (Py_UCS2 *)q;
      if (byteorder == 0)
  	*p++ = 0xFEFF;
***************
*** 1105,1114 ****
  #endif
  	)
! 	Py_UNICODE_COPY(p, s, size);
!     else
! 	while (size-- > 0) {
! 	    Py_UNICODE ch = *s++;
  	    *p++ = (ch >> 8) | (ch << 8);
  	}
      return v;
  }
--- 1155,1176 ----
  #endif
  	)
! 	doswap = 0;
!     while (size-- > 0) {
! 	Py_UNICODE ch = *s++;
! 	Py_UNICODE ch2 = 0;
! 	if (ch >= 0x10000) {
! 	    ch2 = 0xDC00|((ch-0x10000) & 0x3FF);
! 	    ch  = 0xD800|((ch-0x10000)>>10);
! 	}
! 	if (doswap){
  	    *p++ = (ch >> 8) | (ch << 8);
+ 	    if (ch2)
+ 		*p++ = (ch2 >> 8) | (ch2 << 8);
+ 	}else{
+ 	    *p++ = ch;
+ 	    if(ch2)
+ 		*p++ = ch2;
  	}
+     }
      return v;
  }
***************
*** 1264,1271 ****
                  *p++ = (Py_UNICODE) chr;
              else if (chr <= 0x10ffff) {
!                 /* UCS-4 character.  store as two surrogate characters */
                  chr -= 0x10000L;
                  *p++ = 0xD800 + (Py_UNICODE) (chr >> 10);
!                 *p++ = 0xDC00 + (Py_UNICODE) (chr & ~0xFC00);
              } else {
                  if (unicodeescape_decoding_error(
--- 1326,1337 ----
                  *p++ = (Py_UNICODE) chr;
              else if (chr <= 0x10ffff) {
!                 /* UCS-4 character. Either store directly, or as surrogate pair. */
! #ifdef Py_UNICODE_WIDE
!                 *p++ = chr;
! #else
                  chr -= 0x10000L;
                  *p++ = 0xD800 + (Py_UNICODE) (chr >> 10);
!                 *p++ = 0xDC00 + (Py_UNICODE) (chr & 0x03FF);
! #endif
              } else {
                  if (unicodeescape_decoding_error(
***************
*** 1372,1379 ****
          Py_UNICODE ch = *s++;
          /* Escape quotes */
!         if (quotes && (ch == q[1] || ch == '\\')) {
              *p++ = '\\';
              *p++ = (char) ch;
          } 
          /* Map 16-bit characters to '\uxxxx' */
          else if (ch >= 256) {
--- 1438,1458 ----
          Py_UNICODE ch = *s++;
          /* Escape quotes */
!         if (quotes && (ch == (Py_UNICODE) q[1] || ch == '\\')) {
              *p++ = '\\';
              *p++ = (char) ch;
          } 
+         /* Map 21-bit characters to '\U00xxxxxx' */
+         else if (ch >= 0x10000) {
+             *p++ = '\\';
+             *p++ = 'U';
+             *p++ = hexdigit[(ch >> 28) & 0xf];
+             *p++ = hexdigit[(ch >> 24) & 0xf];
+             *p++ = hexdigit[(ch >> 20) & 0xf];
+             *p++ = hexdigit[(ch >> 16) & 0xf];
+             *p++ = hexdigit[(ch >> 12) & 0xf];
+             *p++ = hexdigit[(ch >> 8) & 0xf];
+             *p++ = hexdigit[(ch >> 4) & 0xf];
+             *p++ = hexdigit[ch & 15];
+         }
          /* Map 16-bit characters to '\uxxxx' */
          else if (ch >= 256) {
***************
*** 1824,1828 ****
  }
  
! #ifdef MS_WIN32
  
  /* --- MBCS codecs for Windows -------------------------------------------- */
--- 1903,1907 ----
  }
  
! #if defined(MS_WIN32) && defined(HAVE_USABLE_WCHAR_T)
  
  /* --- MBCS codecs for Windows -------------------------------------------- */
***************
*** 2722,2732 ****
      int reslen = 0;
      Py_UNICODE *p;
-     int seqlen = 0;
      int sz = 100;
      int i;
  
!     seqlen = PySequence_Size(seq);
!     if (seqlen < 0 && PyErr_Occurred())
! 	return NULL;
  
      if (separator == NULL) {
--- 2801,2811 ----
      int reslen = 0;
      Py_UNICODE *p;
      int sz = 100;
      int i;
+     PyObject *it;
  
!     it = PyObject_GetIter(seq);
!     if (it == NULL)
!         return NULL;
  
      if (separator == NULL) {
***************
*** 2738,2742 ****
  	separator = PyUnicode_FromObject(separator);
  	if (separator == NULL)
! 	    return NULL;
  	sep = PyUnicode_AS_UNICODE(separator);
  	seplen = PyUnicode_GET_SIZE(separator);
--- 2817,2821 ----
  	separator = PyUnicode_FromObject(separator);
  	if (separator == NULL)
! 	    goto onError;
  	sep = PyUnicode_AS_UNICODE(separator);
  	seplen = PyUnicode_GET_SIZE(separator);
***************
*** 2749,2759 ****
      reslen = 0;
  
!     for (i = 0; i < seqlen; i++) {
  	int itemlen;
! 	PyObject *item;
! 
! 	item = PySequence_GetItem(seq, i);
! 	if (item == NULL)
! 	    goto onError;
  	if (!PyUnicode_Check(item)) {
  	    PyObject *v;
--- 2828,2839 ----
      reslen = 0;
  
!     for (i = 0; ; ++i) {
  	int itemlen;
! 	PyObject *item = PyIter_Next(it);
! 	if (item == NULL) {
! 	    if (PyErr_Occurred())
! 		goto onError;
! 	    break;
! 	}
  	if (!PyUnicode_Check(item)) {
  	    PyObject *v;
***************
*** 2785,2793 ****
  
      Py_XDECREF(separator);
      return (PyObject *)res;
  
   onError:
      Py_XDECREF(separator);
!     Py_DECREF(res);
      return NULL;
  }
--- 2865,2875 ----
  
      Py_XDECREF(separator);
+     Py_DECREF(it);
      return (PyObject *)res;
  
   onError:
      Py_XDECREF(separator);
!     Py_XDECREF(res);
!     Py_DECREF(it);
      return NULL;
  }
***************
*** 3250,3266 ****
      while (len1 > 0 && len2 > 0) {
          Py_UNICODE c1, c2;     
- 	long diff;
  
          c1 = *s1++;
          c2 = *s2++;
  	if (c1 > (1<<11) * 26)
  	    c1 += utf16Fixup[c1>>11];
  	if (c2 > (1<<11) * 26)
              c2 += utf16Fixup[c2>>11];
-         
          /* now c1 and c2 are in UTF-32-compatible order */
!         diff = (long)c1 - (long)c2;
!         if (diff)
!             return (diff < 0) ? -1 : (diff != 0);
          len1--; len2--;
      }
--- 3332,3348 ----
      while (len1 > 0 && len2 > 0) {
          Py_UNICODE c1, c2;     
  
          c1 = *s1++;
          c2 = *s2++;
+ 
  	if (c1 > (1<<11) * 26)
  	    c1 += utf16Fixup[c1>>11];
  	if (c2 > (1<<11) * 26)
              c2 += utf16Fixup[c2>>11];
          /* now c1 and c2 are in UTF-32-compatible order */
! 
!         if (c1 != c2)
!             return (c1 < c2) ? -1 : 1;
!         
          len1--; len2--;
      }
***************
*** 3283,3291 ****
      
      while (len1 > 0 && len2 > 0) {
! 	register long diff;
  
!         diff = (long)*s1++ - (long)*s2++;
!         if (diff)
!             return (diff < 0) ? -1 : (diff != 0);
          len1--; len2--;
      }
--- 3365,3376 ----
      
      while (len1 > 0 && len2 > 0) {
!         Py_UNICODE c1, c2;     
! 
!         c1 = *s1++;
!         c2 = *s2++;
  
!         if (c1 != c2)
!             return (c1 < c2) ? -1 : 1;
! 
          len1--; len2--;
      }
***************
*** 4732,4735 ****
--- 4817,4821 ----
      char fmt[64]; /* plenty big enough! */
      long x;
+     int use_native_c_format = 1;
  
      x = PyInt_AsLong(v);
***************
*** 4748,4756 ****
       * 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);
  }
--- 4834,4852 ----
       * 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);
  }
***************
*** 5292,5300 ****
  {
      int i;
- 
-     /* Doublecheck the configuration... */
-     if (sizeof(Py_UNICODE) != 2)
-         Py_FatalError("Unicode configuration error: "
- 		      "sizeof(Py_UNICODE) != 2 bytes");
  
      /* Init the implementation */
--- 5388,5391 ----