[Python-checkins] r46284 - in python/branches/blais-bytebuf: Doc/api/abstract.tex Doc/api/newtypes.tex Doc/lib/libstdtypes.tex Include/longobject.h Include/pyport.h Include/unicodeobject.h Lib/idlelib/configHelpSourceEdit.py Lib/popen2.py Lib/test/string_tests.py Lib/test/test_grp.py Misc/NEWS Misc/developers.txt Modules/_ctypes/libffi/configure Modules/_ctypes/libffi/configure.ac Modules/_ctypes/libffi/fficonfig.h.in Modules/_ctypes/libffi/fficonfig.py.in Modules/_ctypes/libffi/src/darwin Modules/_ctypes/libffi/src/powerpc/darwin.S Modules/_ctypes/libffi/src/powerpc/darwin_closure.S Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c Modules/_ctypes/libffi/src/prep_cif.c Modules/_ctypes/libffi/src/x86/darwin.S Modules/_ctypes/libffi/src/x86/ffi_darwin.c Modules/_ctypes/libffi/src/x86/ffitarget.h Modules/_struct.c Modules/cPickle.c Modules/gcmodule.c Modules/grpmodule.c Modules/parsermodule.c Modules/timemodule.c Objects/classobject.c Objects/floatobject.c Objects/longobject.c Objects/stringobject.c Objects/typeobject.c Objects/unicodeobject.c Objects/weakrefobject.c PC/pyconfig.h Python/ceval.c Python/import.c Python/mystrtoul.c Python/pystrtod.c

martin.blais python-checkins at python.org
Fri May 26 13:03:58 CEST 2006


Author: martin.blais
Date: Fri May 26 13:03:30 2006
New Revision: 46284

Added:
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/darwin/
      - copied from r46282, python/trunk/Modules/_ctypes/libffi/src/darwin/
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/darwin.S
      - copied unchanged from r46282, python/trunk/Modules/_ctypes/libffi/src/x86/darwin.S
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffi_darwin.c
      - copied unchanged from r46282, python/trunk/Modules/_ctypes/libffi/src/x86/ffi_darwin.c
Modified:
   python/branches/blais-bytebuf/Doc/api/abstract.tex
   python/branches/blais-bytebuf/Doc/api/newtypes.tex
   python/branches/blais-bytebuf/Doc/lib/libstdtypes.tex
   python/branches/blais-bytebuf/Include/longobject.h
   python/branches/blais-bytebuf/Include/pyport.h
   python/branches/blais-bytebuf/Include/unicodeobject.h
   python/branches/blais-bytebuf/Lib/idlelib/configHelpSourceEdit.py
   python/branches/blais-bytebuf/Lib/popen2.py
   python/branches/blais-bytebuf/Lib/test/string_tests.py
   python/branches/blais-bytebuf/Lib/test/test_grp.py
   python/branches/blais-bytebuf/Misc/NEWS
   python/branches/blais-bytebuf/Misc/developers.txt
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure.ac
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.h.in
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.py.in
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin.S
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/prep_cif.c
   python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffitarget.h
   python/branches/blais-bytebuf/Modules/_struct.c
   python/branches/blais-bytebuf/Modules/cPickle.c
   python/branches/blais-bytebuf/Modules/gcmodule.c
   python/branches/blais-bytebuf/Modules/grpmodule.c
   python/branches/blais-bytebuf/Modules/parsermodule.c
   python/branches/blais-bytebuf/Modules/timemodule.c
   python/branches/blais-bytebuf/Objects/classobject.c
   python/branches/blais-bytebuf/Objects/floatobject.c
   python/branches/blais-bytebuf/Objects/longobject.c
   python/branches/blais-bytebuf/Objects/stringobject.c
   python/branches/blais-bytebuf/Objects/typeobject.c
   python/branches/blais-bytebuf/Objects/unicodeobject.c
   python/branches/blais-bytebuf/Objects/weakrefobject.c
   python/branches/blais-bytebuf/PC/pyconfig.h
   python/branches/blais-bytebuf/Python/ceval.c
   python/branches/blais-bytebuf/Python/import.c
   python/branches/blais-bytebuf/Python/mystrtoul.c
   python/branches/blais-bytebuf/Python/pystrtod.c
Log:
Updated branch bytebuf to 46281

Modified: python/branches/blais-bytebuf/Doc/api/abstract.tex
==============================================================================
--- python/branches/blais-bytebuf/Doc/api/abstract.tex	(original)
+++ python/branches/blais-bytebuf/Doc/api/abstract.tex	Fri May 26 13:03:30 2006
@@ -260,6 +260,8 @@
   result of the call on success, or \NULL{} on failure.  This is the
   equivalent of the Python expression \samp{apply(\var{callable},
   \var{args})} or \samp{\var{callable}(*\var{args})}.
+  Note that if you only pass \ctype{PyObject *} args,
+  \cfunction{PyObject_CallFunctionObjArgs} is a faster alternative.
   \bifuncindex{apply}
 \end{cfuncdesc}
 
@@ -274,6 +276,8 @@
   indicating that no arguments are provided. Returns the result of the
   call on success, or \NULL{} on failure.  This is the equivalent of
   the Python expression \samp{\var{o}.\var{method}(\var{args})}.
+  Note that if you only pass \ctype{PyObject *} args,
+  \cfunction{PyObject_CallMethodObjArgs} is a faster alternative.
 \end{cfuncdesc}
 
 

Modified: python/branches/blais-bytebuf/Doc/api/newtypes.tex
==============================================================================
--- python/branches/blais-bytebuf/Doc/api/newtypes.tex	(original)
+++ python/branches/blais-bytebuf/Doc/api/newtypes.tex	Fri May 26 13:03:30 2006
@@ -990,10 +990,10 @@
   An optional pointer to the rich comparison function.
 
   The signature is the same as for \cfunction{PyObject_RichCompare()}.
-  The function should return \code{1} if the requested comparison
-  returns true, \code{0} if it returns false.  It should return
-  \code{-1} and set an exception condition when an error occurred
-  during the comparison.
+  The function should return the result of the comparison (usually
+  \code{Py_True} or \code{Py_False}).  If the comparison is undefined,
+  it must return \code{Py_NotImplemented}, if another error occurred
+  it must return \code{NULL} and set an exception condition.
 
   This field is inherited by subtypes together with
   \member{tp_compare} and \member{tp_hash}: a subtype inherits all

Modified: python/branches/blais-bytebuf/Doc/lib/libstdtypes.tex
==============================================================================
--- python/branches/blais-bytebuf/Doc/lib/libstdtypes.tex	(original)
+++ python/branches/blais-bytebuf/Doc/lib/libstdtypes.tex	Fri May 26 13:03:30 2006
@@ -727,6 +727,15 @@
 \versionchanged[Support for the \var{chars} argument]{2.2.2}
 \end{methoddesc}
 
+\begin{methoddesc}[string]{partition}{sep}
+Splits the string at the first occurence of \var{sep}, and return
+a 3-tuple containing the part before the separator, the separator
+itself, and the part after the separator.  If the separator is not
+found, return a 3-tuple containing the string itself, followed by
+two empty strings.
+\versionadded{2.5}
+\end{methoddesc}
+
 \begin{methoddesc}[string]{replace}{old, new\optional{, count}}
 Return a copy of the string with all occurrences of substring
 \var{old} replaced by \var{new}.  If the optional argument

Modified: python/branches/blais-bytebuf/Include/longobject.h
==============================================================================
--- python/branches/blais-bytebuf/Include/longobject.h	(original)
+++ python/branches/blais-bytebuf/Include/longobject.h	Fri May 26 13:03:30 2006
@@ -25,6 +25,7 @@
 PyAPI_FUNC(Py_ssize_t) _PyLong_AsSsize_t(PyObject *);
 PyAPI_FUNC(PyObject *) _PyLong_FromSize_t(size_t);
 PyAPI_FUNC(PyObject *) _PyLong_FromSsize_t(Py_ssize_t);
+PyAPI_DATA(int) _PyLong_DigitValue[256];
 
 /* _PyLong_AsScaledDouble returns a double x and an exponent e such that
    the true value is approximately equal to x * 2**(SHIFT*e).  e is >= 0.

Modified: python/branches/blais-bytebuf/Include/pyport.h
==============================================================================
--- python/branches/blais-bytebuf/Include/pyport.h	(original)
+++ python/branches/blais-bytebuf/Include/pyport.h	Fri May 26 13:03:30 2006
@@ -295,6 +295,15 @@
 #define Py_IS_INFINITY(X) ((X) && (X)*0.5 == (X))
 #endif
 
+/* Py_IS_FINITE(X)
+ * Return 1 if float or double arg is neither infinite nor NAN, else 0.
+ * Some compilers (e.g. VisualStudio) have intrisics for this, so a special
+ * macro for this particular test is useful
+ */
+#ifndef Py_IS_FINITE
+#define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X))
+#endif
+
 /* HUGE_VAL is supposed to expand to a positive double infinity.  Python
  * uses Py_HUGE_VAL instead because some platforms are broken in this
  * respect.  We used to embed code in pyport.h to try to worm around that,

Modified: python/branches/blais-bytebuf/Include/unicodeobject.h
==============================================================================
--- python/branches/blais-bytebuf/Include/unicodeobject.h	(original)
+++ python/branches/blais-bytebuf/Include/unicodeobject.h	Fri May 26 13:03:30 2006
@@ -184,6 +184,7 @@
 # define PyUnicode_GetMax PyUnicodeUCS2_GetMax
 # define PyUnicode_GetSize PyUnicodeUCS2_GetSize
 # define PyUnicode_Join PyUnicodeUCS2_Join
+# define PyUnicode_Partition PyUnicodeUCS2_Partition
 # define PyUnicode_Replace PyUnicodeUCS2_Replace
 # define PyUnicode_Resize PyUnicodeUCS2_Resize
 # define PyUnicode_SetDefaultEncoding PyUnicodeUCS2_SetDefaultEncoding
@@ -259,6 +260,7 @@
 # define PyUnicode_GetMax PyUnicodeUCS4_GetMax
 # define PyUnicode_GetSize PyUnicodeUCS4_GetSize
 # define PyUnicode_Join PyUnicodeUCS4_Join
+# define PyUnicode_Partition PyUnicodeUCS4_Partition
 # define PyUnicode_Replace PyUnicodeUCS4_Replace
 # define PyUnicode_Resize PyUnicodeUCS4_Resize
 # define PyUnicode_SetDefaultEncoding PyUnicodeUCS4_SetDefaultEncoding
@@ -1018,6 +1020,13 @@
     int keepends		/* If true, line end markers are included */
     );		
 
+/* Partition a string using a given separator. */
+
+PyAPI_FUNC(PyObject*) PyUnicode_Partition(
+    PyObject *s,		/* String to partition */
+    PyObject *sep		/* String separator */
+    );		
+
 /* Split a string giving a list of Unicode strings.
 
    If sep is NULL, splitting will be done at all whitespace

Modified: python/branches/blais-bytebuf/Lib/idlelib/configHelpSourceEdit.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/idlelib/configHelpSourceEdit.py	(original)
+++ python/branches/blais-bytebuf/Lib/idlelib/configHelpSourceEdit.py	Fri May 26 13:03:30 2006
@@ -151,6 +151,7 @@
                     pass
                 else:
                     # Mac Safari insists on using the URI form for local files
+                    self.result = list(self.result)
                     self.result[1] = "file://" + path
             self.destroy()
 

Modified: python/branches/blais-bytebuf/Lib/popen2.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/popen2.py	(original)
+++ python/branches/blais-bytebuf/Lib/popen2.py	Fri May 26 13:03:30 2006
@@ -72,8 +72,9 @@
         # In case the child hasn't been waited on, check if it's done.
         self.poll(_deadstate=sys.maxint)
         if self.sts < 0:
-            # Child is still running, keep us alive until we can wait on it.
-            _active.append(self)
+            if _active:
+                # Child is still running, keep us alive until we can wait on it.
+                _active.append(self)
 
     def _run_child(self, cmd):
         if isinstance(cmd, basestring):

Modified: python/branches/blais-bytebuf/Lib/test/string_tests.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/test/string_tests.py	(original)
+++ python/branches/blais-bytebuf/Lib/test/string_tests.py	Fri May 26 13:03:30 2006
@@ -555,15 +555,14 @@
         self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
         self.checkraises(TypeError, 'hello', 'replace', 'h', 42)
 
-### Commented out until the underlying libraries are fixed
-##    def test_replace_overflow(self):
-##        # Check for overflow checking on 32 bit machines
-##        if sys.maxint != 2147483647:
-##            return
-##        A2_16 = "A" * (2**16)
-##        self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
-##        self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
-##        self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
+    def test_replace_overflow(self):
+        # Check for overflow checking on 32 bit machines
+        if sys.maxint != 2147483647:
+            return
+        A2_16 = "A" * (2**16)
+        self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
+        self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
+        self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
 
     def test_zfill(self):
         self.checkequal('123', '123', 'zfill', 2)
@@ -882,6 +881,40 @@
                 else:
                     self.checkcall(format, "__mod__", value)
 
+    def test_inplace_rewrites(self):
+        # Check that strings don't copy and modify cached single-character strings
+        self.checkequal('a', 'A', 'lower')
+        self.checkequal(True, 'A', 'isupper')
+        self.checkequal('A', 'a', 'upper')
+        self.checkequal(True, 'a', 'islower')
+
+        self.checkequal('a', 'A', 'replace', 'A', 'a')
+        self.checkequal(True, 'A', 'isupper')
+
+        self.checkequal('A', 'a', 'capitalize')
+        self.checkequal(True, 'a', 'islower')
+
+        self.checkequal('A', 'a', 'swapcase')
+        self.checkequal(True, 'a', 'islower')
+
+        self.checkequal('A', 'a', 'title')
+        self.checkequal(True, 'a', 'islower')
+
+    def test_partition(self):
+
+        self.checkequal(('this', ' is ', 'the partition method'),
+            'this is the partition method', 'partition', ' is ')
+
+        # from raymond's original specification
+        S = 'http://www.python.org'
+        self.checkequal(('http', '://', 'www.python.org'), S, 'partition', '://')
+        self.checkequal(('http://www.python.org', '', ''), S, 'partition', '?')
+        self.checkequal(('', 'http://', 'www.python.org'), S, 'partition', 'http://')
+        self.checkequal(('http://www.python.', 'org', ''), S, 'partition', 'org')
+
+        self.checkraises(ValueError, S, 'partition', '')
+        self.checkraises(TypeError, S, 'partition', None)
+
 
 class MixinStrStringUserStringTest:
     # Additional tests for 8bit strings, i.e. str, UserString and

Modified: python/branches/blais-bytebuf/Lib/test/test_grp.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/test/test_grp.py	(original)
+++ python/branches/blais-bytebuf/Lib/test/test_grp.py	Fri May 26 13:03:30 2006
@@ -31,7 +31,10 @@
             self.assertEqual(e2.gr_gid, e.gr_gid)
             e2 = grp.getgrnam(e.gr_name)
             self.check_value(e2)
-            self.assertEqual(e2.gr_name, e.gr_name)
+            # There are instances where getgrall() returns group names in
+            # lowercase while getgrgid() returns proper casing.
+            # Discovered on Ubuntu 5.04 (custom).
+            self.assertEqual(e2.gr_name.lower(), e.gr_name.lower())
 
     def test_errors(self):
         self.assertRaises(TypeError, grp.getgrgid)

Modified: python/branches/blais-bytebuf/Misc/NEWS
==============================================================================
--- python/branches/blais-bytebuf/Misc/NEWS	(original)
+++ python/branches/blais-bytebuf/Misc/NEWS	Fri May 26 13:03:30 2006
@@ -64,6 +64,10 @@
 - Use Win32 API to implement os.{access,chdir,chmod,mkdir,remove,rename,rmdir,utime}.
   As a result, these functions now raise WindowsError instead of OSError.
 
+- ``time.clock()`` on Win64 should use the high-performance Windows
+  ``QueryPerformanceCounter()`` now (as was already the case on 32-bit
+  Windows platforms).
+
 - Calling Tk_Init twice is refused if the first call failed as that
   may deadlock.
 

Modified: python/branches/blais-bytebuf/Misc/developers.txt
==============================================================================
--- python/branches/blais-bytebuf/Misc/developers.txt	(original)
+++ python/branches/blais-bytebuf/Misc/developers.txt	Fri May 26 13:03:30 2006
@@ -18,10 +18,11 @@
 -------------------
 
 - 2006 Summer of Code entries: Matt Fleming was added on 25 May 2006
-  by AMK; he'll be working on enhancing the Python debugger.  SoC
-  developers are expected to work primarily in nondist/sandbox or on a
-  branch of their own, and will have their work reviewed before
-  changes are accepted into the trunk.
+  by AMK; he'll be working on enhancing the Python debugger.  Jackilyn
+  Hoxworth was added on 25 May 2005 by AMK; she'll be adding logging
+  to the standard library.  SoC developers are expected to work
+  primarily in nondist/sandbox or on a branch of their own, and will
+  have their work reviewed before changes are accepted into the trunk.
 
 - Steven Bethard was given SVN access on 27 Apr 2006 by DJG, for PEP
   update access.

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure	Fri May 26 13:03:30 2006
@@ -3483,6 +3483,7 @@
 
 TARGETDIR="unknown"
 case "$host" in
+i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
 i*86-*-linux*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-solaris2.1[0-9]*) TARGET=X86_64; TARGETDIR=x86;;
@@ -5243,6 +5244,9 @@
 esac
 
 
+
+
+
 if test x$TARGET = xSPARC; then
     echo "$as_me:$LINENO: checking assembler and linker support unaligned pc related relocs" >&5
 echo $ECHO_N "checking assembler and linker support unaligned pc related relocs... $ECHO_C" >&6
@@ -5470,7 +5474,15 @@
           ac_config_commands="$ac_config_commands src"
 
 
-          ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h"
+TARGETINCDIR=$TARGETDIR
+case $host in
+*-*-darwin*)
+   TARGETINCDIR="darwin"
+   ;;
+esac
+
+
+          ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h"
 
           ac_config_links="$ac_config_links include/ffi_common.h:include/ffi_common.h"
 
@@ -6017,7 +6029,7 @@
   # Handling of arguments.
   "include/ffi.h" ) CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;;
   "fficonfig.py" ) CONFIG_FILES="$CONFIG_FILES fficonfig.py" ;;
-  "include/ffitarget.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;;
+  "include/ffitarget.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h" ;;
   "include/ffi_common.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffi_common.h:include/ffi_common.h" ;;
   "include" ) CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;;
   "src" ) CONFIG_COMMANDS="$CONFIG_COMMANDS src" ;;

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure.ac
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure.ac	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure.ac	Fri May 26 13:03:30 2006
@@ -21,6 +21,7 @@
 
 TARGETDIR="unknown"
 case "$host" in
+i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
 i*86-*-linux*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-solaris2.1[[0-9]]*) TARGET=X86_64; TARGETDIR=x86;;
@@ -99,6 +100,24 @@
 AC_SUBST(HAVE_LONG_DOUBLE)
 
 AC_C_BIGENDIAN
+AH_VERBATIM([WORDS_BIGENDIAN],
+[
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). 
+
+   The block below does compile-time checking for endianness on platforms
+   that use GCC and therefore allows compiling fat binaries on OSX by using
+   '-arch ppc -arch i386' as the compile flags. The phrasing was choosen
+   such that the configure-result is used on systems that don't use GCC.
+*/
+#ifdef __BIG_ENDIAN__
+#define WORDS_BIGENDIAN 1
+#else
+#ifndef __LITTLE_ENDIAN__
+#undef WORDS_BIGENDIAN
+#endif
+#endif])
+
 
 if test x$TARGET = xSPARC; then
     AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
@@ -201,7 +220,15 @@
 test -d src/$TARGETDIR || mkdir src/$TARGETDIR
 ], [TARGETDIR="$TARGETDIR"])
 
-AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
+TARGETINCDIR=$TARGETDIR
+case $host in
+*-*-darwin*)
+   TARGETINCDIR="darwin"
+   ;;
+esac
+
+
+AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h)
 AC_CONFIG_LINKS(include/ffi_common.h:include/ffi_common.h)
 
 AC_CONFIG_FILES(include/ffi.h fficonfig.py)

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.h.in
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.h.in	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.h.in	Fri May 26 13:03:30 2006
@@ -114,9 +114,22 @@
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
+
 /* Define to 1 if your processor stores words with the most significant byte
-   first (like Motorola and SPARC, unlike Intel and VAX). */
+   first (like Motorola and SPARC, unlike Intel and VAX). 
+
+   The block below does compile-time checking for endianness on platforms
+   that use GCC and therefore allows compiling fat binaries on OSX by using
+   '-arch ppc -arch i386' as the compile flags. The phrasing was choosen
+   such that the configure-result is used on systems that don't use GCC.
+*/
+#ifdef __BIG_ENDIAN__
+#define WORDS_BIGENDIAN 1
+#else
+#ifndef __LITTLE_ENDIAN__
 #undef WORDS_BIGENDIAN
+#endif
+#endif
 
 
 #ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.py.in
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.py.in	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.py.in	Fri May 26 13:03:30 2006
@@ -6,6 +6,7 @@
     'MIPS_IRIX': ['src/mips/ffi.c', 'src/mips/o32.S', 'src/mips/n32.S'],
     'MIPS_LINUX': ['src/mips/ffi.c', 'src/mips/o32.S'],
     'X86': ['src/x86/ffi.c', 'src/x86/sysv.S'],
+    'X86_DARWIN': ['src/x86/ffi_darwin.c', 'src/x86/darwin.S'],
     'X86_WIN32': ['src/x86/ffi.c', 'src/x86/win32.S'],
     'SPARC': ['src/sparc/ffi.c', 'src/sparc/v8.S', 'src/sparc/v9.S'],
     'ALPHA': ['src/alpha/ffi.c', 'src/alpha/osf.S'],
@@ -26,6 +27,17 @@
     'PA': ['src/pa/linux.S', 'src/pa/ffi.c'],
 }
 
+# Build all darwin related files on all supported darwin architectures, this
+# makes it easier to build universal binaries.
+if 0:
+    all_darwin = ('X86_DARWIN', 'POWERPC_DARWIN')
+    all_darwin_files = []
+    for pn in all_darwin:
+        all_darwin_files.extend(ffi_platforms[pn])
+    for pn in all_darwin:
+        ffi_platforms[pn] = all_darwin_files
+    del all_darwin, all_darwin_files, pn
+
 ffi_srcdir = '@srcdir@'
 ffi_sources += ffi_platforms['@MKTARGET@']
 ffi_sources = [os.path.join('@srcdir@', f) for f in ffi_sources]

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin.S
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin.S	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin.S	Fri May 26 13:03:30 2006
@@ -1,3 +1,4 @@
+#ifdef __ppc__
 /* -----------------------------------------------------------------------
    darwin.S - Copyright (c) 2000 John Hornkvist
 	      Copyright (c) 2004 Free Software Foundation, Inc.
@@ -243,3 +244,4 @@
 	.align LOG2_GPR_BYTES
 LLFB0$non_lazy_ptr:
 	.g_long LFB0
+#endif

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S	Fri May 26 13:03:30 2006
@@ -1,3 +1,4 @@
+#ifdef __ppc__
 /* -----------------------------------------------------------------------
    darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
    Inc. based on ppc_closure.S
@@ -315,3 +316,4 @@
 	.align LOG2_GPR_BYTES
 LLFB1$non_lazy_ptr:
 	.g_long LFB1
+#endif

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c	Fri May 26 13:03:30 2006
@@ -1,3 +1,4 @@
+#ifdef __ppc__
 /* -----------------------------------------------------------------------
    ffi.c - Copyright (c) 1998 Geoffrey Keating
 
@@ -767,3 +768,4 @@
   /* Tell ffi_closure_ASM to perform return type promotions.  */
   return cif->rtype->type;
 }
+#endif

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/prep_cif.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/prep_cif.c	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/prep_cif.c	Fri May 26 13:03:30 2006
@@ -55,11 +55,29 @@
       /* Perform a sanity check on the argument type */
       FFI_ASSERT_VALID_TYPE(*ptr);
 
+#ifdef POWERPC_DARWIN
+      {
+	      int curalign;
+
+	      curalign = (*ptr)->alignment;
+	      if (ptr != &(arg->elements[0])) {
+		      if (curalign > 4 && curalign != 16) {
+			      curalign = 4;
+		      }
+	      }
+      arg->size = ALIGN(arg->size, curalign);
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > curalign) ? 
+	      arg->alignment : curalign;
+      }
+#else
       arg->size = ALIGN(arg->size, (*ptr)->alignment);
       arg->size += (*ptr)->size;
 
       arg->alignment = (arg->alignment > (*ptr)->alignment) ? 
 	arg->alignment : (*ptr)->alignment;
+#endif
 
       ptr++;
     }
@@ -89,6 +107,19 @@
 /* Perform machine independent ffi_cif preparation, then call
    machine dependent routine. */
 
+#ifdef X86_DARWIN
+static inline int struct_on_stack(int size)
+{
+	if (size > 8) return 1;
+	/* This is not what the ABI says, but is what is really implemented */
+	switch (size) {
+	case 1: case 2: case 4: case 8: return 0;
+	}
+	return 1;
+}
+#endif
+
+
 ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, 
 			ffi_abi abi, unsigned int nargs, 
 			/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
@@ -124,6 +155,10 @@
 #ifdef SPARC
       && (cif->abi != FFI_V9 || cif->rtype->size > 32)
 #endif
+#ifdef X86_DARWIN
+
+      && (struct_on_stack(cif->rtype->size))
+#endif
       )
     bytes = STACK_ARG_SIZE(sizeof(void*));
 #endif
@@ -139,7 +174,16 @@
 	 check after the initialization.  */
       FFI_ASSERT_VALID_TYPE(*ptr);
 
-#if !defined __x86_64__ && !defined S390 && !defined PA
+#if defined(X86_DARWIN)
+      {
+	      int align = (*ptr)->alignment;
+	      if (align > 4) align = 4;
+	      if ((align - 1) & bytes)
+		 bytes = ALIGN(bytes, align);
+	      bytes += STACK_ARG_SIZE((*ptr)->size);
+      }
+
+#elif !defined __x86_64__ && !defined S390 && !defined PA
 #ifdef SPARC
       if (((*ptr)->type == FFI_TYPE_STRUCT
 	   && ((*ptr)->size > 16 || cif->abi != FFI_V9))

Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffitarget.h
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffitarget.h	(original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffitarget.h	Fri May 26 13:03:30 2006
@@ -51,7 +51,7 @@
 #endif
 
   /* ---- Intel x86 and AMD x86-64 - */
-#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
+#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) 
   FFI_SYSV,
   FFI_UNIX64,   /* Unix variants all use the same ABI for x86-64  */
 #ifdef __i386__

Modified: python/branches/blais-bytebuf/Modules/_struct.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/_struct.c	(original)
+++ python/branches/blais-bytebuf/Modules/_struct.c	Fri May 26 13:03:30 2006
@@ -18,6 +18,14 @@
 /* Forward declarations */
 static Py_ssize_t convertbuffer(PyObject *, void **p);
 
+/* PY_USE_INT_WHEN_POSSIBLE is an experimental flag that changes the 
+   struct API to return int instead of long when possible. This is
+   often a significant performance improvement. */
+/*
+#define PY_USE_INT_WHEN_POSSIBLE 1
+*/
+
+
 /* The translation function for each format character is table driven */
 typedef struct _formatdef {
 	char format;
@@ -284,6 +292,10 @@
 {
 	unsigned int x;
 	memcpy((char *)&x, p, sizeof x);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x <= LONG_MAX)
+		return PyInt_FromLong((long)x);
+#endif
 	return PyLong_FromUnsignedLong((unsigned long)x);
 }
 
@@ -300,6 +312,10 @@
 {
 	unsigned long x;
 	memcpy((char *)&x, p, sizeof x);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x <= LONG_MAX)
+		return PyInt_FromLong((long)x);
+#endif
 	return PyLong_FromUnsignedLong(x);
 }
 
@@ -313,6 +329,10 @@
 {
 	PY_LONG_LONG x;
 	memcpy((char *)&x, p, sizeof x);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x >= LONG_MIN && x <= LONG_MAX)
+		return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
+#endif
 	return PyLong_FromLongLong(x);
 }
 
@@ -321,6 +341,10 @@
 {
 	unsigned PY_LONG_LONG x;
 	memcpy((char *)&x, p, sizeof x);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x <= LONG_MAX)
+		return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
+#endif
 	return PyLong_FromUnsignedLongLong(x);
 }
 
@@ -550,13 +574,13 @@
 	{'I',	sizeof(int),	INT_ALIGN,	nu_uint,	np_uint},
 	{'l',	sizeof(long),	LONG_ALIGN,	nu_long,	np_long},
 	{'L',	sizeof(long),	LONG_ALIGN,	nu_ulong,	np_ulong},
-	{'f',	sizeof(float),	FLOAT_ALIGN,	nu_float,	np_float},
-	{'d',	sizeof(double),	DOUBLE_ALIGN,	nu_double,	np_double},
-	{'P',	sizeof(void *),	VOID_P_ALIGN,	nu_void_p,	np_void_p},
 #ifdef HAVE_LONG_LONG
 	{'q',	sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong},
 	{'Q',	sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong},
 #endif
+	{'f',	sizeof(float),	FLOAT_ALIGN,	nu_float,	np_float},
+	{'d',	sizeof(double),	DOUBLE_ALIGN,	nu_double,	np_double},
+	{'P',	sizeof(void *),	VOID_P_ALIGN,	nu_void_p,	np_void_p},
 	{0}
 };
 
@@ -584,28 +608,61 @@
 	do {
 		x = (x<<8) | (*p++ & 0xFF);
 	} while (--i > 0);
-	if (f->size >= 4)
-		return PyLong_FromUnsignedLong(x);
-	else
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x <= LONG_MAX)
 		return PyInt_FromLong((long)x);
+#else
+	if (SIZEOF_LONG > f->size)
+		return PyInt_FromLong((long)x);
+#endif
+	return PyLong_FromUnsignedLong(x);
 }
 
 static PyObject *
 bu_longlong(const char *p, const formatdef *f)
 {
+#if HAVE_LONG_LONG
+	PY_LONG_LONG x = 0;
+	int i = f->size;
+	do {
+		x = (x<<8) | (*p++ & 0xFF);
+	} while (--i > 0);
+	/* Extend the sign bit. */
+	if (SIZEOF_LONG_LONG > f->size)
+		x |= -(x & (1L << (8 * f->size - 1)));
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x >= LONG_MIN && x <= LONG_MAX)
+		return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
+#endif
+	return PyLong_FromLongLong(x);
+#else
 	return _PyLong_FromByteArray((const unsigned char *)p,
 				      8,
 				      0, /* little-endian */
 				      1  /* signed */);
+#endif
 }
 
 static PyObject *
 bu_ulonglong(const char *p, const formatdef *f)
 {
+#if HAVE_LONG_LONG
+	unsigned PY_LONG_LONG x = 0;
+	int i = f->size;
+	do {
+		x = (x<<8) | (*p++ & 0xFF);
+	} while (--i > 0);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x <= LONG_MAX)
+		return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
+#endif
+	return PyLong_FromUnsignedLongLong(x);
+#else
 	return _PyLong_FromByteArray((const unsigned char *)p,
 				      8,
 				      0, /* little-endian */
 				      0  /* signed */);
+#endif
 }
 
 static PyObject *
@@ -750,28 +807,61 @@
 	do {
 		x = (x<<8) | (p[--i] & 0xFF);
 	} while (i > 0);
-	if (f->size >= 4)
-		return PyLong_FromUnsignedLong(x);
-	else
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x <= LONG_MAX)
 		return PyInt_FromLong((long)x);
+#else
+	if (SIZEOF_LONG > f->size)
+		return PyInt_FromLong((long)x);
+#endif
+	return PyLong_FromUnsignedLong((long)x);
 }
 
 static PyObject *
 lu_longlong(const char *p, const formatdef *f)
 {
+#if HAVE_LONG_LONG
+	PY_LONG_LONG x = 0;
+	int i = f->size;
+	do {
+		x = (x<<8) | (p[--i] & 0xFF);
+	} while (i > 0);
+	/* Extend the sign bit. */
+	if (SIZEOF_LONG_LONG > f->size)
+		x |= -(x & (1L << (8 * f->size - 1)));
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x >= LONG_MIN && x <= LONG_MAX)
+		return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
+#endif
+	return PyLong_FromLongLong(x);
+#else
 	return _PyLong_FromByteArray((const unsigned char *)p,
 				      8,
 				      1, /* little-endian */
 				      1  /* signed */);
+#endif
 }
 
 static PyObject *
 lu_ulonglong(const char *p, const formatdef *f)
 {
+#if HAVE_LONG_LONG
+	unsigned PY_LONG_LONG x = 0;
+	int i = f->size;
+	do {
+		x = (x<<8) | (p[--i] & 0xFF);
+	} while (i > 0);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+	if (x <= LONG_MAX)
+		return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
+#endif
+	return PyLong_FromUnsignedLongLong(x);
+#else
 	return _PyLong_FromByteArray((const unsigned char *)p,
 				      8,
 				      1, /* little-endian */
 				      0  /* signed */);
+#endif
 }
 
 static PyObject *
@@ -1446,7 +1536,7 @@
 
 static
 PyTypeObject PyStructType = {
-	PyObject_HEAD_INIT(&PyType_Type)
+	PyObject_HEAD_INIT(NULL)
 	0,
 	"Struct",
 	sizeof(PyStructObject),
@@ -1497,14 +1587,59 @@
 	if (m == NULL)
 		return;
 
+	PyStructType.ob_type = &PyType_Type;
+	if (PyType_Ready(&PyStructType) < 0)
+		return;
+
+	/* Check endian and swap in faster functions */
+	{
+		int one = 1;
+		formatdef *native = native_table;
+		formatdef *other, *ptr;
+		if ((int)*(unsigned char*)&one)
+			other = lilendian_table;
+		else
+			other = bigendian_table;
+		/* Scan through the native table, find a matching
+		   entry in the endian table and swap in the
+		   native implementations whenever possible
+		   (64-bit platforms may not have "standard" sizes) */
+		while (native->format != '\0' && other->format != '\0') {
+			ptr = other;
+			while (ptr->format != '\0') {
+				if (ptr->format == native->format) {
+					/* Match faster when formats are
+					   listed in the same order */
+					if (ptr == other)
+						other++;
+					/* Only use the trick if the 
+					   size matches */
+					if (ptr->size != native->size)
+						break;
+					/* Skip float and double, could be
+					   "unknown" float format */
+					if (ptr->format == 'd' || ptr->format == 'f')
+						break;
+					ptr->pack = native->pack;
+					ptr->unpack = native->unpack;
+					break;
+				}
+				ptr++;
+			}
+			native++;
+		}
+	}
+	
 	/* Add some symbolic constants to the module */
 	if (StructError == NULL) {
 		StructError = PyErr_NewException("struct.error", NULL, NULL);
 		if (StructError == NULL)
 			return;
 	}
+
 	Py_INCREF(StructError);
 	PyModule_AddObject(m, "error", StructError);
+
 	Py_INCREF((PyObject*)&PyStructType);
 	PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType);
 }

Modified: python/branches/blais-bytebuf/Modules/cPickle.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/cPickle.c	(original)
+++ python/branches/blais-bytebuf/Modules/cPickle.c	Fri May 26 13:03:30 2006
@@ -3073,8 +3073,8 @@
 					"pickles are not supported.");
 			return NULL;
 		}
-		return PyObject_CallFunction(fc, "OO", py_module_name,
-					     py_global_name);
+		return PyObject_CallFunctionObjArgs(fc, py_module_name,
+					            py_global_name, NULL);
 	}
 
 	module = PySys_GetObject("modules");

Modified: python/branches/blais-bytebuf/Modules/gcmodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/gcmodule.c	(original)
+++ python/branches/blais-bytebuf/Modules/gcmodule.c	Fri May 26 13:03:30 2006
@@ -603,7 +603,7 @@
 		assert(callback != NULL);
 
 		/* copy-paste of weakrefobject.c's handle_callback() */
-		temp = PyObject_CallFunction(callback, "O", wr);
+		temp = PyObject_CallFunctionObjArgs(callback, wr, NULL);
 		if (temp == NULL)
 			PyErr_WriteUnraisable(callback);
 		else

Modified: python/branches/blais-bytebuf/Modules/grpmodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/grpmodule.c	(original)
+++ python/branches/blais-bytebuf/Modules/grpmodule.c	Fri May 26 13:03:30 2006
@@ -84,12 +84,18 @@
 }
 
 static PyObject *
-grp_getgrgid(PyObject *self, PyObject *args)
+grp_getgrgid(PyObject *self, PyObject *pyo_id)
 {
+    PyObject *py_int_id;
     unsigned int gid;
     struct group *p;
-    if (!PyArg_ParseTuple(args, "I:getgrgid", &gid))
-        return NULL;
+
+    py_int_id = PyNumber_Int(pyo_id);
+    if (!py_int_id)
+	    return NULL;
+    gid = PyInt_AS_LONG(py_int_id);
+    Py_DECREF(py_int_id);
+
     if ((p = getgrgid(gid)) == NULL) {
 	PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %d", gid);
         return NULL;
@@ -98,27 +104,33 @@
 }
 
 static PyObject *
-grp_getgrnam(PyObject *self, PyObject *args)
+grp_getgrnam(PyObject *self, PyObject *pyo_name)
 {
+    PyObject *py_str_name;
     char *name;
     struct group *p;
-    if (!PyArg_ParseTuple(args, "s:getgrnam", &name))
-        return NULL;
+
+    py_str_name = PyObject_Str(pyo_name);
+    if (!py_str_name)
+	    return NULL;
+    name = PyString_AS_STRING(py_str_name);
+    
     if ((p = getgrnam(name)) == NULL) {
 	PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %s", name);
+	Py_DECREF(py_str_name);
         return NULL;
     }
+
+    Py_DECREF(py_str_name);
     return mkgrent(p);
 }
 
 static PyObject *
-grp_getgrall(PyObject *self, PyObject *args)
+grp_getgrall(PyObject *self, PyObject *ignore)
 {
     PyObject *d;
     struct group *p;
 
-    if (!PyArg_ParseTuple(args, ":getgrall"))
-        return NULL;
     if ((d = PyList_New(0)) == NULL)
         return NULL;
     setgrent();
@@ -136,15 +148,15 @@
 }
 
 static PyMethodDef grp_methods[] = {
-    {"getgrgid",	grp_getgrgid,	METH_VARARGS,
+    {"getgrgid",	grp_getgrgid,	METH_O,
      "getgrgid(id) -> tuple\n\
 Return the group database entry for the given numeric group ID.  If\n\
 id is not valid, raise KeyError."},
-    {"getgrnam",	grp_getgrnam,	METH_VARARGS,
+    {"getgrnam",	grp_getgrnam,	METH_O,
      "getgrnam(name) -> tuple\n\
 Return the group database entry for the given group name.  If\n\
 name is not valid, raise KeyError."},
-    {"getgrall",	grp_getgrall,	METH_VARARGS,
+    {"getgrall",	grp_getgrall,	METH_NOARGS,
      "getgrall() -> list of tuples\n\
 Return a list of all available group entries, in arbitrary order."},
     {NULL,		NULL}		/* sentinel */

Modified: python/branches/blais-bytebuf/Modules/parsermodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/parsermodule.c	(original)
+++ python/branches/blais-bytebuf/Modules/parsermodule.c	Fri May 26 13:03:30 2006
@@ -3267,8 +3267,8 @@
             && (pickler != NULL)) {
             PyObject *res;
 
-            res = PyObject_CallFunction(func, "OOO", &PyST_Type, pickler,
-                                        pickle_constructor);
+            res = PyObject_CallFunctionObjArgs(func, &PyST_Type, pickler,
+                                               pickle_constructor, NULL);
             Py_XDECREF(res);
         }
         Py_XDECREF(func);

Modified: python/branches/blais-bytebuf/Modules/timemodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/timemodule.c	(original)
+++ python/branches/blais-bytebuf/Modules/timemodule.c	Fri May 26 13:03:30 2006
@@ -63,11 +63,10 @@
 #endif /* MS_WINDOWS */
 #endif /* !__WATCOMC__ || __QNX__ */
 
-#if defined(MS_WINDOWS) && !defined(MS_WIN64) && !defined(__BORLANDC__)
-/* Win32 has better clock replacement
-   XXX Win64 does not yet, but might when the platform matures. */
-#undef HAVE_CLOCK /* We have our own version down below */
-#endif /* MS_WINDOWS && !MS_WIN64 */
+#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
+/* Win32 has better clock replacement; we have our own version below. */
+#undef HAVE_CLOCK
+#endif /* MS_WINDOWS && !defined(__BORLANDC__) */
 
 #if defined(PYOS_OS2)
 #define INCL_DOS
@@ -162,7 +161,7 @@
 }
 #endif /* HAVE_CLOCK */
 
-#if defined(MS_WINDOWS) && !defined(MS_WIN64) && !defined(__BORLANDC__)
+#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
 /* Due to Mark Hammond and Tim Peters */
 static PyObject *
 time_clock(PyObject *self, PyObject *args)
@@ -191,7 +190,7 @@
 }
 
 #define HAVE_CLOCK /* So it gets included in the methods */
-#endif /* MS_WINDOWS && !MS_WIN64 */
+#endif /* MS_WINDOWS && !defined(__BORLANDC__) */
 
 #ifdef HAVE_CLOCK
 PyDoc_STRVAR(clock_doc,
@@ -821,7 +820,7 @@
 	SetConsoleCtrlHandler( PyCtrlHandler, TRUE);
 #endif /* MS_WINDOWS */
 	if (!initialized) {
-		PyStructSequence_InitType(&StructTimeType, 
+		PyStructSequence_InitType(&StructTimeType,
 					  &struct_time_type_desc);
 	}
 	Py_INCREF(&StructTimeType);

Modified: python/branches/blais-bytebuf/Objects/classobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/classobject.c	(original)
+++ python/branches/blais-bytebuf/Objects/classobject.c	Fri May 26 13:03:30 2006
@@ -81,12 +81,9 @@
 			if (!PyClass_Check(base)) {
 				if (PyCallable_Check(
 					(PyObject *) base->ob_type))
-					return PyObject_CallFunction(
+					return PyObject_CallFunctionObjArgs(
 						(PyObject *) base->ob_type,
-						"OOO",
-						name,
-						bases,
-						dict);
+						name, bases, dict, NULL);
 				PyErr_SetString(PyExc_TypeError,
 					"PyClass_New: base must be a class");
 				return NULL;

Modified: python/branches/blais-bytebuf/Objects/floatobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/floatobject.c	(original)
+++ python/branches/blais-bytebuf/Objects/floatobject.c	Fri May 26 13:03:30 2006
@@ -384,7 +384,7 @@
 	if (PyFloat_Check(w))
 		j = PyFloat_AS_DOUBLE(w);
 
-	else if (Py_IS_INFINITY(i) || Py_IS_NAN(i)) {
+	else if (!Py_IS_FINITE(i)) {
 		if (PyInt_Check(w) || PyLong_Check(w))
 			/* If i is an infinity, its magnitude exceeds any
 			 * finite integer, so it doesn't matter which int we
@@ -802,10 +802,7 @@
 		 * bug; we let that slide in math.pow() (which currently
 		 * reflects all platform accidents), but not for Python's **.
 		 */
-		 if (iv == -1.0 && !Py_IS_INFINITY(iw) && iw == iw) {
-		 	/* XXX the "iw == iw" was to weed out NaNs.  This
-		 	 * XXX doesn't actually work on all platforms.
-		 	 */
+		 if (iv == -1.0 && Py_IS_FINITE(iw)) {
 		 	/* Return 1 if iw is even, -1 if iw is odd; there's
 		 	 * no guarantee that any C integral type is big
 		 	 * enough to hold iw, so we have to check this

Modified: python/branches/blais-bytebuf/Objects/longobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/longobject.c	(original)
+++ python/branches/blais-bytebuf/Objects/longobject.c	Fri May 26 13:03:30 2006
@@ -40,7 +40,7 @@
 #define SIGCHECK(PyTryBlock) \
 	if (--_Py_Ticker < 0) { \
 		_Py_Ticker = _Py_CheckInterval; \
-		if (PyErr_CheckSignals()) { PyTryBlock; } \
+		if (PyErr_CheckSignals()) PyTryBlock \
 	}
 
 /* Normalize (remove leading zeros from) a long int object.
@@ -844,11 +844,36 @@
 PyObject *
 PyLong_FromLongLong(PY_LONG_LONG ival)
 {
-	PY_LONG_LONG bytes = ival;
-	int one = 1;
-	return _PyLong_FromByteArray(
-			(unsigned char *)&bytes,
-			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
+	PyLongObject *v;
+	unsigned PY_LONG_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 PY_LONG_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 PY_LONG_LONG)ival;
+		while (t) {
+			*p++ = (digit)(t & MASK);
+			t >>= SHIFT;
+		}
+	}
+	return (PyObject *)v;
 }
 
 /* Create a new long int object from a C unsigned PY_LONG_LONG int. */
@@ -856,11 +881,26 @@
 PyObject *
 PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG ival)
 {
-	unsigned PY_LONG_LONG bytes = ival;
-	int one = 1;
-	return _PyLong_FromByteArray(
-			(unsigned char *)&bytes,
-			SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
+	PyLongObject *v;
+	unsigned PY_LONG_LONG t;
+	int ndigits = 0;
+
+	/* Count the number of Python digits. */
+	t = (unsigned PY_LONG_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;
 }
 
 /* Create a new long int object from a C Py_ssize_t. */
@@ -1304,7 +1344,14 @@
 	return (PyObject *)str;
 }
 
-static int digval[] = {
+/* Table of digit values for 8-bit string -> integer conversion.
+ * '0' maps to 0, ..., '9' maps to 9.
+ * 'a' and 'A' map to 10, ..., 'z' and 'Z' map to 35.
+ * All other indices map to 37.
+ * Note that when converting a base B string, a char c is a legitimate
+ * base B digit iff _PyLong_DigitValue[Py_CHARMASK(c)] < B.
+ */
+int _PyLong_DigitValue[256] = {
 	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
 	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
 	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
@@ -1321,14 +1368,6 @@
 	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
 	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
 	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37
 };
 
 /* *str points to the first digit in a string of base `base` digits.  base
@@ -1355,7 +1394,7 @@
 		n >>= 1;
 	/* n <- total # of bits needed, while setting p to end-of-string */
 	n = 0;
-	while (digval[Py_CHARMASK(*p)] < base)
+	while (_PyLong_DigitValue[Py_CHARMASK(*p)] < base)
 		++p;
 	*str = p;
 	n = (p - start) * bits_per_char;
@@ -1376,7 +1415,7 @@
 	bits_in_accum = 0;
 	pdigit = z->ob_digit;
 	while (--p >= start) {
-		int k = digval[Py_CHARMASK(*p)];
+		int k = _PyLong_DigitValue[Py_CHARMASK(*p)];
 		assert(k >= 0 && k < base);
 		accum |= (twodigits)(k << bits_in_accum);
 		bits_in_accum += bits_per_char;
@@ -1503,7 +1542,7 @@
 
 		/* Find length of the string of numeric characters. */
 		scan = str;
-		while (digval[Py_CHARMASK(*scan)] < base)
+		while (_PyLong_DigitValue[Py_CHARMASK(*scan)] < base)
 			++scan;
 
 		/* Create a long object that can contain the largest possible
@@ -1527,10 +1566,10 @@
 		/* Work ;-) */
 		while (str < scan) {
 			/* grab up to convwidth digits from the input string */
-			c = (digit)digval[Py_CHARMASK(*str++)];
+			c = (digit)_PyLong_DigitValue[Py_CHARMASK(*str++)];
 			for (i = 1; i < convwidth && str != scan; ++i, ++str) {
 				c = (twodigits)(c *  base +
-					digval[Py_CHARMASK(*str)]);
+					_PyLong_DigitValue[Py_CHARMASK(*str)]);
 				assert(c < BASE);
 			}
 

Modified: python/branches/blais-bytebuf/Objects/stringobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/stringobject.c	(original)
+++ python/branches/blais-bytebuf/Objects/stringobject.c	Fri May 26 13:03:30 2006
@@ -5,6 +5,18 @@
 
 #include <ctype.h>
 
+#undef USE_INLINE /* XXX - set via configure? */
+
+#if defined(_MSC_VER) /* this is taken from _sre.c */
+#pragma warning(disable: 4710)
+/* fastest possible local call under MSVC */
+#define LOCAL(type) static __inline type __fastcall
+#elif defined(USE_INLINE)
+#define LOCAL(type) static inline type
+#else
+#define LOCAL(type) static type
+#endif
+
 #ifdef COUNT_ALLOCS
 int null_strings, one_strings;
 #endif
@@ -763,6 +775,105 @@
 	return 0;
 }
 
+/* -------------------------------------------------------------------- */
+/* Helpers */
+
+#define USE_FAST /* experimental fast search implementation */
+
+/* XXX - this code is copied from unicodeobject.c.  we really should
+   refactor the core implementations (see _sre.c for how this can be
+   done), but that'll have to wait -- fredrik */
+
+/* fast search/count implementation, based on a mix between boyer-
+   moore and horspool, with a few more bells and whistles on the top.
+   for some more background, see: http://effbot.org/stringlib */
+
+/* note: fastsearch may access s[n], which isn't a problem when using
+   Python's ordinary string types, but may cause problems if you're
+   using this code in other contexts.  also, the count mode returns -1
+   if there cannot possibly be a match in the target string, and 0 if
+   it has actually checked for matches, but didn't find any.  callers
+   beware! */
+
+#define FAST_COUNT 0
+#define FAST_SEARCH 1
+
+LOCAL(Py_ssize_t)
+fastsearch(const char* s, Py_ssize_t n, const char* p, Py_ssize_t m, int mode)
+{
+	long mask;
+	Py_ssize_t skip, count = 0;
+	Py_ssize_t i, j, mlast, w;
+
+	w = n - m;
+
+	if (w < 0)
+		return -1;
+
+	/* look for special cases */
+	if (m <= 1) {
+		if (m <= 0)
+			return -1;
+		/* use special case for 1-character strings */
+		if (mode == FAST_COUNT) {
+			for (i = 0; i < n; i++)
+				if (s[i] == p[0])
+					count++;
+			return count;
+		} else {
+			for (i = 0; i < n; i++)
+				if (s[i] == p[0])
+					return i;
+		}
+		return -1;
+	}
+
+	mlast = m - 1;
+
+	/* create compressed boyer-moore delta 1 table */
+	skip = mlast - 1;
+	/* process pattern[:-1] */
+	for (mask = i = 0; i < mlast; i++) {
+		mask |= (1 << (p[i] & 0x1F));
+		if (p[i] == p[mlast])
+			skip = mlast - i - 1;
+	}
+	/* process pattern[-1] outside the loop */
+	mask |= (1 << (p[mlast] & 0x1F));
+
+	for (i = 0; i <= w; i++) {
+		/* note: using mlast in the skip path slows things down on x86 */
+		if (s[i+m-1] == p[m-1]) {
+			/* candidate match */
+			for (j = 0; j < mlast; j++)
+				if (s[i+j] != p[j])
+					break;
+			if (j == mlast) {
+				/* got a match! */
+				if (mode != FAST_COUNT)
+					return i;
+				count++;
+				i = i + mlast;
+				continue;
+			}
+			/* miss: check if next character is part of pattern */
+			if (!(mask & (1 << (s[i+m] & 0x1F))))
+				i = i + m;
+			else
+				i = i + skip;
+		} else {
+			/* skip: check if next character is part of pattern */
+			if (!(mask & (1 << (s[i+m] & 0x1F))))
+				i = i + m;
+		}
+	}
+
+	if (mode != FAST_COUNT)
+		return -1;
+	return count;
+}
+
+/* -------------------------------------------------------------------- */
 /* Methods */
 
 static int
@@ -909,7 +1020,7 @@
 static PyObject *
 string_concat(register PyStringObject *a, register PyObject *bb)
 {
-	register size_t size;
+	register Py_ssize_t size;
 	register PyStringObject *op;
 	if (!PyString_Check(bb)) {
 #ifdef Py_USING_UNICODE
@@ -933,7 +1044,12 @@
 		return (PyObject *)a;
 	}
 	size = a->ob_size + b->ob_size;
-	/* XXX check overflow */
+	if (size < 0) {
+		PyErr_SetString(PyExc_OverflowError,
+				"strings are too large to concat");
+		return NULL;
+	}
+	  
 	/* Inline PyObject_NewVar */
 	op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
 	if (op == NULL)
@@ -1030,10 +1146,14 @@
 {
 	char *s = PyString_AS_STRING(a);
 	const char *sub = PyString_AS_STRING(el);
-	char *last;
 	Py_ssize_t len_sub = PyString_GET_SIZE(el);
+#ifdef USE_FAST
+	Py_ssize_t pos;
+#else
+	char *last;
 	Py_ssize_t shortsub;
 	char firstchar, lastchar;
+#endif
 
 	if (!PyString_CheckExact(el)) {
 #ifdef Py_USING_UNICODE
@@ -1049,6 +1169,14 @@
 
 	if (len_sub == 0)
 		return 1;
+
+#ifdef USE_FAST
+	pos = fastsearch(
+		s, PyString_GET_SIZE(a),
+		sub, len_sub, FAST_SEARCH
+		);
+	return (pos != -1);
+#else    
 	/* last points to one char beyond the start of the rightmost
 	   substring.  When s<last, there is still room for a possible match
 	   and s[0] through s[len_sub-1] will be in bounds.
@@ -1069,6 +1197,7 @@
 			return 1;
 		s++;
 	}
+#endif
 	return 0;
 }
 
@@ -1329,18 +1458,6 @@
 	else							\
 		Py_DECREF(str);
 
-#define SPLIT_INSERT(data, left, right)			 	\
-	str = PyString_FromStringAndSize((data) + (left),	\
-					 (right) - (left));	\
-	if (str == NULL)					\
-		goto onError;					\
-	if (PyList_Insert(list, 0, str)) {			\
-		Py_DECREF(str);					\
-		goto onError;					\
-	}							\
-	else							\
-		Py_DECREF(str);
-
 static PyObject *
 split_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit)
 {
@@ -1481,6 +1598,65 @@
 	return NULL;
 }
 
+PyDoc_STRVAR(partition__doc__,
+"S.partition(sep) -> (head, sep, tail)\n\
+\n\
+Searches for the separator sep in S, and returns the part before it,\n\
+the separator itself, and the part after it.  If the separator is not\n\
+found, returns S and two empty strings.");
+
+static PyObject *
+string_partition(PyStringObject *self, PyObject *sep_obj)
+{
+	Py_ssize_t len = PyString_GET_SIZE(self), sep_len, pos;
+	const char *str = PyString_AS_STRING(self), *sep;
+	PyObject * out;
+
+	if (PyString_Check(sep_obj)) {
+		sep = PyString_AS_STRING(sep_obj);
+		sep_len = PyString_GET_SIZE(sep_obj);
+	}
+#ifdef Py_USING_UNICODE
+	else if (PyUnicode_Check(sep_obj))
+		return PyUnicode_Partition((PyObject *)self, sep_obj);
+#endif
+	else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
+		return NULL;
+
+	if (sep_len == 0) {
+		PyErr_SetString(PyExc_ValueError, "empty separator");
+		return NULL;
+	}
+
+	out = PyTuple_New(3);
+	if (!out)
+		return NULL;
+
+	pos = fastsearch(str, len, sep, sep_len, FAST_SEARCH);
+	if (pos < 0) {
+		Py_INCREF(self);
+		PyTuple_SET_ITEM(out, 0, (PyObject*) self);
+		Py_INCREF(nullstring);
+		PyTuple_SET_ITEM(out, 1, (PyObject*) nullstring);
+		Py_INCREF(nullstring);
+		PyTuple_SET_ITEM(out, 2, (PyObject*) nullstring);
+	} else {
+		PyObject* obj;
+		PyTuple_SET_ITEM(out, 0, PyString_FromStringAndSize(str, pos));
+		Py_INCREF(sep_obj);
+		PyTuple_SET_ITEM(out, 1, sep_obj);
+		pos += sep_len;
+		obj = PyString_FromStringAndSize(str + pos, len - pos);
+		PyTuple_SET_ITEM(out, 2, obj);
+		if (PyErr_Occurred()) {
+			Py_DECREF(out);
+			return NULL;
+		}
+	}
+
+	return out;
+}
+
 static PyObject *
 rsplit_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit)
 {
@@ -1500,15 +1676,17 @@
 		if (j > i) {
 			if (maxsplit-- <= 0)
 				break;
-			SPLIT_INSERT(s, i + 1, j + 1);
+			SPLIT_APPEND(s, i + 1, j + 1);
 			while (i >= 0 && isspace(Py_CHARMASK(s[i])))
 				i--;
 			j = i;
 		}
 	}
 	if (j >= 0) {
-		SPLIT_INSERT(s, 0, j + 1);
+		SPLIT_APPEND(s, 0, j + 1);
 	}
+	if (PyList_Reverse(list) < 0)
+		goto onError;
 	return list;
   onError:
 	Py_DECREF(list);
@@ -1529,14 +1707,16 @@
 		if (s[i] == ch) {
 			if (maxcount-- <= 0)
 				break;
-			SPLIT_INSERT(s, i + 1, j + 1);
+			SPLIT_APPEND(s, i + 1, j + 1);
 			j = i = i - 1;
 		} else
 			i--;
 	}
 	if (j >= -1) {
-		SPLIT_INSERT(s, 0, j + 1);
+		SPLIT_APPEND(s, 0, j + 1);
 	}
+	if (PyList_Reverse(list) < 0)
+		goto onError;
 	return list;
 
  onError:
@@ -1776,6 +1956,17 @@
 
 	string_adjust_indices(&i, &last, len);
 
+#ifdef USE_FAST
+	if (n == 0)
+		return (dir > 0) ? i : last;
+	if (dir > 0) {
+		Py_ssize_t pos = fastsearch(s + i, last - i, sub, n,
+					    FAST_SEARCH);
+		if (pos < 0)
+			return pos;
+		return pos + i;
+	}
+#endif
 	if (dir > 0) {
 		if (n == 0 && i <= last)
 			return (long)i;
@@ -2033,57 +2224,68 @@
 \n\
 Return a copy of the string S converted to lowercase.");
 
+/* _tolower and _toupper are defined by SUSv2, but they're not ISO C */
+#ifndef _tolower
+#define _tolower tolower
+#endif
+
 static PyObject *
 string_lower(PyStringObject *self)
 {
-	char *s = PyString_AS_STRING(self), *s_new;
+	char *s;
 	Py_ssize_t i, n = PyString_GET_SIZE(self);
 	PyObject *newobj;
 
 	newobj = PyString_FromStringAndSize(NULL, n);
-	if (newobj == NULL)
+	if (!newobj)
 		return NULL;
-	s_new = PyString_AsString(newobj);
+
+	s = PyString_AS_STRING(newobj);
+
+	memcpy(s, PyString_AS_STRING(self), n);
+
 	for (i = 0; i < n; i++) {
-		int c = Py_CHARMASK(*s++);
-		if (isupper(c)) {
-			*s_new = tolower(c);
-		} else
-			*s_new = c;
-		s_new++;
+		int c = Py_CHARMASK(s[i]);
+		if (isupper(c))
+			s[i] = _tolower(c);
 	}
+
 	return newobj;
 }
 
-
 PyDoc_STRVAR(upper__doc__,
 "S.upper() -> string\n\
 \n\
 Return a copy of the string S converted to uppercase.");
 
+#ifndef _toupper
+#define _toupper toupper
+#endif
+
 static PyObject *
 string_upper(PyStringObject *self)
 {
-	char *s = PyString_AS_STRING(self), *s_new;
+	char *s;
 	Py_ssize_t i, n = PyString_GET_SIZE(self);
 	PyObject *newobj;
 
 	newobj = PyString_FromStringAndSize(NULL, n);
-	if (newobj == NULL)
+	if (!newobj)
 		return NULL;
-	s_new = PyString_AsString(newobj);
+
+	s = PyString_AS_STRING(newobj);
+
+	memcpy(s, PyString_AS_STRING(self), n);
+
 	for (i = 0; i < n; i++) {
-		int c = Py_CHARMASK(*s++);
-		if (islower(c)) {
-			*s_new = toupper(c);
-		} else
-			*s_new = c;
-		s_new++;
+		int c = Py_CHARMASK(s[i]);
+		if (islower(c))
+			s[i] = _toupper(c);
 	}
+
 	return newobj;
 }
 
-
 PyDoc_STRVAR(title__doc__,
 "S.title() -> string\n\
 \n\
@@ -2166,7 +2368,7 @@
 static PyObject *
 string_count(PyStringObject *self, PyObject *args)
 {
-	const char *s = PyString_AS_STRING(self), *sub, *t;
+	const char *s = PyString_AS_STRING(self), *sub;
 	Py_ssize_t len = PyString_GET_SIZE(self), n;
 	Py_ssize_t i = 0, last = PY_SSIZE_T_MAX;
 	Py_ssize_t m, r;
@@ -2199,8 +2401,14 @@
 	if (n == 0)
 		return PyInt_FromSsize_t(m-i);
 
+#ifdef USE_FAST
+	r = fastsearch(s + i, last - i, sub, n, FAST_COUNT);
+	if (r < 0)
+		r = 0; /* no match */
+#else
 	r = 0;
 	while (i < m) {
+		const char *t
 		if (!memcmp(s+i, sub, n)) {
 			r++;
 			i += n;
@@ -2214,6 +2422,7 @@
 			break;
 		i = t - s;
 	}
+#endif
 	return PyInt_FromSsize_t(r);
 }
 
@@ -2368,156 +2577,625 @@
 }
 
 
-/* What follows is used for implementing replace().  Perry Stoll. */
+#define FORWARD 1
+#define REVERSE -1
 
-/*
-  mymemfind
+/* find and count characters and substrings */
 
-  strstr replacement for arbitrary blocks of memory.
+/* Don't call if length < 2 */
+#define Py_STRING_MATCH(target, offset, pattern, length)	\
+  (target[offset] == pattern[0] &&				\
+   target[offset+length-1] == pattern[length-1] &&		\
+   !memcmp(target+offset+1, pattern+1, length-2) )
+
+#define findchar(target, target_len, c)				\
+  ((char *)memchr((const void *)(target), c, target_len))
+
+/* String ops must return a string.  */
+/* If the object is subclass of string, create a copy */
+static PyStringObject *
+return_self(PyStringObject *self)
+{
+	if (PyString_CheckExact(self)) {
+		Py_INCREF(self);
+		return self;
+	}
+	return (PyStringObject *)PyString_FromStringAndSize(
+		PyString_AS_STRING(self),
+		PyString_GET_SIZE(self));
+}
 
-  Locates the first occurrence in the memory pointed to by MEM of the
-  contents of memory pointed to by PAT.  Returns the index into MEM if
-  found, or -1 if not found.  If len of PAT is greater than length of
-  MEM, the function returns -1.
-*/
 static Py_ssize_t
-mymemfind(const char *mem, Py_ssize_t len, const char *pat, Py_ssize_t pat_len)
+countchar(char *target, int target_len, char c)
 {
-	register Py_ssize_t ii;
+	Py_ssize_t count=0;
+	char *start=target;
+	char *end=target+target_len;
 
-	/* pattern can not occur in the last pat_len-1 chars */
-	len -= pat_len;
+	while ( (start=findchar(start, end-start, c)) != NULL ) {
+		count++;
+		start += 1;
+	}
 
-	for (ii = 0; ii <= len; ii++) {
-		if (mem[ii] == pat[0] && memcmp(&mem[ii], pat, pat_len) == 0) {
-			return ii;
-		}
+	return count;
+}
+
+static Py_ssize_t
+findstring(char *target, Py_ssize_t target_len,
+	   char *pattern, Py_ssize_t pattern_len,
+	   Py_ssize_t start,
+	   Py_ssize_t end,
+	   int direction)
+{
+	if (start < 0) {
+		start += target_len;
+		if (start < 0)
+			start = 0;
+	}
+	if (end > target_len) {
+		end = target_len;
+	} else if (end < 0) {
+		end += target_len;
+		if (end < 0)
+			end = 0;
+	}
+
+	/* zero-length substrings always match at the first attempt */
+	if (pattern_len == 0)
+		return (direction > 0) ? start : end;
+
+	end -= pattern_len;
+
+	if (direction < 0) {
+		for (; end >= start; end--)
+			if (Py_STRING_MATCH(target, end, pattern, pattern_len))
+				return end;
+	} else {
+		for (; start <= end; start++)
+			if (Py_STRING_MATCH(target, start, pattern, pattern_len))
+				return start;
 	}
 	return -1;
 }
 
-/*
-  mymemcnt
+Py_ssize_t
+countstring(char *target, Py_ssize_t target_len,
+	    char *pattern, Py_ssize_t pattern_len,
+	    Py_ssize_t start,
+	    Py_ssize_t end,
+	    int direction)
+{
+	Py_ssize_t count=0;
+
+	if (start < 0) {
+		start += target_len;
+		if (start < 0)
+			start = 0;
+	}
+	if (end > target_len) {
+		end = target_len;
+	} else if (end < 0) {
+		end += target_len;
+		if (end < 0)
+			end = 0;
+	}
+
+	/* zero-length substrings match everywhere */
+	if (pattern_len == 0)
+		return target_len+1;
+
+	end -= pattern_len;
+
+	if (direction < 0) {
+		for (; end >= start; end--)
+			if (Py_STRING_MATCH(target, end, pattern, pattern_len)) {
+				count++;
+				end -= pattern_len-1;
+			}
+	} else {
+		for (; start <= end; start++)
+			if (Py_STRING_MATCH(target, start, pattern, pattern_len)) {
+				count++;
+				start += pattern_len-1;
+			}
+	}
+	return count;
+}
 
-   Return the number of distinct times PAT is found in MEM.
-   meaning mem=1111 and pat==11 returns 2.
-           mem=11111 and pat==11 also return 2.
- */
-static Py_ssize_t
-mymemcnt(const char *mem, Py_ssize_t len, const char *pat, Py_ssize_t pat_len)
-{
-	register Py_ssize_t offset = 0;
-	Py_ssize_t nfound = 0;
 
-	while (len >= 0) {
-		offset = mymemfind(mem, len, pat, pat_len);
+/* Algorithms for difference cases of string replacement */
+
+/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */
+static PyStringObject *
+replace_interleave(PyStringObject *self,
+		   PyStringObject *to,
+		   Py_ssize_t maxcount)
+{
+	char *self_s, *to_s, *result_s;
+	Py_ssize_t self_len, to_len, result_len;
+	Py_ssize_t count, i, product;
+	PyStringObject *result;
+
+	self_len = PyString_GET_SIZE(self);
+	to_len = PyString_GET_SIZE(to);
+	
+	/* 1 at the end plus 1 after every character */
+	count = self_len+1;
+	if (maxcount < count) 
+		count = maxcount;
+	
+	/* Check for overflow */
+	/*   result_len = count * to_len + self_len; */
+	product = count * to_len;
+	if (product / to_len != count) {
+		PyErr_SetString(PyExc_OverflowError,
+				"replace string is too long");
+		return NULL;
+	}
+	result_len = product + self_len;
+	if (result_len < 0) {
+		PyErr_SetString(PyExc_OverflowError,
+				"replace string is too long");
+		return NULL;
+	}
+  
+	if (! (result = (PyStringObject *)
+	                 PyString_FromStringAndSize(NULL, result_len)) )
+		return NULL;
+
+	self_s = PyString_AS_STRING(self);
+	to_s = PyString_AS_STRING(to);
+	to_len = PyString_GET_SIZE(to);
+	result_s = PyString_AS_STRING(result);
+
+	/* TODO: special case single character, which doesn't need memcpy */
+
+	/* Lay the first one down (guaranteed this will occur) */
+	memcpy(result_s, to_s, to_len);
+	result_s += to_len;
+	count -= 1;
+  
+	for (i=0; i<count; i++) {
+		*result_s++ = *self_s++;
+		memcpy(result_s, to_s, to_len);
+		result_s += to_len;
+	}
+
+	/* Copy the rest of the original string */
+	memcpy(result_s, self_s, self_len-i);
+
+	return result;
+}
+
+/* Special case for deleting a single character */
+/* len(self)>=1, len(from)==1, to="", maxcount>=1 */
+static PyStringObject *
+replace_delete_single_character(PyStringObject *self,
+				char from_c, Py_ssize_t maxcount)
+{
+	char *self_s, *result_s;
+	char *start, *next, *end;
+	Py_ssize_t self_len, result_len;
+	Py_ssize_t count;
+	PyStringObject *result;
+
+	self_len = PyString_GET_SIZE(self);
+	self_s = PyString_AS_STRING(self);
+
+	count = countchar(self_s, self_len, from_c);
+	if (count == 0) {
+		return return_self(self);
+	}
+	if (count > maxcount)
+		count = maxcount;
+  
+	result_len = self_len - count;  /* from_len == 1 */
+	assert(result_len>=0);
+
+	if ( (result = (PyStringObject *)
+	                PyString_FromStringAndSize(NULL, result_len)) == NULL)
+		return NULL;
+	result_s = PyString_AS_STRING(result);
+
+	start = self_s;
+	end = self_s + self_len;
+	while (count-- > 0) {
+		next = findchar(start, end-start, from_c);
+		if (next == NULL)
+			break;
+		memcpy(result_s, start, next-start);
+		result_s += (next-start);
+		start = next+1;
+	}
+	memcpy(result_s, start, end-start);
+	
+	return result;
+}
+
+/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */
+
+static PyStringObject *
+replace_delete_substring(PyStringObject *self, PyStringObject *from,
+			 Py_ssize_t maxcount) {
+	char *self_s, *from_s, *result_s;
+	char *start, *next, *end;
+	Py_ssize_t self_len, from_len, result_len;
+	Py_ssize_t count, offset;
+	PyStringObject *result;
+
+	self_len = PyString_GET_SIZE(self);
+	self_s = PyString_AS_STRING(self);
+	from_len = PyString_GET_SIZE(from);
+	from_s = PyString_AS_STRING(from);
+
+	count = countstring(self_s, self_len,
+			    from_s, from_len,
+			    0, self_len, 1);
+  
+	if (count > maxcount)
+		count = maxcount;
+
+	if (count == 0) {
+		/* no matches */
+		return return_self(self);
+	}
+
+	result_len = self_len - (count * from_len);
+	assert (result_len>=0);
+	
+	if ( (result = (PyStringObject *)
+	      PyString_FromStringAndSize(NULL, result_len)) == NULL )
+		return NULL;
+	
+	result_s = PyString_AS_STRING(result);
+	
+	start = self_s;
+	end = self_s + self_len;
+	while (count-- > 0) {
+		offset = findstring(start, end-start,
+				    from_s, from_len,
+				    0, end-start, FORWARD);
 		if (offset == -1)
 			break;
-		mem += offset + pat_len;
-		len -= offset + pat_len;
-		nfound++;
+		next = start + offset;
+		
+		memcpy(result_s, start, next-start);
+		
+		result_s += (next-start);
+		start = next+from_len;
 	}
-	return nfound;
+	memcpy(result_s, start, end-start);
+	return result;
 }
 
-/*
-   mymemreplace
+/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */
+static PyStringObject *
+replace_single_character_in_place(PyStringObject *self,
+				  char from_c, char to_c,
+				  Py_ssize_t maxcount)
+{
+	char *self_s, *result_s, *start, *end, *next;
+	Py_ssize_t self_len;
+	PyStringObject *result;
+	
+	/* The result string will be the same size */
+	self_s = PyString_AS_STRING(self);
+	self_len = PyString_GET_SIZE(self);
+	
+	next = findchar(self_s, self_len, from_c);
+	
+	if (next == NULL) {
+		/* No matches; return the original string */
+		return return_self(self);
+	}
+	
+	/* Need to make a new string */
+	result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len);
+	if (result == NULL)
+		return NULL;
+	result_s = PyString_AS_STRING(result);
+	memcpy(result_s, self_s, self_len);
+	
+	/* change everything in-place, starting with this one */
+	start =  result_s + (next-self_s);
+	*start = to_c;
+	start++;
+	end = result_s + self_len;
+	
+	while (--maxcount > 0) {
+		next = findchar(start, end-start, from_c);
+		if (next == NULL)
+			break;
+		*next = to_c;
+		start = next+1;
+	}
+	
+	return result;
+}
 
-   Return a string in which all occurrences of PAT in memory STR are
-   replaced with SUB.
+/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
+static PyStringObject *
+replace_substring_in_place(PyStringObject *self,
+			   PyStringObject *from,
+			   PyStringObject *to,
+			   Py_ssize_t maxcount)
+{
+	char *result_s, *start, *end;
+	char *self_s, *from_s, *to_s;
+	Py_ssize_t self_len, from_len, offset;
+	PyStringObject *result;
+	
+	/* The result string will be the same size */
+	
+	self_s = PyString_AS_STRING(self);
+	self_len = PyString_GET_SIZE(self);
+	
+	from_s = PyString_AS_STRING(from);
+	from_len = PyString_GET_SIZE(from);
+	to_s = PyString_AS_STRING(to);
+	
+	offset = findstring(self_s, self_len,
+			    from_s, from_len,
+			    0, self_len, FORWARD);
+	
+	if (offset == -1) {
+		/* No matches; return the original string */
+		return return_self(self);
+	}
+	
+	/* Need to make a new string */
+	result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len);
+	if (result == NULL)
+		return NULL;
+	result_s = PyString_AS_STRING(result);
+	memcpy(result_s, self_s, self_len);
 
-   If length of PAT is less than length of STR or there are no occurrences
-   of PAT in STR, then the original string is returned. Otherwise, a new
-   string is allocated here and returned.
-
-   on return, out_len is:
-       the length of output string, or
-       -1 if the input string is returned, or
-       unchanged if an error occurs (no memory).
-
-   return value is:
-       the new string allocated locally, or
-       NULL if an error occurred.
-*/
-static char *
-mymemreplace(const char *str, Py_ssize_t len,		/* input string */
-             const char *pat, Py_ssize_t pat_len,	/* pattern string to find */
-             const char *sub, Py_ssize_t sub_len,	/* substitution string */
-             Py_ssize_t count,				/* number of replacements */
-	     Py_ssize_t *out_len)
-{
-	char *out_s;
-	char *new_s;
-	Py_ssize_t nfound, offset, new_len;
-
-	if (len == 0 || (pat_len == 0 && sub_len == 0) || pat_len > len)
-		goto return_same;
-
-	/* find length of output string */
-	nfound = (pat_len > 0) ? mymemcnt(str, len, pat, pat_len) : len + 1;
-	if (count < 0)
-		count = PY_SSIZE_T_MAX;
-	else if (nfound > count)
-		nfound = count;
-	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';
+	
+	/* change everything in-place, starting with this one */
+	start =  result_s + offset;
+	memcpy(start, to_s, from_len);
+	start += from_len;
+	end = result_s + self_len;
+	
+	while ( --maxcount > 0) {
+		offset = findstring(start, end-start,
+				    from_s, from_len,
+				    0, end-start, FORWARD);
+		if (offset==-1)
+			break;
+		memcpy(start+offset, to_s, from_len);
+		start += offset+from_len;
 	}
-	else {
-		assert(new_len > 0);
-		new_s = (char *)PyMem_MALLOC(new_len);
-		if (new_s == NULL)
-			return NULL;
-		out_s = new_s;
+	
+	return result;
+}
 
-		if (pat_len > 0) {
-			for (; nfound > 0; --nfound) {
-				/* find index of next instance of pattern */
-				offset = mymemfind(str, len, pat, pat_len);
-				if (offset == -1)
-					break;
+/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */
+static PyStringObject *
+replace_single_character(PyStringObject *self,
+			 char from_c,
+			 PyStringObject *to,
+			 Py_ssize_t maxcount)
+{
+	char *self_s, *to_s, *result_s;
+	char *start, *next, *end;
+	Py_ssize_t self_len, to_len, result_len;
+	Py_ssize_t count, product;
+	PyStringObject *result;
+	
+	self_s = PyString_AS_STRING(self);
+	self_len = PyString_GET_SIZE(self);
+	
+	count = countchar(self_s, self_len, from_c);
+	if (count > maxcount)
+		count = maxcount;
+	
+	if (count == 0) {
+		/* no matches, return unchanged */
+		return return_self(self);
+	}
+	
+	to_s = PyString_AS_STRING(to);
+	to_len = PyString_GET_SIZE(to);
+	
+	/* use the difference between current and new, hence the "-1" */
+	/*   result_len = self_len + count * (to_len-1)  */
+	product = count * (to_len-1);
+	if (product / (to_len-1) != count) {
+		PyErr_SetString(PyExc_OverflowError, "replace string is too long");
+		return NULL;
+	}
+	result_len = self_len + product;
+	if (result_len < 0) {
+		PyErr_SetString(PyExc_OverflowError, "replace string is too long");
+		return NULL;
+	}
+	
+	if ( (result = (PyStringObject *)
+	      PyString_FromStringAndSize(NULL, result_len)) == NULL)
+		return NULL;
+	result_s = PyString_AS_STRING(result);
+	
+	start = self_s;
+	end = self_s + self_len;
+	while (count-- > 0) {
+		next = findchar(start, end-start, from_c);
+		if (next == NULL) 
+			break;
+		
+		if (next == start) {
+			/* replace with the 'to' */
+			memcpy(result_s, to_s, to_len);
+			result_s += to_len;
+			start += 1;
+		} else {
+			/* copy the unchanged old then the 'to' */
+			memcpy(result_s, start, next-start);
+			result_s += (next-start);
+			memcpy(result_s, to_s, to_len);
+			result_s += to_len;
+			start = next+1;
+		}
+	}
+	/* Copy the remainder of the remaining string */
+	memcpy(result_s, start, end-start);
+	
+	return result;
+}
 
-				/* 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);
+/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
+static PyStringObject *
+replace_substring(PyStringObject *self,
+		  PyStringObject *from,
+		  PyStringObject *to,
+		  Py_ssize_t maxcount) {
+	char *self_s, *from_s, *to_s, *result_s;
+	char *start, *next, *end;
+	Py_ssize_t self_len, from_len, to_len, result_len;
+	Py_ssize_t count, offset, product;
+	PyStringObject *result;
+	
+	self_s = PyString_AS_STRING(self);
+	self_len = PyString_GET_SIZE(self);
+	from_s = PyString_AS_STRING(from);
+	from_len = PyString_GET_SIZE(from);
+	
+	count = countstring(self_s, self_len,
+			    from_s, from_len,
+			    0, self_len, FORWARD);
+	if (count > maxcount)
+		count = maxcount;
+	
+	if (count == 0) {
+		/* no matches, return unchanged */
+		return return_self(self);
+	}
+	
+	to_s = PyString_AS_STRING(to);
+	to_len = PyString_GET_SIZE(to);
+	
+	/* Check for overflow */
+	/*    result_len = self_len + count * (to_len-from_len) */
+	product = count * (to_len-from_len);
+	if (product / (to_len-from_len) != count) {
+		PyErr_SetString(PyExc_OverflowError, "replace string is too long");
+		return NULL;
+	}
+	result_len = self_len + product;
+	if (result_len < 0) {
+		PyErr_SetString(PyExc_OverflowError, "replace string is too long");
+		return NULL;
+	}
+	
+	if ( (result = (PyStringObject *)
+	      PyString_FromStringAndSize(NULL, result_len)) == NULL)
+		return NULL;
+	result_s = PyString_AS_STRING(result);
+	
+	start = self_s;
+	end = self_s + self_len;
+	while (count-- > 0) {
+		offset = findstring(start, end-start,
+				    from_s, from_len,
+				    0, end-start, FORWARD);
+		if (offset == -1)
+			break;
+		next = start+offset;
+		if (next == start) {
+			/* replace with the 'to' */
+			memcpy(result_s, to_s, to_len);
+			result_s += to_len;
+			start += from_len;
+		} else {
+			/* copy the unchanged old then the 'to' */
+			memcpy(result_s, start, next-start);
+			result_s += (next-start);
+			memcpy(result_s, to_s, to_len);
+			result_s += to_len;
+			start = next+from_len;
 		}
-		else {
-			for (;;++str, --len) {
-				memcpy(new_s, sub, sub_len);
-				new_s += sub_len;
-				if (--nfound <= 0) {
-					memcpy(new_s, str, len);
-					break;
-				}
-				*new_s++ = *str;
-			}
+	}
+	/* Copy the remainder of the remaining string */
+	memcpy(result_s, start, end-start);
+	
+	return result;
+}
+
+
+static PyStringObject *
+replace(PyStringObject *self,
+	PyStringObject *from,
+	PyStringObject *to,
+	Py_ssize_t maxcount)
+{
+	Py_ssize_t from_len, to_len;
+	
+	if (maxcount < 0) {
+		maxcount = PY_SSIZE_T_MAX;
+	} else if (maxcount == 0 || PyString_GET_SIZE(self) == 0) {
+		/* nothing to do; return the original string */
+		return return_self(self);
+	}
+	
+	from_len = PyString_GET_SIZE(from);
+	to_len = PyString_GET_SIZE(to);
+	
+	if (maxcount == 0 ||
+	    (from_len == 0 && to_len == 0)) {
+		/* nothing to do; return the original string */
+		return return_self(self);
+	}
+
+	/* Handle zero-length special cases */
+	
+	if (from_len == 0) {
+		/* insert the 'to' string everywhere.   */
+		/*    >>> "Python".replace("", ".")     */
+		/*    '.P.y.t.h.o.n.'                   */
+		return replace_interleave(self, to, maxcount);
+	}
+
+	/* Except for "".replace("", "A") == "A" there is no way beyond this */
+	/* point for an empty self string to generate a non-empty string */
+	/* Special case so the remaining code always gets a non-empty string */
+	if (PyString_GET_SIZE(self) == 0) {
+		return return_self(self);
+	}
+
+	if (to_len == 0) {
+		/* delete all occurances of 'from' string */
+		if (from_len == 1) {
+			return replace_delete_single_character(
+				self, PyString_AS_STRING(from)[0], maxcount);
+		} else {
+			return replace_delete_substring(self, from, maxcount);
 		}
 	}
-	*out_len = new_len;
-	return out_s;
 
-  return_same:
-	*out_len = -1;
-	return (char *)str; /* cast away const */
-}
+	/* Handle special case where both strings have the same length */
+
+	if (from_len == to_len) {
+		if (from_len == 1) {
+			return replace_single_character_in_place(
+				self,
+				PyString_AS_STRING(from)[0],
+				PyString_AS_STRING(to)[0],
+				maxcount);
+		} else {
+			return replace_substring_in_place(
+				self, from, to, maxcount);
+		}
+	}
 
+	/* Otherwise use the more generic algorithms */
+	if (from_len == 1) {
+		return replace_single_character(self, PyString_AS_STRING(from)[0],
+						to, maxcount);
+	} else {
+		/* len('from')>=2, len('to')>=1 */
+		return replace_substring(self, from, to, maxcount);
+	}
+}
 
 PyDoc_STRVAR(replace__doc__,
 "S.replace (old, new[, count]) -> string\n\
@@ -2529,66 +3207,42 @@
 static PyObject *
 string_replace(PyStringObject *self, PyObject *args)
 {
-	const char *str = PyString_AS_STRING(self), *sub, *repl;
-	char *new_s;
-	const Py_ssize_t len = PyString_GET_SIZE(self);
-	Py_ssize_t sub_len, repl_len, out_len;
 	Py_ssize_t count = -1;
-	PyObject *newobj;
-	PyObject *subobj, *replobj;
+	PyObject *from, *to;
+	const char *tmp_s;
+	Py_ssize_t tmp_len;
 
-	if (!PyArg_ParseTuple(args, "OO|n:replace",
-			      &subobj, &replobj, &count))
+	if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
 		return NULL;
 
-	if (PyString_Check(subobj)) {
-		sub = PyString_AS_STRING(subobj);
-		sub_len = PyString_GET_SIZE(subobj);
+	if (PyString_Check(from)) {
+	  /* Can this be made a '!check' after the Unicode check? */
 	}
 #ifdef Py_USING_UNICODE
-	else if (PyUnicode_Check(subobj))
+	if (PyUnicode_Check(from))
 		return PyUnicode_Replace((PyObject *)self,
-					 subobj, replobj, count);
+					 from, to, count);
 #endif
-	else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))
+	else if (PyObject_AsCharBuffer(from, &tmp_s, &tmp_len))
 		return NULL;
 
-	if (PyString_Check(replobj)) {
-		repl = PyString_AS_STRING(replobj);
-		repl_len = PyString_GET_SIZE(replobj);
+	if (PyString_Check(to)) {
+	  /* Can this be made a '!check' after the Unicode check? */
 	}
 #ifdef Py_USING_UNICODE
-	else if (PyUnicode_Check(replobj))
+	else if (PyUnicode_Check(to))
 		return PyUnicode_Replace((PyObject *)self,
-					 subobj, replobj, count);
+					 from, to, count);
 #endif
-	else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len))
+	else if (PyObject_AsCharBuffer(to, &tmp_s, &tmp_len))
 		return NULL;
 
-	new_s = mymemreplace(str,len,sub,sub_len,repl,repl_len,count,&out_len);
-	if (new_s == NULL) {
-		PyErr_NoMemory();
-		return NULL;
-	}
-	if (out_len == -1) {
-		if (PyString_CheckExact(self)) {
-			/* we're returning another reference to self */
-			newobj = (PyObject*)self;
-			Py_INCREF(newobj);
-		}
-		else {
-			newobj = PyString_FromStringAndSize(str, len);
-			if (newobj == NULL)
-				return NULL;
-		}
-	}
-	else {
-		newobj = PyString_FromStringAndSize(new_s, out_len);
-		PyMem_FREE(new_s);
-	}
-	return newobj;
+	return (PyObject *)replace((PyStringObject *) self,
+				   (PyStringObject *) from,
+				   (PyStringObject *) to, count);
 }
 
+/** End DALKE **/
 
 PyDoc_STRVAR(startswith__doc__,
 "S.startswith(prefix[, start[, end]]) -> bool\n\
@@ -3312,6 +3966,7 @@
 	{"count", (PyCFunction)string_count, METH_VARARGS, count__doc__},
 	{"endswith", (PyCFunction)string_endswith, METH_VARARGS,
 	 endswith__doc__},
+	{"partition", (PyCFunction)string_partition, METH_O, partition__doc__},
 	{"find", (PyCFunction)string_find, METH_VARARGS, find__doc__},
 	{"index", (PyCFunction)string_index, METH_VARARGS, index__doc__},
 	{"lstrip", (PyCFunction)string_lstrip, METH_VARARGS, lstrip__doc__},

Modified: python/branches/blais-bytebuf/Objects/typeobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/typeobject.c	(original)
+++ python/branches/blais-bytebuf/Objects/typeobject.c	Fri May 26 13:03:30 2006
@@ -4641,10 +4641,10 @@
 	     (void *)PyObject_GenericGetAttr))
 		res = PyObject_GenericGetAttr(self, name);
 	else
-		res = PyObject_CallFunction(getattribute, "OO", self, name);
+		res = PyObject_CallFunctionObjArgs(getattribute, self, name, NULL);
 	if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
 		PyErr_Clear();
-		res = PyObject_CallFunction(getattr, "OO", self, name);
+		res = PyObject_CallFunctionObjArgs(getattr, self, name, NULL);
 	}
 	return res;
 }
@@ -4781,7 +4781,7 @@
 		obj = Py_None;
 	if (type == NULL)
 		type = Py_None;
-	return PyObject_CallFunction(get, "OOO", self, obj, type);
+	return PyObject_CallFunctionObjArgs(get, self, obj, type, NULL);
 }
 
 static int
@@ -5728,8 +5728,8 @@
 	if (su->ob_type != &PySuper_Type)
 		/* If su is an instance of a (strict) subclass of super,
 		   call its type */
-		return PyObject_CallFunction((PyObject *)su->ob_type,
-					     "OO", su->type, obj);
+		return PyObject_CallFunctionObjArgs((PyObject *)su->ob_type,
+					            su->type, obj, NULL);
 	else {
 		/* Inline the common case */
 		PyTypeObject *obj_type = supercheck(su->type, obj);

Modified: python/branches/blais-bytebuf/Objects/unicodeobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/unicodeobject.c	(original)
+++ python/branches/blais-bytebuf/Objects/unicodeobject.c	Fri May 26 13:03:30 2006
@@ -4,6 +4,9 @@
 modified by Marc-Andre Lemburg <mal at lemburg.com> according to the
 Unicode Integration Proposal (see file Misc/unicode.txt).
 
+Major speed upgrades to the method implementations at the Reykjavik
+NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke.
+
 Copyright (c) Corporation for National Research Initiatives.
 
 --------------------------------------------------------------------
@@ -193,6 +196,7 @@
     /* Resizing shared object (unicode_empty or single character
        objects) in-place is not allowed. Use PyUnicode_Resize()
        instead ! */
+
     if (unicode == unicode_empty || 
 	(unicode->length == 1 && 
 	 unicode->str[0] < 256U &&
@@ -202,8 +206,11 @@
         return -1;
     }
 
-    /* We allocate one more byte to make sure the string is
-       Ux0000 terminated -- XXX is this needed ? */
+    /* We allocate one more byte to make sure the string is Ux0000 terminated.
+       The overallocation is also used by fastsearch, which assumes that it's
+       safe to look at str[length] (without makeing any assumptions about what
+       it contains). */
+
     oldstr = unicode->str;
     PyMem_RESIZE(unicode->str, Py_UNICODE, length + 1);
     if (!unicode->str) {
@@ -3859,16 +3866,16 @@
 
 /* --- Helpers ------------------------------------------------------------ */
 
-#define USE_FAST /* experimental fast search implementation */
-
 /* fast search/count implementation, based on a mix between boyer-
    moore and horspool, with a few more bells and whistles on the top.
    for some more background, see: http://effbot.org/stringlib */
 
 /* note: fastsearch may access s[n], which isn't a problem when using
-   Python's ordinary string types.  also, the count mode returns -1 if
-   there cannot possible be a match in the target string, and 0 if it
-   has actually checked for matches. */
+   Python's ordinary string types, but may cause problems if you're
+   using this code in other contexts.  also, the count mode returns -1
+   if there cannot possible be a match in the target string, and 0 if
+   it has actually checked for matches, but didn't find any.  callers
+   beware! */
 
 #define FAST_COUNT 0
 #define FAST_SEARCH 1
@@ -3877,7 +3884,7 @@
 fastsearch(Py_UNICODE* s, Py_ssize_t n, Py_UNICODE* p, Py_ssize_t m, int mode)
 {
     long mask;
-    int skip, count = 0;
+    Py_ssize_t skip, count = 0;
     Py_ssize_t i, j, mlast, w;
 
     w = n - m;
@@ -3934,10 +3941,8 @@
             /* miss: check if next character is part of pattern */
             if (!(mask & (1 << (s[i+m] & 0x1F))))
                 i = i + m;
-            else {
+            else
                 i = i + skip;
-                continue;
-            }
         } else {
             /* skip: check if next character is part of pattern */
             if (!(mask & (1 << (s[i+m] & 0x1F))))
@@ -3971,23 +3976,13 @@
     if (substring->length == 0)
 	return (end - start + 1);
 
-#ifdef USE_FAST
     count = fastsearch(
         PyUnicode_AS_UNICODE(self) + start, end - start,
         substring->str, substring->length, FAST_COUNT
         );
+
     if (count < 0)
         count = 0; /* no match */
-#else    
-    end -= substring->length;
-
-    while (start <= end)
-        if (Py_UNICODE_MATCH(self, start, substring)) {
-            count++;
-            start += substring->length;
-        } else
-            start++;
-#endif
 
     return count;
 }
@@ -4038,30 +4033,19 @@
     if (substring->length == 0)
 	return (direction > 0) ? start : end;
 
-#ifdef USE_FAST
     if (direction > 0) {
         Py_ssize_t pos = fastsearch(
             PyUnicode_AS_UNICODE(self) + start, end - start,
             substring->str, substring->length, FAST_SEARCH
             );
-        if (pos < 0)
-            return pos;
-        return pos + start;
-    }
-#endif
-
-    end -= substring->length;
-
-    if (direction < 0) {
+        if (pos >= 0)
+            return pos + start;
+    } else {
+        end -= substring->length;
         for (; end >= start; end--)
             if (Py_UNICODE_MATCH(self, end, substring))
                 return end;
-    } else {
-        for (; start <= end; start++)
-            if (Py_UNICODE_MATCH(self, start, substring))
-                return start;
     }
-
     return -1;
 }
 
@@ -4862,6 +4846,7 @@
     } else {
 
         Py_ssize_t n, i;
+        Py_ssize_t product, new_size, delta;
         Py_UNICODE *p;
 
         /* replace strings */
@@ -4870,7 +4855,25 @@
             n = maxcount;
         if (n == 0)
             goto nothing;
-        u = _PyUnicode_New(self->length + n * (str2->length - str1->length));
+        /* new_size = self->length + n * (str2->length - str1->length)); */
+        delta = (str2->length - str1->length);
+        if (delta == 0) {
+            new_size = self->length;
+        } else {
+            product = n * (str2->length - str1->length);
+            if ((product / (str2->length - str1->length)) != n) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "replace string is too long");
+                return NULL;
+            }
+            new_size = self->length + product;
+            if (new_size < 0) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "replace string is too long");
+                return NULL;
+            }
+        }
+        u = _PyUnicode_New(new_size);
         if (!u)
             return NULL;
         i = 0;
@@ -5146,11 +5149,8 @@
 		       PyObject *element)
 {
     PyUnicodeObject *u, *v;
-    int result;
     Py_ssize_t size;
-#ifdef USE_FAST
     Py_ssize_t pos;
-#endif
 
     /* Coerce the two arguments */
     v = (PyUnicodeObject *) PyUnicode_FromObject(element);
@@ -5168,44 +5168,19 @@
 
     size = PyUnicode_GET_SIZE(v);
     if (!size) {
-        result = 1;
+        pos = 0;
         goto done;
     }
 
-#ifdef USE_FAST
     pos = fastsearch(
         PyUnicode_AS_UNICODE(u), PyUnicode_GET_SIZE(u),
         PyUnicode_AS_UNICODE(v), size, FAST_SEARCH
         );
-    result = (pos != -1);
-#else    
-    result = 0;
-
-    if (size == 1) {
-        Py_UNICODE chr = PyUnicode_AS_UNICODE(v)[0];
-        Py_UNICODE* ptr = PyUnicode_AS_UNICODE(u);
-	Py_UNICODE* end = ptr + PyUnicode_GET_SIZE(u);
-	for (; ptr < end; ptr++) {
-	    if (*ptr == chr) {
-		result = 1;
-		break;
-	    }
-	}
-    } else {
-        Py_ssize_t start = 0;
-        Py_ssize_t end = PyUnicode_GET_SIZE(u) - size;
-        for (; start <= end; start++)
-            if (Py_UNICODE_MATCH(u, start, v)) {
-                result = 1;
-                break;
-            }
-    }
-#endif
 
 done:
     Py_DECREF(u);
     Py_DECREF(v);
-    return result;
+    return (pos != -1);
 }
 
 /* Concat to string or Unicode object giving a new Unicode object. */
@@ -5285,7 +5260,7 @@
     if (end < 0)
         end = 0;
 
-    result = PyInt_FromLong((long) count(self, start, end, substring));
+    result = PyInt_FromSsize_t(count(self, start, end, substring));
 
     Py_DECREF(substring);
     return result;
@@ -6314,6 +6289,79 @@
 	return PyUnicode_Split((PyObject *)self, substring, maxcount);
 }
 
+PyObject *
+PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)
+{
+    PyObject* str_obj;
+    PyObject* sep_obj;
+    Py_UNICODE *str, *sep;
+    Py_ssize_t len, sep_len, pos;
+    PyObject* out;
+    
+    str_obj = PyUnicode_FromObject(str_in);
+    if (!str_obj)
+	return NULL;
+    sep_obj = PyUnicode_FromObject(sep_in);
+    if (!sep_obj)
+        goto error;
+
+    str = PyUnicode_AS_UNICODE(str_obj);
+    len = PyUnicode_GET_SIZE(str_obj);
+
+    sep = PyUnicode_AS_UNICODE(sep_obj);
+    sep_len = PyUnicode_GET_SIZE(sep_obj);
+
+    if (sep_len == 0) {
+        PyErr_SetString(PyExc_ValueError, "empty separator");
+        goto error;
+    }
+
+    out = PyTuple_New(3);
+    if (!out)
+        goto error;
+
+    pos = fastsearch(str, len, sep, sep_len, FAST_SEARCH);
+    if (pos < 0) {
+        Py_INCREF(str_obj);
+        PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj);
+        Py_INCREF(unicode_empty);
+        PyTuple_SET_ITEM(out, 1, (PyObject*) unicode_empty);
+        Py_INCREF(unicode_empty);
+        PyTuple_SET_ITEM(out, 2, (PyObject*) unicode_empty);
+    } else {
+        PyObject* obj;
+        PyTuple_SET_ITEM(out, 0, PyUnicode_FromUnicode(str, pos));
+        Py_INCREF(sep_obj);
+        PyTuple_SET_ITEM(out, 1, sep_obj);
+        obj = PyUnicode_FromUnicode(str + sep_len + pos, len - sep_len - pos);
+        PyTuple_SET_ITEM(out, 2, obj);
+        if (PyErr_Occurred()) {
+            Py_DECREF(out);
+            goto error;
+        }
+    }
+
+    return out;
+
+error:
+    Py_XDECREF(sep_obj);
+    Py_DECREF(str_obj);
+    return NULL;
+}
+
+PyDoc_STRVAR(partition__doc__,
+"S.partition(sep) -> (head, sep, tail)\n\
+\n\
+Searches for the separator sep in S, and returns the part before it,\n\
+the separator itself, and the part after it.  If the separator is not\n\
+found, returns S and two empty strings.");
+
+static PyObject*
+unicode_partition(PyUnicodeObject *self, PyObject *separator)
+{
+    return PyUnicode_Partition((PyObject *)self, separator);
+}
+
 PyObject *PyUnicode_RSplit(PyObject *s,
 			   PyObject *sep,
 			   Py_ssize_t maxsplit)
@@ -6567,6 +6615,7 @@
     {"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__},
     {"expandtabs", (PyCFunction) unicode_expandtabs, METH_VARARGS, expandtabs__doc__},
     {"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__},
+    {"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__},
     {"index", (PyCFunction) unicode_index, METH_VARARGS, index__doc__},
     {"ljust", (PyCFunction) unicode_ljust, METH_VARARGS, ljust__doc__},
     {"lower", (PyCFunction) unicode_lower, METH_NOARGS, lower__doc__},

Modified: python/branches/blais-bytebuf/Objects/weakrefobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/weakrefobject.c	(original)
+++ python/branches/blais-bytebuf/Objects/weakrefobject.c	Fri May 26 13:03:30 2006
@@ -851,7 +851,7 @@
 static void
 handle_callback(PyWeakReference *ref, PyObject *callback)
 {
-    PyObject *cbresult = PyObject_CallFunction(callback, "O", ref);
+    PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
 
     if (cbresult == NULL)
         PyErr_WriteUnraisable(callback);

Modified: python/branches/blais-bytebuf/PC/pyconfig.h
==============================================================================
--- python/branches/blais-bytebuf/PC/pyconfig.h	(original)
+++ python/branches/blais-bytebuf/PC/pyconfig.h	Fri May 26 13:03:30 2006
@@ -162,6 +162,7 @@
 #include <float.h>
 #define Py_IS_NAN _isnan
 #define Py_IS_INFINITY(X) (!_finite(X) && !_isnan(X))
+#define Py_IS_FINITE(X) _finite(X)
 
 #endif /* _MSC_VER */
 

Modified: python/branches/blais-bytebuf/Python/ceval.c
==============================================================================
--- python/branches/blais-bytebuf/Python/ceval.c	(original)
+++ python/branches/blais-bytebuf/Python/ceval.c	Fri May 26 13:03:30 2006
@@ -4053,7 +4053,7 @@
 			metaclass = (PyObject *) &PyClass_Type;
 		Py_INCREF(metaclass);
 	}
-	result = PyObject_CallFunction(metaclass, "OOO", name, bases, methods);
+	result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods, NULL);
 	Py_DECREF(metaclass);
 	if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
 		/* A type error here likely means that the user passed 

Modified: python/branches/blais-bytebuf/Python/import.c
==============================================================================
--- python/branches/blais-bytebuf/Python/import.c	(original)
+++ python/branches/blais-bytebuf/Python/import.c	Fri May 26 13:03:30 2006
@@ -1043,7 +1043,7 @@
 		PyObject *hook = PyList_GetItem(path_hooks, j);
 		if (hook == NULL)
 			return NULL;
-		importer = PyObject_CallFunction(hook, "O", p);
+		importer = PyObject_CallFunctionObjArgs(hook, p, NULL);
 		if (importer != NULL)
 			break;
 
@@ -2499,8 +2499,8 @@
 		goto err;
 
 	/* Call the _import__ function with the proper argument list */
-	r = PyObject_CallFunction(import, "OOOO",
-				  module_name, globals, globals, silly_list);
+	r = PyObject_CallFunctionObjArgs(import, module_name, globals,
+					 globals, silly_list, NULL);
 
   err:
 	Py_XDECREF(globals);

Modified: python/branches/blais-bytebuf/Python/mystrtoul.c
==============================================================================
--- python/branches/blais-bytebuf/Python/mystrtoul.c	(original)
+++ python/branches/blais-bytebuf/Python/mystrtoul.c	Fri May 26 13:03:30 2006
@@ -75,34 +75,6 @@
 	7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  /* 20 - 29 */
 	6,  6,  6,  6,  6,  6,  6};             /* 30 - 36 */
 
-/* char-to-digit conversion for bases 2-36; all non-digits are 37 */
-static int digitlookup[] = {
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  37, 37, 37, 37, 37, 37,
-	37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
-	25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
-	37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
-	25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-	37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37
-};
-
 /*
 **	strtoul
 **		This is a general purpose routine for converting
@@ -167,7 +139,7 @@
 	ovlimit = digitlimit[base];
 
 	/* do the conversion until non-digit character encountered */
-	while ((c = digitlookup[Py_CHARMASK(*str)]) < base) {
+	while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
 		if (ovlimit > 0) /* no overflow check required */
 			result = result * base + c;
 		else { /* requires overflow check */
@@ -204,7 +176,7 @@
 overflowed:
 	if (ptr) {
 		/* spool through remaining digit characters */
-		while (digitlookup[Py_CHARMASK(*str)] < base)
+		while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
 			++str;
 		*ptr = str;
 	}

Modified: python/branches/blais-bytebuf/Python/pystrtod.c
==============================================================================
--- python/branches/blais-bytebuf/Python/pystrtod.c	(original)
+++ python/branches/blais-bytebuf/Python/pystrtod.c	Fri May 26 13:03:30 2006
@@ -101,7 +101,7 @@
 		char *copy, *c;
 
 		/* We need to convert the '.' to the locale specific decimal point */
-		copy = (char *)malloc(end - nptr + 1 + decimal_point_len);
+		copy = (char *)PyMem_MALLOC(end - nptr + 1 + decimal_point_len);
 
 		c = copy;
 		memcpy(c, nptr, decimal_point_pos - nptr);
@@ -122,7 +122,7 @@
 				fail_pos = (char *)nptr + (fail_pos - copy);
 		}
 
-		free(copy);
+		PyMem_FREE(copy);
 
 	}
 	else {


More information about the Python-checkins mailing list