[pypy-commit] pypy py3k: hg merge default

amauryfa noreply at buildbot.pypy.org
Wed May 2 01:03:58 CEST 2012


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r54855:d8adf28f689b
Date: 2012-04-28 22:23 +0200
http://bitbucket.org/pypy/pypy/changeset/d8adf28f689b/

Log:	hg merge default

diff --git a/lib-python/modified-2.7/test/test_peepholer.py b/lib-python/modified-2.7/test/test_peepholer.py
--- a/lib-python/modified-2.7/test/test_peepholer.py
+++ b/lib-python/modified-2.7/test/test_peepholer.py
@@ -145,12 +145,15 @@
 
     def test_binary_subscr_on_unicode(self):
         # valid code get optimized
-        asm = dis_single('u"foo"[0]')
-        self.assertIn("(u'f')", asm)
-        self.assertNotIn('BINARY_SUBSCR', asm)
-        asm = dis_single('u"\u0061\uffff"[1]')
-        self.assertIn("(u'\\uffff')", asm)
-        self.assertNotIn('BINARY_SUBSCR', asm)
+        # XXX for now we always disable this optimization
+        # XXX see CPython's issue5057
+        if 0:
+            asm = dis_single('u"foo"[0]')
+            self.assertIn("(u'f')", asm)
+            self.assertNotIn('BINARY_SUBSCR', asm)
+            asm = dis_single('u"\u0061\uffff"[1]')
+            self.assertIn("(u'\\uffff')", asm)
+            self.assertNotIn('BINARY_SUBSCR', asm)
 
         # invalid code doesn't get optimized
         # out of range
diff --git a/lib_pypy/_ctypes/builtin.py b/lib_pypy/_ctypes/builtin.py
--- a/lib_pypy/_ctypes/builtin.py
+++ b/lib_pypy/_ctypes/builtin.py
@@ -3,7 +3,8 @@
 try:
     from thread import _local as local
 except ImportError:
-    local = object    # no threads
+    class local(object):    # no threads
+        pass
 
 class ConvMode:
     encoding = 'ascii'
diff --git a/lib_pypy/_ctypes_test.py b/lib_pypy/_ctypes_test.py
--- a/lib_pypy/_ctypes_test.py
+++ b/lib_pypy/_ctypes_test.py
@@ -21,7 +21,7 @@
     # Compile .c file
     include_dir = os.path.join(thisdir, '..', 'include')
     if sys.platform == 'win32':
-        ccflags = []
+        ccflags = ['-D_CRT_SECURE_NO_WARNINGS']
     else:
         ccflags = ['-fPIC']
     res = compiler.compile([os.path.join(thisdir, '_ctypes_test.c')],
@@ -34,6 +34,13 @@
     if sys.platform == 'win32':
         # XXX libpypy-c.lib is currently not installed automatically
         library = os.path.join(thisdir, '..', 'include', 'libpypy-c')
+        if not os.path.exists(library + '.lib'):
+            #For a nightly build
+            library = os.path.join(thisdir, '..', 'include', 'python27')
+        if not os.path.exists(library + '.lib'):
+            # For a local translation
+            library = os.path.join(thisdir, '..', 'pypy', 'translator',
+                    'goal', 'libpypy-c')
         libraries = [library, 'oleaut32']
         extra_ldargs = ['/MANIFEST'] # needed for VC10
     else:
diff --git a/lib_pypy/_testcapi.py b/lib_pypy/_testcapi.py
--- a/lib_pypy/_testcapi.py
+++ b/lib_pypy/_testcapi.py
@@ -16,7 +16,7 @@
     # Compile .c file
     include_dir = os.path.join(thisdir, '..', 'include')
     if sys.platform == 'win32':
-        ccflags = []
+        ccflags = ['-D_CRT_SECURE_NO_WARNINGS']
     else:
         ccflags = ['-fPIC', '-Wimplicit-function-declaration']
     res = compiler.compile([os.path.join(thisdir, '_testcapimodule.c')],
@@ -29,6 +29,13 @@
     if sys.platform == 'win32':
         # XXX libpypy-c.lib is currently not installed automatically
         library = os.path.join(thisdir, '..', 'include', 'libpypy-c')
+        if not os.path.exists(library + '.lib'):
+            #For a nightly build
+            library = os.path.join(thisdir, '..', 'include', 'python27')
+        if not os.path.exists(library + '.lib'):
+            # For a local translation
+            library = os.path.join(thisdir, '..', 'pypy', 'translator',
+                    'goal', 'libpypy-c')
         libraries = [library, 'oleaut32']
         extra_ldargs = ['/MANIFEST',  # needed for VC10
                         '/EXPORT:init_testcapi']
diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
--- a/lib_pypy/pyrepl/reader.py
+++ b/lib_pypy/pyrepl/reader.py
@@ -152,8 +152,8 @@
      (r'\<delete>', 'delete'),
      (r'\<backspace>', 'backspace'),
      (r'\M-\<backspace>', 'backward-kill-word'),
-     (r'\<end>', 'end'),
-     (r'\<home>', 'home'),
+     (r'\<end>', 'end-of-line'),         # was 'end'
+     (r'\<home>', 'beginning-of-line'),  # was 'home'
      (r'\<f1>', 'help'),
      (r'\EOF', 'end'),  # the entries in the terminfo database for xterms
      (r'\EOH', 'home'), # seem to be wrong.  this is a less than ideal
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -229,8 +229,8 @@
                     return thing
                 elif hasattr(thing, '__name__'): # mostly types and functions
                     return thing.__name__
-                elif hasattr(thing, 'name'): # mostly ClassDescs
-                    return thing.name
+                elif hasattr(thing, 'name') and isinstance(thing.name, str):
+                    return thing.name            # mostly ClassDescs
                 elif isinstance(thing, tuple):
                     return '_'.join(map(nameof, thing))
                 else:
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -321,10 +321,14 @@
                    default=False),
         BoolOption("getattributeshortcut",
                    "track types that override __getattribute__",
-                   default=False),
+                   default=False,
+                   # weakrefs needed, because of get_subclasses()
+                   requires=[("translation.rweakref", True)]),
         BoolOption("newshortcut",
                    "cache and shortcut calling __new__ from builtin types",
-                   default=False),
+                   default=False,
+                   # weakrefs needed, because of get_subclasses()
+                   requires=[("translation.rweakref", True)]),
 
         BoolOption("logspaceoptypes",
                    "a instrumentation option: before exit, print the types seen by "
@@ -338,7 +342,9 @@
                    requires=[("objspace.std.builtinshortcut", True)]),
         BoolOption("withidentitydict",
                    "track types that override __hash__, __eq__ or __cmp__ and use a special dict strategy for those which do not",
-                   default=False),
+                   default=False,
+                   # weakrefs needed, because of get_subclasses()
+                   requires=[("translation.rweakref", True)]),
      ]),
 ])
 
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/cppyy.rst
@@ -0,0 +1,554 @@
+============================
+cppyy: C++ bindings for PyPy
+============================
+
+The cppyy module provides C++ bindings for PyPy by using the reflection
+information extracted from C++ header files by means of the
+`Reflex package`_.
+For this to work, you have to both install Reflex and build PyPy from the
+reflex-support branch.
+As indicated by this being a branch, support for Reflex is still
+experimental.
+However, it is functional enough to put it in the hands of those who want
+to give it a try.
+In the medium term, cppyy will move away from Reflex and instead use
+`cling`_ as its backend, which is based on `llvm`_.
+Although that will change the logistics on the generation of reflection
+information, it will not change the python-side interface.
+
+.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex
+.. _`cling`: http://root.cern.ch/drupal/content/cling
+.. _`llvm`: http://llvm.org/
+
+
+Installation
+============
+
+For now, the easiest way of getting the latest version of Reflex, is by
+installing the ROOT package.
+Besides getting the latest version of Reflex, another advantage is that with
+the full ROOT package, you can also use your Reflex-bound code on `CPython`_.
+`Download`_ a binary or install from `source`_.
+Some Linux and Mac systems may have ROOT provided in the list of scientific
+software of their packager.
+A current, standalone version of Reflex should be provided at some point,
+once the dependencies and general packaging have been thought out.
+Also, make sure you have a version of `gccxml`_ installed, which is most
+easily provided by the packager of your system.
+If you read up on gccxml, you'll probably notice that it is no longer being
+developed and hence will not provide C++11 support.
+That's why the medium term plan is to move to `cling`_.
+
+.. _`Download`: http://root.cern.ch/drupal/content/downloading-root
+.. _`source`: http://root.cern.ch/drupal/content/installing-root-source
+.. _`gccxml`: http://www.gccxml.org
+
+Next, get the `PyPy sources`_, select the reflex-support branch, and build
+pypy-c.
+For the build to succeed, the ``$ROOTSYS`` environment variable must point to
+the location of your ROOT installation::
+
+    $ hg clone https://bitbucket.org/pypy/pypy
+    $ cd pypy
+    $ hg up reflex-support
+    $ cd pypy/translator/goal
+    $ python translate.py -O jit --gcrootfinder=shadowstack targetpypystandalone.py --withmod-cppyy
+
+This will build a ``pypy-c`` that includes the cppyy module, and through that,
+Reflex support.
+Of course, if you already have a pre-built version of the ``pypy`` interpreter,
+you can use that for the translation rather than ``python``.
+
+.. _`PyPy sources`: https://bitbucket.org/pypy/pypy/overview
+
+
+Basic example
+=============
+
+Now test with a trivial example whether all packages are properly installed
+and functional.
+First, create a C++ header file with some class in it (note that all functions
+are made inline for convenience; a real-world example would of course have a
+corresponding source file)::
+
+    $ cat MyClass.h
+    class MyClass {
+    public:
+        MyClass(int i = -99) : m_myint(i) {}
+
+        int GetMyInt() { return m_myint; }
+        void SetMyInt(int i) { m_myint = i; }
+
+    public:
+        int m_myint;
+    };
+
+Then, generate the bindings using ``genreflex`` (part of ROOT), and compile the
+code::
+
+    $ genreflex MyClass.h
+    $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyClass_rflx.cpp -o libMyClassDict.so
+
+Now you're ready to use the bindings.
+Since the bindings are designed to look pythonistic, it should be
+straightforward::
+
+    $ pypy-c
+    >>>> import cppyy
+    >>>> cppyy.load_reflection_info("libMyClassDict.so")
+    <CPPLibrary object at 0xb6fd7c4c>
+    >>>> myinst = cppyy.gbl.MyClass(42)
+    >>>> print myinst.GetMyInt()
+    42
+    >>>> myinst.SetMyInt(33)
+    >>>> print myinst.m_myint
+    33
+    >>>> myinst.m_myint = 77
+    >>>> print myinst.GetMyInt()
+    77
+    >>>> help(cppyy.gbl.MyClass)   # shows that normal python introspection works
+
+That's all there is to it!
+
+
+Advanced example
+================
+The following snippet of C++ is very contrived, to allow showing that such
+pathological code can be handled and to show how certain features play out in
+practice::
+
+    $ cat MyAdvanced.h
+    #include <string>
+
+    class Base1 {
+    public:
+        Base1(int i) : m_i(i) {}
+        virtual ~Base1() {}
+        int m_i;
+    };
+
+    class Base2 {
+    public:
+        Base2(double d) : m_d(d) {}
+        virtual ~Base2() {}
+        double m_d;
+    };
+
+    class C;
+
+    class Derived : public virtual Base1, public virtual Base2 {
+    public:
+        Derived(const std::string& name, int i, double d) : Base1(i), Base2(d), m_name(name) {}
+        virtual C* gimeC() { return (C*)0; }
+        std::string m_name;
+    };
+
+    Base1* BaseFactory(const std::string& name, int i, double d) {
+        return new Derived(name, i, d);
+    }
+
+This code is still only in a header file, with all functions inline, for
+convenience of the example.
+If the implementations live in a separate source file or shared library, the
+only change needed is to link those in when building the reflection library.
+
+If you were to run ``genreflex`` like above in the basic example, you will
+find that not all classes of interest will be reflected, nor will be the
+global factory function.
+In particular, ``std::string`` will be missing, since it is not defined in
+this header file, but in a header file that is included.
+In practical terms, general classes such as ``std::string`` should live in a
+core reflection set, but for the moment assume we want to have it in the
+reflection library that we are building for this example.
+
+The ``genreflex`` script can be steered using a so-called `selection file`_,
+which is a simple XML file specifying, either explicitly or by using a
+pattern, which classes, variables, namespaces, etc. to select from the given
+header file.
+With the aid of a selection file, a large project can be easily managed:
+simply ``#include`` all relevant headers into a single header file that is
+handed to ``genreflex``.
+Then, apply a selection file to pick up all the relevant classes.
+For our purposes, the following rather straightforward selection will do
+(the name ``lcgdict`` for the root is historical, but required)::
+
+    $ cat MyAdvanced.xml
+    <lcgdict>
+        <class pattern="Base?" />
+        <class name="Derived" />
+        <class name="std::string" />
+        <function name="BaseFactory" />
+    </lcgdict>
+
+.. _`selection file`: http://root.cern.ch/drupal/content/generating-reflex-dictionaries
+
+Now the reflection info can be generated and compiled::
+
+    $ genreflex MyAdvanced.h --selection=MyAdvanced.xml
+    $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyAdvanced_rflx.cpp -o libAdvExDict.so
+
+and subsequently be used from PyPy::
+
+    >>>> import cppyy
+    >>>> cppyy.load_reflection_info("libAdvExDict.so")
+    <CPPLibrary object at 0x00007fdb48fc8120>
+    >>>> d = cppyy.gbl.BaseFactory("name", 42, 3.14)
+    >>>> type(d)
+    <class '__main__.Derived'>
+    >>>> d.m_i
+    42
+    >>>> d.m_d
+    3.14
+    >>>> d.m_name == "name"
+    True
+    >>>>
+
+Again, that's all there is to it!
+
+A couple of things to note, though.
+If you look back at the C++ definition of the ``BaseFactory`` function,
+you will see that it declares the return type to be a ``Base1``, yet the
+bindings return an object of the actual type ``Derived``?
+This choice is made for a couple of reasons.
+First, it makes method dispatching easier: if bound objects are always their
+most derived type, then it is easy to calculate any offsets, if necessary.
+Second, it makes memory management easier: the combination of the type and
+the memory address uniquely identifies an object.
+That way, it can be recycled and object identity can be maintained if it is
+entered as a function argument into C++ and comes back to PyPy as a return
+value.
+Last, but not least, casting is decidedly unpythonistic.
+By always providing the most derived type known, casting becomes unnecessary.
+For example, the data member of ``Base2`` is simply directly available.
+Note also that the unreflected ``gimeC`` method of ``Derived`` does not
+preclude its use.
+It is only the ``gimeC`` method that is unusable as long as class ``C`` is
+unknown to the system.
+
+
+Features
+========
+
+The following is not meant to be an exhaustive list, since cppyy is still
+under active development.
+Furthermore, the intention is that every feature is as natural as possible on
+the python side, so if you find something missing in the list below, simply
+try it out.
+It is not always possible to provide exact mapping between python and C++
+(active memory management is one such case), but by and large, if the use of a
+feature does not strike you as obvious, it is more likely to simply be a bug.
+That is a strong statement to make, but also a worthy goal.
+
+* **abstract classes**: Are represented as python classes, since they are
+  needed to complete the inheritance hierarchies, but will raise an exception
+  if an attempt is made to instantiate from them.
+
+* **arrays**: Supported for builtin data types only, as used from module
+  ``array``.
+  Out-of-bounds checking is limited to those cases where the size is known at
+  compile time (and hence part of the reflection info).
+
+* **builtin data types**: Map onto the expected equivalent python types, with
+  the caveat that there may be size differences, and thus it is possible that
+  exceptions are raised if an overflow is detected.
+
+* **casting**: Is supposed to be unnecessary.
+  Object pointer returns from functions provide the most derived class known
+  in the hierarchy of the object being returned.
+  This is important to preserve object identity as well as to make casting,
+  a pure C++ feature after all, superfluous.
+
+* **classes and structs**: Get mapped onto python classes, where they can be
+  instantiated as expected.
+  If classes are inner classes or live in a namespace, their naming and
+  location will reflect that.
+
+* **data members**: Public data members are represented as python properties
+  and provide read and write access on instances as expected.
+
+* **default arguments**: C++ default arguments work as expected, but python
+  keywords are not supported.
+  It is technically possible to support keywords, but for the C++ interface,
+  the formal argument names have no meaning and are not considered part of the
+  API, hence it is not a good idea to use keywords.
+
+* **doc strings**: The doc string of a method or function contains the C++
+  arguments and return types of all overloads of that name, as applicable.
+
+* **enums**: Are translated as ints with no further checking.
+
+* **functions**: Work as expected and live in their appropriate namespace
+  (which can be the global one, ``cppyy.gbl``).
+
+* **inheritance**: All combinations of inheritance on the C++ (single,
+  multiple, virtual) are supported in the binding.
+  However, new python classes can only use single inheritance from a bound C++
+  class.
+  Multiple inheritance would introduce two "this" pointers in the binding.
+  This is a current, not a fundamental, limitation.
+  The C++ side will not see any overridden methods on the python side, as
+  cross-inheritance is planned but not yet supported.
+
+* **methods**: Are represented as python methods and work as expected.
+  They are first class objects and can be bound to an instance.
+  Virtual C++ methods work as expected.
+  To select a specific virtual method, do like with normal python classes
+  that override methods: select it from the class that you need, rather than
+  calling the method on the instance.
+
+* **namespaces**: Are represented as python classes.
+  Namespaces are more open-ended than classes, so sometimes initial access may
+  result in updates as data and functions are looked up and constructed
+  lazily.
+  Thus the result of ``dir()`` on a namespace should not be relied upon: it
+  only shows the already accessed members. (TODO: to be fixed by implementing
+  __dir__.)
+  The global namespace is ``cppyy.gbl``.
+
+* **operator conversions**: If defined in the C++ class and a python
+  equivalent exists (i.e. all builtin integer and floating point types, as well
+  as ``bool``), it will map onto that python conversion.
+  Note that ``char*`` is mapped onto ``__str__``.
+
+* **operator overloads**: If defined in the C++ class and if a python
+  equivalent is available (not always the case, think e.g. of ``operator||``),
+  then they work as expected.
+  Special care needs to be taken for global operator overloads in C++: first,
+  make sure that they are actually reflected, especially for the global
+  overloads for ``operator==`` and ``operator!=`` of STL iterators in the case
+  of gcc.
+  Second, make sure that reflection info is loaded in the proper order.
+  I.e. that these global overloads are available before use.
+
+* **pointers**: For builtin data types, see arrays.
+  For objects, a pointer to an object and an object looks the same, unless
+  the pointer is a data member.
+  In that case, assigning to the data member will cause a copy of the pointer
+  and care should be taken about the object's life time.
+  If a pointer is a global variable, the C++ side can replace the underlying
+  object and the python side will immediately reflect that.
+
+* **static data members**: Are represented as python property objects on the
+  class and the meta-class.
+  Both read and write access is as expected.
+
+* **static methods**: Are represented as python's ``staticmethod`` objects
+  and can be called both from the class as well as from instances.
+
+* **strings**: The std::string class is considered a builtin C++ type and
+  mixes quite well with python's str.
+  Python's str can be passed where a ``const char*`` is expected, and an str
+  will be returned if the return type is ``const char*``.
+
+* **templated classes**: Are represented in a meta-class style in python.
+  This looks a little bit confusing, but conceptually is rather natural.
+  For example, given the class ``std::vector<int>``, the meta-class part would
+  be ``std.vector`` in python.
+  Then, to get the instantiation on ``int``, do ``std.vector(int)`` and to
+  create an instance of that class, do ``std.vector(int)()``.
+  Note that templates can be build up by handing actual types to the class
+  instantiation (as done in this vector example), or by passing in the list of
+  template arguments as a string.
+  The former is a lot easier to work with if you have template instantiations
+  using classes that themselves are templates (etc.) in the arguments.
+  All classes must already exist in the loaded reflection info.
+
+* **typedefs**: Are simple python references to the actual classes to which
+  they refer.
+
+* **unary operators**: Are supported if a python equivalent exists, and if the
+  operator is defined in the C++ class.
+
+You can always find more detailed examples and see the full of supported
+features by looking at the tests in pypy/module/cppyy/test.
+
+If a feature or reflection info is missing, this is supposed to be handled
+gracefully.
+In fact, there are unit tests explicitly for this purpose (even as their use
+becomes less interesting over time, as the number of missing features
+decreases).
+Only when a missing feature is used, should there be an exception.
+For example, if no reflection info is available for a return type, then a
+class that has a method with that return type can still be used.
+Only that one specific method can not be used.
+
+
+Templates
+=========
+
+A bit of special care needs to be taken for the use of templates.
+For a templated class to be completely available, it must be guaranteed that
+said class is fully instantiated, and hence all executable C++ code is
+generated and compiled in.
+The easiest way to fulfill that guarantee is by explicit instantiation in the
+header file that is handed to ``genreflex``.
+The following example should make that clear::
+
+    $ cat MyTemplate.h
+    #include <vector>
+
+    class MyClass {
+    public:
+        MyClass(int i = -99) : m_i(i) {}
+        MyClass(const MyClass& s) : m_i(s.m_i) {}
+        MyClass& operator=(const MyClass& s) { m_i = s.m_i; return *this; }
+        ~MyClass() {}
+        int m_i;
+    };
+
+    template class std::vector<MyClass>;
+
+If you know for certain that all symbols will be linked in from other sources,
+you can also declare the explicit template instantiation ``extern``.
+
+Unfortunately, this is not enough for gcc.
+The iterators, if they are going to be used, need to be instantiated as well,
+as do the comparison operators on those iterators, as these live in an
+internal namespace, rather than in the iterator classes.
+One way to handle this, is to deal with this once in a macro, then reuse that
+macro for all ``vector`` classes.
+Thus, the header above needs this, instead of just the explicit instantiation
+of the ``vector<MyClass>``::
+
+    #define STLTYPES_EXPLICIT_INSTANTIATION_DECL(STLTYPE, TTYPE)                      \
+    template class std::STLTYPE< TTYPE >;                                             \
+    template class __gnu_cxx::__normal_iterator<TTYPE*, std::STLTYPE< TTYPE > >;      \
+    template class __gnu_cxx::__normal_iterator<const TTYPE*, std::STLTYPE< TTYPE > >;\
+    namespace __gnu_cxx {                                                             \
+    template bool operator==(const std::STLTYPE< TTYPE >::iterator&,                  \
+                             const std::STLTYPE< TTYPE >::iterator&);                 \
+    template bool operator!=(const std::STLTYPE< TTYPE >::iterator&,                  \
+                             const std::STLTYPE< TTYPE >::iterator&);                 \
+    }
+
+    STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, MyClass)
+
+Then, still for gcc, the selection file needs to contain the full hierarchy as
+well as the global overloads for comparisons for the iterators::
+
+    $ cat MyTemplate.xml
+    <lcgdict>
+        <class pattern="std::vector<*>" />
+        <class pattern="__gnu_cxx::__normal_iterator<*>" />
+        <class pattern="__gnu_cxx::new_allocator<*>" />
+        <class pattern="std::_Vector_base<*>" />
+        <class pattern="std::_Vector_base<*>::_Vector_impl" />
+        <class pattern="std::allocator<*>" />
+        <function name="__gnu_cxx::operator=="/>
+        <function name="__gnu_cxx::operator!="/>
+
+        <class name="MyClass" />
+    </lcgdict>
+
+Run the normal ``genreflex`` and compilation steps::
+
+    $ genreflex MyTemplate.h --selection=MyTemplate.xm
+    $ g++ -fPIC -rdynamic -O2 -shared -I$ROOTSYS/include MyTemplate_rflx.cpp -o libTemplateDict.so
+
+Note: this is a dirty corner that clearly could do with some automation,
+even if the macro already helps.
+Such automation is planned.
+In fact, in the cling world, the backend can perform the template
+instantations and generate the reflection info on the fly, and none of the
+above will any longer be necessary.
+
+Subsequent use should be as expected.
+Note the meta-class style of "instantiating" the template::
+
+    >>>> import cppyy
+    >>>> cppyy.load_reflection_info("libTemplateDict.so")
+    >>>> std = cppyy.gbl.std
+    >>>> MyClass = cppyy.gbl.MyClass
+    >>>> v = std.vector(MyClass)()
+    >>>> v += [MyClass(1), MyClass(2), MyClass(3)]
+    >>>> for m in v:
+    ....     print m.m_i,
+    ....
+    1 2 3
+    >>>>
+
+Other templates work similarly.
+The arguments to the template instantiation can either be a string with the
+full list of arguments, or the explicit classes.
+The latter makes for easier code writing if the classes passed to the
+instantiation are themselves templates.
+
+
+The fast lane
+=============
+
+The following is an experimental feature of cppyy, and that makes it doubly
+experimental, so caveat emptor.
+With a slight modification of Reflex, it can provide function pointers for
+C++ methods, and hence allow PyPy to call those pointers directly, rather than
+calling C++ through a Reflex stub.
+This results in a rather significant speed-up.
+Mind you, the normal stub path is not exactly slow, so for now only use this
+out of curiosity or if you really need it.
+
+To install this patch of Reflex, locate the file genreflex-methptrgetter.patch
+in pypy/module/cppyy and apply it to the genreflex python scripts found in
+``$ROOTSYS/lib``::
+
+    $ cd $ROOTSYS/lib
+    $ patch -p2 < genreflex-methptrgetter.patch
+
+With this patch, ``genreflex`` will have grown the ``--with-methptrgetter``
+option.
+Use this option when running ``genreflex``, and add the
+``-Wno-pmf-conversions`` option to ``g++`` when compiling.
+The rest works the same way: the fast path will be used transparently (which
+also means that you can't actually find out whether it is in use, other than
+by running a micro-benchmark).
+
+
+CPython
+=======
+
+Most of the ideas in cppyy come originally from the `PyROOT`_ project.
+Although PyROOT does not support Reflex directly, it has an alter ego called
+"PyCintex" that, in a somewhat roundabout way, does.
+If you installed ROOT, rather than just Reflex, PyCintex should be available
+immediately if you add ``$ROOTSYS/lib`` to the ``PYTHONPATH`` environment
+variable.
+
+.. _`PyROOT`: http://root.cern.ch/drupal/content/pyroot
+
+There are a couple of minor differences between PyCintex and cppyy, most to do
+with naming.
+The one that you will run into directly, is that PyCintex uses a function
+called ``loadDictionary`` rather than ``load_reflection_info``.
+The reason for this is that Reflex calls the shared libraries that contain
+reflection info "dictionaries."
+However, in python, the name `dictionary` already has a well-defined meaning,
+so a more descriptive name was chosen for cppyy.
+In addition, PyCintex requires that the names of shared libraries so loaded
+start with "lib" in their name.
+The basic example above, rewritten for PyCintex thus goes like this::
+
+    $ python
+    >>> import PyCintex
+    >>> PyCintex.loadDictionary("libMyClassDict.so")
+    >>> myinst = PyCintex.gbl.MyClass(42)
+    >>> print myinst.GetMyInt()
+    42
+    >>> myinst.SetMyInt(33)
+    >>> print myinst.m_myint
+    33
+    >>> myinst.m_myint = 77
+    >>> print myinst.GetMyInt()
+    77
+    >>> help(PyCintex.gbl.MyClass)   # shows that normal python introspection works
+
+Other naming differences are such things as taking an address of an object.
+In PyCintex, this is done with ``AddressOf`` whereas in cppyy the choice was
+made to follow the naming as in ``ctypes`` and hence use ``addressof``
+(PyROOT/PyCintex predate ``ctypes`` by several years, and the ROOT project
+follows camel-case, hence the differences).
+
+Of course, this is python, so if any of the naming is not to your liking, all
+you have to do is provide a wrapper script that you import instead of
+importing the ``cppyy`` or ``PyCintex`` modules directly.
+In that wrapper script you can rename methods exactly the way you need it.
+
+In the cling world, all these differences will be resolved.
diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst
--- a/pypy/doc/extending.rst
+++ b/pypy/doc/extending.rst
@@ -23,6 +23,8 @@
 
 * Write them in RPython as mixedmodule_, using *rffi* as bindings.
 
+* Write them in C++ and bind them through Reflex_ (EXPERIMENTAL)
+
 .. _ctypes: #CTypes
 .. _\_ffi: #LibFFI
 .. _mixedmodule: #Mixed Modules
@@ -110,3 +112,34 @@
 
 XXX we should provide detailed docs about lltype and rffi, especially if we
     want people to follow that way.
+
+Reflex
+======
+
+This method is only experimental for now, and is being exercised on a branch,
+`reflex-support`_, so you will have to build PyPy yourself.
+The method works by using the `Reflex package`_ to provide reflection
+information of the C++ code, which is then used to automatically generate
+bindings at runtime, which can then be used from python.
+Full details are `available here`_.
+
+.. _`reflex-support`: cppyy.html
+.. _`Reflex package`: http://root.cern.ch/drupal/content/reflex
+.. _`available here`: cppyy.html
+
+Pros
+----
+
+If it works, it is mostly automatic, and hence easy in use.
+The bindings can make use of direct pointers, in which case the calls are
+very fast.
+
+Cons
+----
+
+C++ is a large language, and these bindings are not yet feature-complete.
+Although missing features should do no harm if you don't use them, if you do
+need a particular feature, it may be necessary to work around it in python
+or with a C++ helper function.
+Although Reflex works on various platforms, the bindings with PyPy have only
+been tested on Linux.
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -24,7 +24,8 @@
 translation.  Failing that, they will pick the most recent Visual Studio
 compiler they can find.  In addition, the target architecture
 (32 bits, 64 bits) is automatically selected.  A 32 bit build can only be built
-using a 32 bit Python and vice versa.
+using a 32 bit Python and vice versa. By default pypy is built using the 
+Multi-threaded DLL (/MD) runtime environment.
 
 **Note:** PyPy is currently not supported for 64 bit Windows, and translation
 will fail in this case.
@@ -102,10 +103,12 @@
 
 Download the source code of expat on sourceforge:
 http://sourceforge.net/projects/expat/ and extract it in the base
-directory.  Then open the project file ``expat.dsw`` with Visual
+directory.  Version 2.1.0 is known to pass tests. Then open the project 
+file ``expat.dsw`` with Visual
 Studio; follow the instruction for converting the project files,
-switch to the "Release" configuration, and build the solution (the
-``expat`` project is actually enough for pypy).
+switch to the "Release" configuration, reconfigure the runtime for 
+Multi-threaded DLL (/MD) and build the solution (the ``expat`` project 
+is actually enough for pypy).
 
 Then, copy the file ``win32\bin\release\libexpat.dll`` somewhere in
 your PATH.
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -98,6 +98,10 @@
     Collects the arguments of a function call.
 
     Instances should be considered immutable.
+
+    Some parts of this class are written in a slightly convoluted style to help
+    the JIT. It is really crucial to get this right, because Python's argument
+    semantics are complex, but calls occur everywhere.
     """
 
     ###  Construction  ###
@@ -184,7 +188,13 @@
         space = self.space
         keywords, values_w = space.view_as_kwargs(w_starstararg)
         if keywords is not None: # this path also taken for empty dicts
-            self._add_keywordargs_no_unwrapping(keywords, values_w)
+            if self.keywords is None:
+                self.keywords = keywords[:] # copy to make non-resizable
+                self.keywords_w = values_w[:]
+            else:
+                self._check_not_duplicate_kwargs(keywords, values_w)
+                self.keywords = self.keywords + keywords
+                self.keywords_w = self.keywords_w + values_w
             return not jit.isconstant(len(self.keywords))
         if space.isinstance_w(w_starstararg, space.w_dict):
             keys_w = space.unpackiterable(w_starstararg)
@@ -242,22 +252,16 @@
     @jit.look_inside_iff(lambda self, keywords, keywords_w:
             jit.isconstant(len(keywords) and
             jit.isconstant(self.keywords)))
-    def _add_keywordargs_no_unwrapping(self, keywords, keywords_w):
-        if self.keywords is None:
-            self.keywords = keywords[:] # copy to make non-resizable
-            self.keywords_w = keywords_w[:]
-        else:
-            # looks quadratic, but the JIT should remove all of it nicely.
-            # Also, all the lists should be small
-            for key in keywords:
-                for otherkey in self.keywords:
-                    if otherkey == key:
-                        raise operationerrfmt(self.space.w_TypeError,
-                                              "got multiple values "
-                                              "for keyword argument "
-                                              "'%s'", key)
-            self.keywords = self.keywords + keywords
-            self.keywords_w = self.keywords_w + keywords_w
+    def _check_not_duplicate_kwargs(self, keywords, keywords_w):
+        # looks quadratic, but the JIT should remove all of it nicely.
+        # Also, all the lists should be small
+        for key in keywords:
+            for otherkey in self.keywords:
+                if otherkey == key:
+                    raise operationerrfmt(self.space.w_TypeError,
+                                          "got multiple values "
+                                          "for keyword argument "
+                                          "'%s'", key)
 
     def fixedunpack(self, argcount):
         """The simplest argument parsing: get the 'argcount' arguments,
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -311,14 +311,19 @@
                     # produce compatible pycs.
                     if (self.space.isinstance_w(w_obj, self.space.w_unicode) and
                         self.space.isinstance_w(w_const, self.space.w_unicode)):
-                        unistr = self.space.unicode_w(w_const)
-                        if len(unistr) == 1:
-                            ch = ord(unistr[0])
-                        else:
-                            ch = 0
-                        if (ch > 0xFFFF or
-                            (MAXUNICODE == 0xFFFF and 0xD800 <= ch <= 0xDFFF)):
-                            return subs
+                        #unistr = self.space.unicode_w(w_const)
+                        #if len(unistr) == 1:
+                        #    ch = ord(unistr[0])
+                        #else:
+                        #    ch = 0
+                        #if (ch > 0xFFFF or
+                        #    (MAXUNICODE == 0xFFFF and 0xD800 <= ch <= 0xDFFF)):
+                        # --XXX-- for now we always disable optimization of
+                        # u'...'[constant] because the tests above are not
+                        # enough to fix issue5057 (CPython has the same
+                        # problem as of April 24, 2012).
+                        # See test_const_fold_unicode_subscr
+                        return subs
 
                     return ast.Const(w_const, subs.lineno, subs.col_offset)
 
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -910,7 +910,8 @@
         return "abc"[0]
         """
         counts = self.count_instructions(source)
-        assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
+        if 0:   # xxx later?
+            assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
 
         # getitem outside of the BMP should not be optimized
         source = """def f():
@@ -920,12 +921,20 @@
         assert counts == {ops.LOAD_CONST: 2, ops.BINARY_SUBSCR: 1,
                           ops.RETURN_VALUE: 1}
 
+        source = """def f():
+        return u"\U00012345abcdef"[3]
+        """
+        counts = self.count_instructions(source)
+        assert counts == {ops.LOAD_CONST: 2, ops.BINARY_SUBSCR: 1,
+                          ops.RETURN_VALUE: 1}
+
         monkeypatch.setattr(optimize, "MAXUNICODE", 0xFFFF)
         source = """def f():
         return "\uE01F"[0]
         """
         counts = self.count_instructions(source)
-        assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
+        if 0:   # xxx later?
+            assert counts == {ops.LOAD_CONST: 1, ops.RETURN_VALUE: 1}
         monkeypatch.undo()
 
         # getslice is not yet optimized.
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -51,7 +51,9 @@
     def __repr__(self):
         # return "function %s.%s" % (self.space, self.name)
         # maybe we want this shorter:
-        name = getattr(self, 'name', '?')
+        name = getattr(self, 'name', None)
+        if not isinstance(name, str):
+            name = '?'
         return "<%s %s>" % (self.__class__.__name__, name)
 
     def call_args(self, args):
diff --git a/pypy/jit/backend/llsupport/asmmemmgr.py b/pypy/jit/backend/llsupport/asmmemmgr.py
--- a/pypy/jit/backend/llsupport/asmmemmgr.py
+++ b/pypy/jit/backend/llsupport/asmmemmgr.py
@@ -277,6 +277,8 @@
             from pypy.jit.backend.hlinfo import highleveljitinfo
             if highleveljitinfo.sys_executable:
                 debug_print('SYS_EXECUTABLE', highleveljitinfo.sys_executable)
+            else:
+                debug_print('SYS_EXECUTABLE', '??')
             #
             HEX = '0123456789ABCDEF'
             dump = []
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -1656,15 +1656,21 @@
         else:
             # XXX hard-coded assumption: to go from an object to its class
             # we use the following algorithm:
-            #   - read the typeid from mem(locs[0]), i.e. at offset 0
-            #   - keep the lower 16 bits read there
-            #   - multiply by 4 and use it as an offset in type_info_group
-            #   - add 16 bytes, to go past the TYPE_INFO structure
+            #   - read the typeid from mem(locs[0]), i.e. at offset 0;
+            #     this is a complete word (N=4 bytes on 32-bit, N=8 on
+            #     64-bits)
+            #   - keep the lower half of what is read there (i.e.
+            #     truncate to an unsigned 'N / 2' bytes value)
+            #   - multiply by 4 (on 32-bits only) and use it as an
+            #     offset in type_info_group
+            #   - add 16/32 bytes, to go past the TYPE_INFO structure
             loc = locs[1]
             assert isinstance(loc, ImmedLoc)
             classptr = loc.value
             # here, we have to go back from 'classptr' to the value expected
-            # from reading the 16 bits in the object header
+            # from reading the half-word in the object header.  Note that
+            # this half-word is at offset 0 on a little-endian machine;
+            # it would be at offset 2 or 4 on a big-endian machine.
             from pypy.rpython.memory.gctypelayout import GCData
             sizeof_ti = rffi.sizeof(GCData.TYPE_INFO)
             type_info_group = llop.gc_get_type_info_group(llmemory.Address)
diff --git a/pypy/jit/metainterp/heapcache.py b/pypy/jit/metainterp/heapcache.py
--- a/pypy/jit/metainterp/heapcache.py
+++ b/pypy/jit/metainterp/heapcache.py
@@ -20,6 +20,7 @@
         self.dependencies = {}
         # contains frame boxes that are not virtualizables
         self.nonstandard_virtualizables = {}
+
         # heap cache
         # maps descrs to {from_box, to_box} dicts
         self.heap_cache = {}
@@ -29,6 +30,26 @@
         # cache the length of arrays
         self.length_cache = {}
 
+        # replace_box is called surprisingly often, therefore it's not efficient
+        # to go over all the dicts and fix them.
+        # instead, these two dicts are kept, and a replace_box adds an entry to
+        # each of them.
+        # every time one of the dicts heap_cache, heap_array_cache, length_cache
+        # is accessed, suitable indirections need to be performed
+
+        # this looks all very subtle, but in practice the patterns of
+        # replacements should not be that complex. Usually a box is replaced by
+        # a const, once. Also, if something goes wrong, the effect is that less
+        # caching than possible is done, which is not a huge problem.
+        self.input_indirections = {}
+        self.output_indirections = {}
+
+    def _input_indirection(self, box):
+        return self.input_indirections.get(box, box)
+
+    def _output_indirection(self, box):
+        return self.output_indirections.get(box, box)
+
     def invalidate_caches(self, opnum, descr, argboxes):
         self.mark_escaped(opnum, argboxes)
         self.clear_caches(opnum, descr, argboxes)
@@ -132,14 +153,16 @@
         self.arraylen_now_known(box, lengthbox)
 
     def getfield(self, box, descr):
+        box = self._input_indirection(box)
         d = self.heap_cache.get(descr, None)
         if d:
             tobox = d.get(box, None)
-            if tobox:
-                return tobox
+            return self._output_indirection(tobox)
         return None
 
     def getfield_now_known(self, box, descr, fieldbox):
+        box = self._input_indirection(box)
+        fieldbox = self._input_indirection(fieldbox)
         self.heap_cache.setdefault(descr, {})[box] = fieldbox
 
     def setfield(self, box, descr, fieldbox):
@@ -148,6 +171,8 @@
         self.heap_cache[descr] = new_d
 
     def _do_write_with_aliasing(self, d, box, fieldbox):
+        box = self._input_indirection(box)
+        fieldbox = self._input_indirection(fieldbox)
         # slightly subtle logic here
         # a write to an arbitrary box, all other boxes can alias this one
         if not d or box not in self.new_boxes:
@@ -166,6 +191,7 @@
         return new_d
 
     def getarrayitem(self, box, descr, indexbox):
+        box = self._input_indirection(box)
         if not isinstance(indexbox, ConstInt):
             return
         index = indexbox.getint()
@@ -173,9 +199,11 @@
         if cache:
             indexcache = cache.get(index, None)
             if indexcache is not None:
-                return indexcache.get(box, None)
+                return self._output_indirection(indexcache.get(box, None))
 
     def getarrayitem_now_known(self, box, descr, indexbox, valuebox):
+        box = self._input_indirection(box)
+        valuebox = self._input_indirection(valuebox)
         if not isinstance(indexbox, ConstInt):
             return
         index = indexbox.getint()
@@ -198,25 +226,13 @@
         cache[index] = self._do_write_with_aliasing(indexcache, box, valuebox)
 
     def arraylen(self, box):
-        return self.length_cache.get(box, None)
+        box = self._input_indirection(box)
+        return self._output_indirection(self.length_cache.get(box, None))
 
     def arraylen_now_known(self, box, lengthbox):
-        self.length_cache[box] = lengthbox
-
-    def _replace_box(self, d, oldbox, newbox):
-        new_d = {}
-        for frombox, tobox in d.iteritems():
-            if frombox is oldbox:
-                frombox = newbox
-            if tobox is oldbox:
-                tobox = newbox
-            new_d[frombox] = tobox
-        return new_d
+        box = self._input_indirection(box)
+        self.length_cache[box] = self._input_indirection(lengthbox)
 
     def replace_box(self, oldbox, newbox):
-        for descr, d in self.heap_cache.iteritems():
-            self.heap_cache[descr] = self._replace_box(d, oldbox, newbox)
-        for descr, d in self.heap_array_cache.iteritems():
-            for index, cache in d.iteritems():
-                d[index] = self._replace_box(cache, oldbox, newbox)
-        self.length_cache = self._replace_box(self.length_cache, oldbox, newbox)
+        self.input_indirections[self._output_indirection(newbox)] = self._input_indirection(oldbox)
+        self.output_indirections[self._input_indirection(oldbox)] = self._output_indirection(newbox)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -7,7 +7,7 @@
 import pypy.jit.metainterp.optimizeopt.optimizer as optimizeopt
 import pypy.jit.metainterp.optimizeopt.virtualize as virtualize
 from pypy.jit.metainterp.optimize import InvalidLoop
-from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt
+from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt, get_const_ptr_for_string
 from pypy.jit.metainterp import executor, compile, resume, history
 from pypy.jit.metainterp.resoperation import rop, opname, ResOperation
 from pypy.rlib.rarithmetic import LONG_BIT
@@ -5067,6 +5067,25 @@
         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_call_pure_vstring_const(self):
+        ops = """
+        []
+        p0 = newstr(3)
+        strsetitem(p0, 0, 97)
+        strsetitem(p0, 1, 98)
+        strsetitem(p0, 2, 99)
+        i0 = call_pure(123, p0, descr=nonwritedescr)
+        finish(i0)
+        """
+        expected = """
+        []
+        finish(5)
+        """
+        call_pure_results = {
+            (ConstInt(123), get_const_ptr_for_string("abc"),): ConstInt(5),
+        }
+        self.optimize_loop(ops, expected, call_pure_results)
+
 
 class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
     pass
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1223,7 +1223,7 @@
     def run_one_step(self):
         # Execute the frame forward.  This method contains a loop that leaves
         # whenever the 'opcode_implementations' (which is one of the 'opimpl_'
-        # methods) returns True.  This is the case when the current frame
+        # methods) raises ChangeFrame.  This is the case when the current frame
         # changes, due to a call or a return.
         try:
             staticdata = self.metainterp.staticdata
diff --git a/pypy/jit/metainterp/test/test_heapcache.py b/pypy/jit/metainterp/test/test_heapcache.py
--- a/pypy/jit/metainterp/test/test_heapcache.py
+++ b/pypy/jit/metainterp/test/test_heapcache.py
@@ -2,12 +2,14 @@
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.history import ConstInt
 
-box1 = object()
-box2 = object()
-box3 = object()
-box4 = object()
+box1 = "box1"
+box2 = "box2"
+box3 = "box3"
+box4 = "box4"
+box5 = "box5"
 lengthbox1 = object()
 lengthbox2 = object()
+lengthbox3 = object()
 descr1 = object()
 descr2 = object()
 descr3 = object()
@@ -276,11 +278,43 @@
         h.setfield(box1, descr2, box3)
         h.setfield(box2, descr3, box3)
         h.replace_box(box1, box4)
-        assert h.getfield(box1, descr1) is None
-        assert h.getfield(box1, descr2) is None
         assert h.getfield(box4, descr1) is box2
         assert h.getfield(box4, descr2) is box3
         assert h.getfield(box2, descr3) is box3
+        h.setfield(box4, descr1, box3)
+        assert h.getfield(box4, descr1) is box3
+
+        h = HeapCache()
+        h.setfield(box1, descr1, box2)
+        h.setfield(box1, descr2, box3)
+        h.setfield(box2, descr3, box3)
+        h.replace_box(box3, box4)
+        assert h.getfield(box1, descr1) is box2
+        assert h.getfield(box1, descr2) is box4
+        assert h.getfield(box2, descr3) is box4
+
+    def test_replace_box_twice(self):
+        h = HeapCache()
+        h.setfield(box1, descr1, box2)
+        h.setfield(box1, descr2, box3)
+        h.setfield(box2, descr3, box3)
+        h.replace_box(box1, box4)
+        h.replace_box(box4, box5)
+        assert h.getfield(box5, descr1) is box2
+        assert h.getfield(box5, descr2) is box3
+        assert h.getfield(box2, descr3) is box3
+        h.setfield(box5, descr1, box3)
+        assert h.getfield(box4, descr1) is box3
+
+        h = HeapCache()
+        h.setfield(box1, descr1, box2)
+        h.setfield(box1, descr2, box3)
+        h.setfield(box2, descr3, box3)
+        h.replace_box(box3, box4)
+        h.replace_box(box4, box5)
+        assert h.getfield(box1, descr1) is box2
+        assert h.getfield(box1, descr2) is box5
+        assert h.getfield(box2, descr3) is box5
 
     def test_replace_box_array(self):
         h = HeapCache()
@@ -291,9 +325,6 @@
         h.setarrayitem(box3, descr2, index2, box1)
         h.setarrayitem(box2, descr3, index2, box3)
         h.replace_box(box1, box4)
-        assert h.getarrayitem(box1, descr1, index1) is None
-        assert h.getarrayitem(box1, descr2, index1) is None
-        assert h.arraylen(box1) is None
         assert h.arraylen(box4) is lengthbox1
         assert h.getarrayitem(box4, descr1, index1) is box2
         assert h.getarrayitem(box4, descr2, index1) is box3
@@ -304,6 +335,27 @@
         h.replace_box(lengthbox1, lengthbox2)
         assert h.arraylen(box4) is lengthbox2
 
+    def test_replace_box_array_twice(self):
+        h = HeapCache()
+        h.setarrayitem(box1, descr1, index1, box2)
+        h.setarrayitem(box1, descr2, index1, box3)
+        h.arraylen_now_known(box1, lengthbox1)
+        h.setarrayitem(box2, descr1, index2, box1)
+        h.setarrayitem(box3, descr2, index2, box1)
+        h.setarrayitem(box2, descr3, index2, box3)
+        h.replace_box(box1, box4)
+        h.replace_box(box4, box5)
+        assert h.arraylen(box4) is lengthbox1
+        assert h.getarrayitem(box5, descr1, index1) is box2
+        assert h.getarrayitem(box5, descr2, index1) is box3
+        assert h.getarrayitem(box2, descr1, index2) is box5
+        assert h.getarrayitem(box3, descr2, index2) is box5
+        assert h.getarrayitem(box2, descr3, index2) is box3
+
+        h.replace_box(lengthbox1, lengthbox2)
+        h.replace_box(lengthbox2, lengthbox3)
+        assert h.arraylen(box4) is lengthbox3
+
     def test_ll_arraycopy(self):
         h = HeapCache()
         h.new_array(box1, lengthbox1)
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -345,9 +345,13 @@
 
     def add(self, w_iobase):
         assert w_iobase.streamholder is None
-        holder = StreamHolder(w_iobase)
-        w_iobase.streamholder = holder
-        self.streams[holder] = None
+        if rweakref.has_weakref_support():
+            holder = StreamHolder(w_iobase)
+            w_iobase.streamholder = holder
+            self.streams[holder] = None
+        #else:
+        #   no support for weakrefs, so ignore and we
+        #   will not get autoflushing
 
     def remove(self, w_iobase):
         holder = w_iobase.streamholder
diff --git a/pypy/module/_multiprocessing/test/test_connection.py b/pypy/module/_multiprocessing/test/test_connection.py
--- a/pypy/module/_multiprocessing/test/test_connection.py
+++ b/pypy/module/_multiprocessing/test/test_connection.py
@@ -157,13 +157,15 @@
         raises(IOError, _multiprocessing.Connection, -15)
 
     def test_byte_order(self):
+        import socket
+        if not 'fromfd' in dir(socket):
+            skip('No fromfd in socket')
         # The exact format of net strings (length in network byte
         # order) is important for interoperation with others
         # implementations.
         rhandle, whandle = self.make_pair()
         whandle.send_bytes("abc")
         whandle.send_bytes("defg")
-        import socket
         sock = socket.fromfd(rhandle.fileno(),
                              socket.AF_INET, socket.SOCK_STREAM)
         data1 = sock.recv(7)
diff --git a/pypy/module/_winreg/test/test_winreg.py b/pypy/module/_winreg/test/test_winreg.py
--- a/pypy/module/_winreg/test/test_winreg.py
+++ b/pypy/module/_winreg/test/test_winreg.py
@@ -198,7 +198,10 @@
         import nt
         r = ExpandEnvironmentStrings(u"%windir%\\test")
         assert isinstance(r, unicode)
-        assert r == nt.environ["WINDIR"] + "\\test"
+        if 'WINDIR' in nt.environ.keys():
+            assert r == nt.environ["WINDIR"] + "\\test"
+        else:
+            assert r == nt.environ["windir"] + "\\test"
 
     def test_long_key(self):
         from _winreg import (
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -102,8 +102,8 @@
 """.split()
 for name in constant_names:
     setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))
-udir.join('pypy_decl.h').write("/* Will be filled later */")
-udir.join('pypy_macros.h').write("/* Will be filled later */")
+udir.join('pypy_decl.h').write("/* Will be filled later */\n")
+udir.join('pypy_macros.h').write("/* Will be filled later */\n")
 globals().update(rffi_platform.configure(CConfig_constants))
 
 def copy_header_files(dstdir):
@@ -924,12 +924,12 @@
                                source_dir / "pyerrors.c",
                                source_dir / "modsupport.c",
                                source_dir / "getargs.c",
+                               source_dir / "abstract.c",
                                source_dir / "unicodeobject.c",
                                source_dir / "mysnprintf.c",
                                source_dir / "pythonrun.c",
                                source_dir / "sysmodule.c",
                                source_dir / "bufferobject.c",
-                               source_dir / "object.c",
                                source_dir / "cobject.c",
                                source_dir / "structseq.c",
                                source_dir / "capsule.c",
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -38,10 +38,19 @@
 	PyObject_VAR_HEAD
 } PyVarObject;
 
+#ifndef PYPY_DEBUG_REFCOUNT
 #define Py_INCREF(ob)   (Py_IncRef((PyObject *)ob))
 #define Py_DECREF(ob)   (Py_DecRef((PyObject *)ob))
 #define Py_XINCREF(ob)  (Py_IncRef((PyObject *)ob))
 #define Py_XDECREF(ob)  (Py_DecRef((PyObject *)ob))
+#else
+#define Py_INCREF(ob)   (((PyObject *)ob)->ob_refcnt++)
+#define Py_DECREF(ob)  ((((PyObject *)ob)->ob_refcnt > 1) ? \
+			((PyObject *)ob)->ob_refcnt-- : (Py_DecRef((PyObject *)ob)))
+
+#define Py_XINCREF(op) do { if ((op) == NULL) ; else Py_INCREF(op); } while (0)
+#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
+#endif
 
 #define Py_CLEAR(op)				\
         do {                            	\
diff --git a/pypy/module/cpyext/include/pyerrors.h b/pypy/module/cpyext/include/pyerrors.h
--- a/pypy/module/cpyext/include/pyerrors.h
+++ b/pypy/module/cpyext/include/pyerrors.h
@@ -29,6 +29,10 @@
 # define vsnprintf _vsnprintf
 #endif
 
+#include <stdarg.h>
+PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const  char  *format, ...);
+PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pypy/module/cpyext/include/stringobject.h b/pypy/module/cpyext/include/stringobject.h
--- a/pypy/module/cpyext/include/stringobject.h
+++ b/pypy/module/cpyext/include/stringobject.h
@@ -7,8 +7,6 @@
 extern "C" {
 #endif
 
-int PyOS_snprintf(char *str, size_t size, const  char  *format, ...);
-
 #define PyString_GET_SIZE(op) PyString_Size(op)
 #define PyString_AS_STRING(op) PyString_AsString(op)
 
diff --git a/pypy/module/cpyext/iterator.py b/pypy/module/cpyext/iterator.py
--- a/pypy/module/cpyext/iterator.py
+++ b/pypy/module/cpyext/iterator.py
@@ -22,7 +22,7 @@
     cannot be iterated."""
     return space.iter(w_obj)
 
- at cpython_api([PyObject], PyObject, error=CANNOT_FAIL)
+ at cpython_api([PyObject], PyObject)
 def PyIter_Next(space, w_obj):
     """Return the next value from the iteration o.  If the object is an
     iterator, this retrieves the next value from the iteration, and returns
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -110,6 +110,16 @@
     space.call_method(w_list, "reverse")
     return 0
 
+ at cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
+def PyList_GetSlice(space, w_list, low, high):
+    """Return a list of the objects in list containing the objects between low
+    and high.  Return NULL and set an exception if unsuccessful.  Analogous
+    to list[low:high].  Negative indices, as when slicing from Python, are not
+    supported."""
+    w_start = space.wrap(low)
+    w_stop = space.wrap(high)
+    return space.getslice(w_list, w_start, w_stop)
+
 @cpython_api([PyObject, Py_ssize_t, Py_ssize_t, PyObject], rffi.INT_real, error=-1)
 def PyList_SetSlice(space, w_list, low, high, w_sequence):
     """Set the slice of list between low and high to the contents of
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -390,6 +390,15 @@
     This is the equivalent of the Python expression hash(o)."""
     return space.int_w(space.hash(w_obj))
 
+ at cpython_api([PyObject], lltype.Signed, error=-1)
+def PyObject_HashNotImplemented(space, o):
+    """Set a TypeError indicating that type(o) is not hashable and return -1.
+    This function receives special treatment when stored in a tp_hash slot,
+    allowing a type to explicitly indicate to the interpreter that it is not
+    hashable.
+    """
+    raise OperationError(space.w_TypeError, space.wrap("unhashable type"))
+
 @cpython_api([PyObject], PyObject)
 def PyObject_Dir(space, w_o):
     """This is equivalent to the Python expression dir(o), returning a (possibly
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -313,7 +313,10 @@
     """This function simulates the effect of a SIGINT signal arriving --- the
     next time PyErr_CheckSignals() is called, KeyboardInterrupt will be raised.
     It may be called without holding the interpreter lock."""
-    space.check_signal_action.set_interrupt()
+    if space.check_signal_action is not None:
+        space.check_signal_action.set_interrupt()
+    #else:
+    #   no 'signal' module present, ignore...  We can't return an error here
 
 @cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
 def PyErr_GetExcInfo(space, ptype, pvalue, ptraceback):
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -7,7 +7,7 @@
     cpython_api, generic_cpy_call, PyObject, Py_ssize_t)
 from pypy.module.cpyext.typeobjectdefs import (
     unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
-    getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc,
+    getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry,
     ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
     cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
     readbufferproc)
@@ -60,6 +60,16 @@
     args_w = space.fixedview(w_args)
     return generic_cpy_call(space, func_binary, w_self, args_w[0])
 
+def wrap_inquirypred(space, w_self, w_args, func):
+    func_inquiry = rffi.cast(inquiry, func)
+    check_num_args(space, w_args, 0)
+    args_w = space.fixedview(w_args)
+    res = generic_cpy_call(space, func_inquiry, w_self)
+    res = rffi.cast(lltype.Signed, res)
+    if res == -1:
+        space.fromcache(State).check_and_raise_exception()
+    return space.wrap(bool(res))
+
 def wrap_getattr(space, w_self, w_args, func):
     func_target = rffi.cast(getattrfunc, func)
     check_num_args(space, w_args, 1)
diff --git a/pypy/module/cpyext/src/bufferobject.c b/pypy/module/cpyext/src/bufferobject.c
--- a/pypy/module/cpyext/src/bufferobject.c
+++ b/pypy/module/cpyext/src/bufferobject.c
@@ -34,13 +34,13 @@
             proc = bp->bf_getreadbuffer;
         else if ((buffer_type == WRITE_BUFFER) ||
             (buffer_type == ANY_BUFFER))
-                proc = (readbufferproc)bp->bf_getwritebuffer;
+	    proc = (readbufferproc)bp->bf_getwritebuffer;
         else if (buffer_type == CHAR_BUFFER) {
             if (!PyType_HasFeature(self->ob_type,
-                Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
-                PyErr_SetString(PyExc_TypeError,
-                    "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
-                return 0;
+                        Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
+            PyErr_SetString(PyExc_TypeError,
+                "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
+            return 0;
             }
             proc = (readbufferproc)bp->bf_getcharbuffer;
         }
@@ -86,18 +86,18 @@
 
 static PyObject *
 buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
-           int readonly)
+                   int readonly)
 {
     PyBufferObject * b;
 
     if (size < 0 && size != Py_END_OF_BUFFER) {
         PyErr_SetString(PyExc_ValueError,
-                "size must be zero or positive");
+                        "size must be zero or positive");
         return NULL;
     }
     if (offset < 0) {
         PyErr_SetString(PyExc_ValueError,
-                "offset must be zero or positive");
+                        "offset must be zero or positive");
         return NULL;
     }
 
@@ -121,7 +121,7 @@
 {
     if (offset < 0) {
         PyErr_SetString(PyExc_ValueError,
-                "offset must be zero or positive");
+                        "offset must be zero or positive");
         return NULL;
     }
     if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
@@ -193,7 +193,7 @@
 
     if (size < 0) {
         PyErr_SetString(PyExc_ValueError,
-                "size must be zero or positive");
+                        "size must be zero or positive");
         return NULL;
     }
     if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
@@ -225,9 +225,11 @@
     Py_ssize_t offset = 0;
     Py_ssize_t size = Py_END_OF_BUFFER;
 
-    /*if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
-        return NULL;*/
-    
+    /*
+     * if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
+     *   return NULL;
+     */
+
     if (!_PyArg_NoKeywords("buffer()", kw))
         return NULL;
 
@@ -278,12 +280,11 @@
     const char *status = self->b_readonly ? "read-only" : "read-write";
 
     if ( self->b_base == NULL )
-        return PyUnicode_FromFormat(
-            "<%s buffer ptr %p, size %zd at %p>",
-            status,
-            self->b_ptr,
-            self->b_size,
-            self);
+        return PyUnicode_FromFormat("<%s buffer ptr %p, size %zd at %p>",
+                                   status,
+                                   self->b_ptr,
+                                   self->b_size,
+                                   self);
     else
         return PyUnicode_FromFormat(
             "<%s buffer for %p, size %zd, offset %zd at %p>",
@@ -316,7 +317,7 @@
     if ( !self->b_readonly )
     {
         PyErr_SetString(PyExc_TypeError,
-                "writable buffers are not hashable");
+                        "writable buffers are not hashable");
         return -1;
     }
 
@@ -376,13 +377,13 @@
     {
         /* ### use a different exception type/message? */
         PyErr_SetString(PyExc_TypeError,
-                "single-segment buffer object expected");
+                        "single-segment buffer object expected");
         return NULL;
     }
 
-     if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
-         return NULL;
- 
+    if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
+        return NULL;
+
     /* optimize special case */
     if ( size == 0 )
     {
@@ -395,12 +396,12 @@
 
     assert(count <= PY_SIZE_MAX - size);
 
-     ob = PyString_FromStringAndSize(NULL, size + count);
+    ob = PyString_FromStringAndSize(NULL, size + count);
     if ( ob == NULL )
         return NULL;
-     p = PyString_AS_STRING(ob);
-     memcpy(p, ptr1, size);
-     memcpy(p + size, ptr2, count);
+    p = PyString_AS_STRING(ob);
+    memcpy(p, ptr1, size);
+    memcpy(p + size, ptr2, count);
 
     /* there is an extra byte in the string object, so this is safe */
     p[size + count] = '\0';
@@ -471,7 +472,7 @@
     if ( right < left )
         right = left;
     return PyString_FromStringAndSize((char *)ptr + left,
-                      right - left);
+                                      right - left);
 }
 
 static PyObject *
@@ -479,10 +480,9 @@
 {
     void *p;
     Py_ssize_t size;
-    
+
     if (!get_buf(self, &p, &size, ANY_BUFFER))
         return NULL;
-    
     if (PyIndex_Check(item)) {
         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
@@ -495,7 +495,7 @@
         Py_ssize_t start, stop, step, slicelength, cur, i;
 
         if (PySlice_GetIndicesEx((PySliceObject*)item, size,
-                 &start, &stop, &step, &slicelength) < 0) {
+                         &start, &stop, &step, &slicelength) < 0) {
             return NULL;
         }
 
@@ -503,7 +503,7 @@
             return PyString_FromStringAndSize("", 0);
         else if (step == 1)
             return PyString_FromStringAndSize((char *)p + start,
-                              stop - start);
+                                              stop - start);
         else {
             PyObject *result;
             char *source_buf = (char *)p;
@@ -518,14 +518,14 @@
             }
 
             result = PyString_FromStringAndSize(result_buf,
-                                slicelength);
+                                                slicelength);
             PyMem_Free(result_buf);
             return result;
         }
     }
     else {
         PyErr_SetString(PyExc_TypeError,
-                "sequence index must be integer");
+                        "sequence index must be integer");
         return NULL;
     }
 }
@@ -540,7 +540,7 @@
 
     if ( self->b_readonly ) {
         PyErr_SetString(PyExc_TypeError,
-                "buffer is read-only");
+                        "buffer is read-only");
         return -1;
     }
 
@@ -549,7 +549,7 @@
 
     if (idx < 0 || idx >= size) {
         PyErr_SetString(PyExc_IndexError,
-                "buffer assignment index out of range");
+                        "buffer assignment index out of range");
         return -1;
     }
 
@@ -565,7 +565,7 @@
     {
         /* ### use a different exception type/message? */
         PyErr_SetString(PyExc_TypeError,
-                "single-segment buffer object expected");
+                        "single-segment buffer object expected");
         return -1;
     }
 
@@ -573,7 +573,7 @@
         return -1;
     if ( count != 1 ) {
         PyErr_SetString(PyExc_TypeError,
-                "right operand must be a single byte");
+                        "right operand must be a single byte");
         return -1;
     }
 
@@ -592,7 +592,7 @@
 
     if ( self->b_readonly ) {
         PyErr_SetString(PyExc_TypeError,
-                "buffer is read-only");
+                        "buffer is read-only");
         return -1;
     }
 
@@ -608,7 +608,7 @@
     {
         /* ### use a different exception type/message? */
         PyErr_SetString(PyExc_TypeError,
-                "single-segment buffer object expected");
+                        "single-segment buffer object expected");
         return -1;
     }
     if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
@@ -649,7 +649,7 @@
 
     if ( self->b_readonly ) {
         PyErr_SetString(PyExc_TypeError,
-                "buffer is read-only");
+                        "buffer is read-only");
         return -1;
     }
 
@@ -665,12 +665,11 @@
     {
         /* ### use a different exception type/message? */
         PyErr_SetString(PyExc_TypeError,
-                "single-segment buffer object expected");
+                        "single-segment buffer object expected");
         return -1;
     }
     if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
         return -1;
-    
     if (PyIndex_Check(item)) {
         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
@@ -681,9 +680,9 @@
     }
     else if (PySlice_Check(item)) {
         Py_ssize_t start, stop, step, slicelength;
-        
+
         if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
-                &start, &stop, &step, &slicelength) < 0)
+                        &start, &stop, &step, &slicelength) < 0)
             return -1;
 
         if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
@@ -704,7 +703,7 @@
         }
         else {
             Py_ssize_t cur, i;
-            
+
             for (cur = start, i = 0; i < slicelength;
                  cur += step, i++) {
                 ((char *)ptr1)[cur] = ((char *)ptr2)[i];
@@ -714,7 +713,7 @@
         }
     } else {
         PyErr_SetString(PyExc_TypeError,
-                "buffer indices must be integers");
+                        "buffer indices must be integers");
         return -1;
     }
 }
@@ -727,7 +726,7 @@
     Py_ssize_t size;
     if ( idx != 0 ) {
         PyErr_SetString(PyExc_SystemError,
-                "accessing non-existent buffer segment");
+                        "accessing non-existent buffer segment");
         return -1;
     }
     if (!get_buf(self, pp, &size, READ_BUFFER))
@@ -748,7 +747,7 @@
 
     if ( idx != 0 ) {
         PyErr_SetString(PyExc_SystemError,
-                "accessing non-existent buffer segment");
+                        "accessing non-existent buffer segment");
         return -1;
     }
     if (!get_buf(self, pp, &size, WRITE_BUFFER))
@@ -775,7 +774,7 @@
     Py_ssize_t size;
     if ( idx != 0 ) {
         PyErr_SetString(PyExc_SystemError,
-                "accessing non-existent buffer segment");
+                        "accessing non-existent buffer segment");
         return -1;
     }
     if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
@@ -813,44 +812,42 @@
 };
 
 PyTypeObject PyBuffer_Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,
+    PyVarObject_HEAD_INIT(NULL, 0)
     "buffer",
     sizeof(PyBufferObject),
     0,
-    (destructor)buffer_dealloc,   /* tp_dealloc */
-    0,                            /* tp_print */
-    0,                            /* tp_getattr */
-    0,                            /* tp_setattr */
-    (cmpfunc)buffer_compare,      /* tp_compare */
-    (reprfunc)buffer_repr,        /* tp_repr */
-    0,                            /* tp_as_number */
-    &buffer_as_sequence,          /* tp_as_sequence */
-    &buffer_as_mapping,           /* tp_as_mapping */
-    (hashfunc)buffer_hash,        /* tp_hash */
-    0,                            /* tp_call */
-    (reprfunc)buffer_str,         /* tp_str */
-    PyObject_GenericGetAttr,      /* tp_getattro */
-    0,                            /* tp_setattro */
-    &buffer_as_buffer,            /* tp_as_buffer */
+    (destructor)buffer_dealloc,                 /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    (cmpfunc)buffer_compare,                    /* tp_compare */
+    (reprfunc)buffer_repr,                      /* tp_repr */
+    0,                                          /* tp_as_number */
+    &buffer_as_sequence,                        /* tp_as_sequence */
+    &buffer_as_mapping,                         /* tp_as_mapping */
+    (hashfunc)buffer_hash,                      /* tp_hash */
+    0,                                          /* tp_call */
+    (reprfunc)buffer_str,                       /* tp_str */
+    PyObject_GenericGetAttr,                    /* tp_getattro */
+    0,                                          /* tp_setattro */
+    &buffer_as_buffer,                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
-    buffer_doc,                   /* tp_doc */
-    0,                            /* tp_traverse */
-    0,                            /* tp_clear */
-    0,                            /* tp_richcompare */
-    0,                            /* tp_weaklistoffset */
-    0,                            /* tp_iter */
-    0,                            /* tp_iternext */
-    0,                            /* tp_methods */    
-    0,                            /* tp_members */
-    0,                            /* tp_getset */
-    0,                            /* tp_base */
-    0,                            /* tp_dict */
-    0,                            /* tp_descr_get */
-    0,                            /* tp_descr_set */
-    0,                            /* tp_dictoffset */
-    0,                            /* tp_init */
-    0,                            /* tp_alloc */
-    buffer_new,                   /* tp_new */
+    buffer_doc,                                 /* tp_doc */
+    0,                                          /* tp_traverse */
+    0,                                          /* tp_clear */
+    0,                                          /* tp_richcompare */
+    0,                                          /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+    0,                                          /* tp_methods */
+    0,                                          /* tp_members */
+    0,                                          /* tp_getset */
+    0,                                          /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    0,                                          /* tp_init */
+    0,                                          /* tp_alloc */
+    buffer_new,                                 /* tp_new */
 };
-
diff --git a/pypy/module/cpyext/src/cobject.c b/pypy/module/cpyext/src/cobject.c
--- a/pypy/module/cpyext/src/cobject.c
+++ b/pypy/module/cpyext/src/cobject.c
@@ -50,6 +50,10 @@
 PyCObject_AsVoidPtr(PyObject *self)
 {
     if (self) {
+        if (PyCapsule_CheckExact(self)) {
+            const char *name = PyCapsule_GetName(self);
+            return (void *)PyCapsule_GetPointer(self, name);
+        }
         if (self->ob_type == &PyCObject_Type)
             return ((PyCObject *)self)->cobject;
         PyErr_SetString(PyExc_TypeError,
diff --git a/pypy/module/cpyext/src/getargs.c b/pypy/module/cpyext/src/getargs.c
--- a/pypy/module/cpyext/src/getargs.c
+++ b/pypy/module/cpyext/src/getargs.c
@@ -7,349 +7,348 @@
 
 
 #ifdef __cplusplus
-extern "C" { 
+extern "C" {
 #endif
-
 int PyArg_Parse(PyObject *, const char *, ...);
 int PyArg_ParseTuple(PyObject *, const char *, ...);
 int PyArg_VaParse(PyObject *, const char *, va_list);
 
 int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *,
-				const char *, char **, ...);
+                                const char *, char **, ...);
 int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
-				const char *, char **, va_list);
+                                const char *, char **, va_list);
 
 
 #define FLAG_COMPAT 1
 #define FLAG_SIZE_T 2
 
-typedef int (*destr_t)(PyObject *, void *);
-
-
-/* Keep track of "objects" that have been allocated or initialized and
-   which will need to be deallocated or cleaned up somehow if overall
-   parsing fails.
-*/
-typedef struct {
-  void *item;
-  destr_t destructor;
-} freelistentry_t;
-
-typedef struct {
-  int first_available;
-  freelistentry_t *entries;
-} freelist_t;
-
 
 /* Forward */
 static int vgetargs1(PyObject *, const char *, va_list *, int);
 static void seterror(int, const char *, int *, const char *, const char *);
-static char *convertitem(PyObject *, const char **, va_list *, int, int *, 
-                         char *, size_t, freelist_t *);
+static char *convertitem(PyObject *, const char **, va_list *, int, int *,
+                         char *, size_t, PyObject **);
 static char *converttuple(PyObject *, const char **, va_list *, int,
-			  int *, char *, size_t, int, freelist_t *);
+                          int *, char *, size_t, int, PyObject **);
 static char *convertsimple(PyObject *, const char **, va_list *, int, char *,
-			   size_t, freelist_t *);
+                           size_t, PyObject **);
 static Py_ssize_t convertbuffer(PyObject *, void **p, char **);
 static int getbuffer(PyObject *, Py_buffer *, char**);
 
 static int vgetargskeywords(PyObject *, PyObject *,
-			    const char *, char **, va_list *, int);
+                            const char *, char **, va_list *, int);
 static char *skipitem(const char **, va_list *, int);
 
 int
 PyArg_Parse(PyObject *args, const char *format, ...)
 {
-	int retval;
-	va_list va;
-	
-	va_start(va, format);
-	retval = vgetargs1(args, format, &va, FLAG_COMPAT);
-	va_end(va);
-	return retval;
+    int retval;
+    va_list va;
+
+    va_start(va, format);
+    retval = vgetargs1(args, format, &va, FLAG_COMPAT);
+    va_end(va);
+    return retval;
 }
 
 int
 _PyArg_Parse_SizeT(PyObject *args, char *format, ...)
 {
-	int retval;
-	va_list va;
-	
-	va_start(va, format);
-	retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T);
-	va_end(va);
-	return retval;
+    int retval;
+    va_list va;
+
+    va_start(va, format);
+    retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T);
+    va_end(va);
+    return retval;
 }
 
 
 int
 PyArg_ParseTuple(PyObject *args, const char *format, ...)
 {
-	int retval;
-	va_list va;
-	
-	va_start(va, format);
-	retval = vgetargs1(args, format, &va, 0);
-	va_end(va);
-	return retval;
+    int retval;
+    va_list va;
+
+    va_start(va, format);
+    retval = vgetargs1(args, format, &va, 0);
+    va_end(va);
+    return retval;
 }
 
 int
 _PyArg_ParseTuple_SizeT(PyObject *args, char *format, ...)
 {
-	int retval;
-	va_list va;
-	
-	va_start(va, format);
-	retval = vgetargs1(args, format, &va, FLAG_SIZE_T);
-	va_end(va);
-	return retval;
+    int retval;
+    va_list va;
+
+    va_start(va, format);
+    retval = vgetargs1(args, format, &va, FLAG_SIZE_T);
+    va_end(va);
+    return retval;
 }
 
 
 int
 PyArg_VaParse(PyObject *args, const char *format, va_list va)
 {
-	va_list lva;
+    va_list lva;
 
 #ifdef VA_LIST_IS_ARRAY
-	memcpy(lva, va, sizeof(va_list));
+    memcpy(lva, va, sizeof(va_list));
 #else
 #ifdef __va_copy
-	__va_copy(lva, va);
+    __va_copy(lva, va);
 #else
-	lva = va;
+    lva = va;
 #endif
 #endif
 
-	return vgetargs1(args, format, &lva, 0);
+    return vgetargs1(args, format, &lva, 0);
 }
 
 int
 _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va)
 {
-	va_list lva;
+    va_list lva;
 
 #ifdef VA_LIST_IS_ARRAY
-	memcpy(lva, va, sizeof(va_list));
+    memcpy(lva, va, sizeof(va_list));
 #else
 #ifdef __va_copy
-	__va_copy(lva, va);
+    __va_copy(lva, va);
 #else
-	lva = va;
+    lva = va;
 #endif
 #endif
 
-	return vgetargs1(args, format, &lva, FLAG_SIZE_T);
+    return vgetargs1(args, format, &lva, FLAG_SIZE_T);
 }
 
 
 /* Handle cleanup of allocated memory in case of exception */
 
+#define GETARGS_CAPSULE_NAME_CLEANUP_PTR "getargs.cleanup_ptr"
+#define GETARGS_CAPSULE_NAME_CLEANUP_BUFFER "getargs.cleanup_buffer"
+
+static void
+cleanup_ptr(PyObject *self)
+{
+    void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR);
+    if (ptr) {
+      PyMem_FREE(ptr);
+    }
+}
+
+static void
+cleanup_buffer(PyObject *self)
+{
+    Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER);
+    if (ptr) {
+        PyBuffer_Release(ptr);
+    }
+}
+
 static int
-cleanup_ptr(PyObject *self, void *ptr)
+addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr)
 {
-    if (ptr) {
-        PyMem_FREE(ptr);
+    PyObject *cobj;
+    const char *name;
+
+    if (!*freelist) {
+        *freelist = PyList_New(0);
+        if (!*freelist) {
+            destr(ptr);
+            return -1;
+        }
     }
+
+    if (destr == cleanup_ptr) {
+        name = GETARGS_CAPSULE_NAME_CLEANUP_PTR;
+    } else if (destr == cleanup_buffer) {
+        name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER;
+    } else {
+        return -1;
+    }
+    cobj = PyCapsule_New(ptr, name, destr);
+    if (!cobj) {
+        destr(ptr);
+        return -1;
+    }
+    if (PyList_Append(*freelist, cobj)) {
+        Py_DECREF(cobj);
+        return -1;
+    }
+    Py_DECREF(cobj);
     return 0;
 }
 
 static int
-cleanup_buffer(PyObject *self, void *ptr)
+cleanreturn(int retval, PyObject *freelist)
 {
-    Py_buffer *buf = (Py_buffer *)ptr;
-    if (buf) {
-        PyBuffer_Release(buf);
+    if (freelist && retval != 0) {
+        /* We were successful, reset the destructors so that they
+           don't get called. */
+        Py_ssize_t len = PyList_GET_SIZE(freelist), i;
+        for (i = 0; i < len; i++)
+            PyCapsule_SetDestructor(PyList_GET_ITEM(freelist, i), NULL);
     }
-    return 0;
+    Py_XDECREF(freelist);
+    return retval;
 }
 
-static int
-addcleanup(void *ptr, freelist_t *freelist, destr_t destructor)
-{
-    int index;
-
-    index = freelist->first_available;
-    freelist->first_available += 1;
-
-    freelist->entries[index].item = ptr;
-    freelist->entries[index].destructor = destructor;
-
-    return 0;
-}
-
-static int
-cleanreturn(int retval, freelist_t *freelist)
-{
-    int index;
-
-    if (retval == 0) {
-      /* A failure occurred, therefore execute all of the cleanup
-	 functions.
-      */
-      for (index = 0; index < freelist->first_available; ++index) {
-          freelist->entries[index].destructor(NULL,
-                                              freelist->entries[index].item);
-      }
-    }
-    PyMem_Free(freelist->entries);
-    return retval;
-}
 
 static int
 vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
 {
-	char msgbuf[256];
-	int levels[32];
-	const char *fname = NULL;
-	const char *message = NULL;
-	int min = -1;
-	int max = 0;
-	int level = 0;
-	int endfmt = 0;
-	const char *formatsave = format;
-	Py_ssize_t i, len;
-	char *msg;
-	freelist_t freelist = {0, NULL};
-	int compat = flags & FLAG_COMPAT;
+    char msgbuf[256];
+    int levels[32];
+    const char *fname = NULL;
+    const char *message = NULL;
+    int min = -1;
+    int max = 0;
+    int level = 0;
+    int endfmt = 0;
+    const char *formatsave = format;
+    Py_ssize_t i, len;
+    char *msg;
+    PyObject *freelist = NULL;
+    int compat = flags & FLAG_COMPAT;
 
-	assert(compat || (args != (PyObject*)NULL));
-	flags = flags & ~FLAG_COMPAT;
+    assert(compat || (args != (PyObject*)NULL));
+    flags = flags & ~FLAG_COMPAT;
 
-	while (endfmt == 0) {
-		int c = *format++;
-		switch (c) {
-		case '(':
-			if (level == 0)
-				max++;
-			level++;
-			if (level >= 30)
-				Py_FatalError("too many tuple nesting levels "
-					      "in argument format string");
-			break;
-		case ')':
-			if (level == 0)
-				Py_FatalError("excess ')' in getargs format");
-			else
-				level--;
-			break;
-		case '\0':
-			endfmt = 1;
-			break;
-		case ':':
-			fname = format;
-			endfmt = 1;
-			break;
-		case ';':
-			message = format;
-			endfmt = 1;
-			break;
-		default:
-			if (level == 0) {
-				if (c == 'O')
-					max++;
-				else if (isalpha(Py_CHARMASK(c))) {
-					if (c != 'e') /* skip encoded */
-						max++;
-				} else if (c == '|')
-					min = max;
-			}
-			break;
-		}
-	}
-	
-	if (level != 0)
-		Py_FatalError(/* '(' */ "missing ')' in getargs format");
-	
-	if (min < 0)
-		min = max;
-	
-	format = formatsave;
-	
-	freelist.entries = PyMem_New(freelistentry_t, max);
+    while (endfmt == 0) {
+        int c = *format++;
+        switch (c) {
+        case '(':
+            if (level == 0)
+                max++;
+            level++;
+            if (level >= 30)
+                Py_FatalError("too many tuple nesting levels "
+                              "in argument format string");
+            break;
+        case ')':
+            if (level == 0)
+                Py_FatalError("excess ')' in getargs format");
+            else
+                level--;
+            break;
+        case '\0':
+            endfmt = 1;
+            break;
+        case ':':
+            fname = format;
+            endfmt = 1;
+            break;
+        case ';':
+            message = format;
+            endfmt = 1;
+            break;
+        default:
+            if (level == 0) {
+                if (c == 'O')
+                    max++;
+                else if (isalpha(Py_CHARMASK(c))) {
+                    if (c != 'e') /* skip encoded */
+                        max++;
+                } else if (c == '|')
+                    min = max;
+            }
+            break;
+        }
+    }
 
-	if (compat) {
-		if (max == 0) {
-			if (args == NULL)
-			    return cleanreturn(1, &freelist);
-			PyOS_snprintf(msgbuf, sizeof(msgbuf),
-				      "%.200s%s takes no arguments",
-				      fname==NULL ? "function" : fname,
-				      fname==NULL ? "" : "()");
-			PyErr_SetString(PyExc_TypeError, msgbuf);
-			return cleanreturn(0, &freelist);
-		}
-		else if (min == 1 && max == 1) {
-			if (args == NULL) {
-				PyOS_snprintf(msgbuf, sizeof(msgbuf),
-				      "%.200s%s takes at least one argument",
-					      fname==NULL ? "function" : fname,
-					      fname==NULL ? "" : "()");
-				PyErr_SetString(PyExc_TypeError, msgbuf);
-				return cleanreturn(0, &freelist);
-			}
-			msg = convertitem(args, &format, p_va, flags, levels, 
-					  msgbuf, sizeof(msgbuf), &freelist);
-			if (msg == NULL)
-				return cleanreturn(1, &freelist);
-			seterror(levels[0], msg, levels+1, fname, message);
-			return cleanreturn(0, &freelist);
-		}
-		else {
-			PyErr_SetString(PyExc_SystemError,
-			    "old style getargs format uses new features");
-			return cleanreturn(0, &freelist);
-		}
-	}
-	
-	if (!PyTuple_Check(args)) {
-		PyErr_SetString(PyExc_SystemError,
-		    "new style getargs format but argument is not a tuple");
-		return cleanreturn(0, &freelist);
-	}
-	
-	len = PyTuple_GET_SIZE(args);
-	
-	if (len < min || max < len) {
-		if (message == NULL) {
-			PyOS_snprintf(msgbuf, sizeof(msgbuf),
-				      "%.150s%s takes %s %d argument%s "
-				      "(%ld given)",
-				      fname==NULL ? "function" : fname,
-				      fname==NULL ? "" : "()",
-				      min==max ? "exactly"
-				      : len < min ? "at least" : "at most",
-				      len < min ? min : max,
-				      (len < min ? min : max) == 1 ? "" : "s",
-				      Py_SAFE_DOWNCAST(len, Py_ssize_t, long));
-			message = msgbuf;
-		}
-		PyErr_SetString(PyExc_TypeError, message);
-		return cleanreturn(0, &freelist);
-	}
-	
-	for (i = 0; i < len; i++) {
-		if (*format == '|')
-			format++;
-		msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
-				  flags, levels, msgbuf, 
-				  sizeof(msgbuf), &freelist);
-		if (msg) {
-			seterror(i+1, msg, levels, fname, message);
-			return cleanreturn(0, &freelist);
-		}
-	}
+    if (level != 0)
+        Py_FatalError(/* '(' */ "missing ')' in getargs format");
 
-	if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) &&
-	    *format != '(' &&
-	    *format != '|' && *format != ':' && *format != ';') {
-		PyErr_Format(PyExc_SystemError,
-			     "bad format string: %.200s", formatsave);
-		return cleanreturn(0, &freelist);
-	}
-	
-	return cleanreturn(1, &freelist);
+    if (min < 0)
+        min = max;
+
+    format = formatsave;
+
+    if (compat) {
+        if (max == 0) {
+            if (args == NULL)
+                return 1;
+            PyOS_snprintf(msgbuf, sizeof(msgbuf),
+                          "%.200s%s takes no arguments",
+                          fname==NULL ? "function" : fname,
+                          fname==NULL ? "" : "()");
+            PyErr_SetString(PyExc_TypeError, msgbuf);
+            return 0;
+        }
+        else if (min == 1 && max == 1) {
+            if (args == NULL) {
+                PyOS_snprintf(msgbuf, sizeof(msgbuf),
+                      "%.200s%s takes at least one argument",
+                          fname==NULL ? "function" : fname,
+                          fname==NULL ? "" : "()");
+                PyErr_SetString(PyExc_TypeError, msgbuf);
+                return 0;
+            }
+            msg = convertitem(args, &format, p_va, flags, levels,
+                              msgbuf, sizeof(msgbuf), &freelist);
+            if (msg == NULL)
+                return cleanreturn(1, freelist);
+            seterror(levels[0], msg, levels+1, fname, message);
+            return cleanreturn(0, freelist);
+        }
+        else {
+            PyErr_SetString(PyExc_SystemError,
+                "old style getargs format uses new features");
+            return 0;
+        }
+    }
+
+    if (!PyTuple_Check(args)) {
+        PyErr_SetString(PyExc_SystemError,
+            "new style getargs format but argument is not a tuple");
+        return 0;
+    }
+
+    len = PyTuple_GET_SIZE(args);
+
+    if (len < min || max < len) {
+        if (message == NULL) {
+            PyOS_snprintf(msgbuf, sizeof(msgbuf),
+                          "%.150s%s takes %s %d argument%s "
+                          "(%ld given)",
+                          fname==NULL ? "function" : fname,
+                          fname==NULL ? "" : "()",
+                          min==max ? "exactly"
+                          : len < min ? "at least" : "at most",
+                          len < min ? min : max,
+                          (len < min ? min : max) == 1 ? "" : "s",
+                          Py_SAFE_DOWNCAST(len, Py_ssize_t, long));
+            message = msgbuf;
+        }
+        PyErr_SetString(PyExc_TypeError, message);
+        return 0;
+    }
+
+    for (i = 0; i < len; i++) {
+        if (*format == '|')
+            format++;
+        msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
+                          flags, levels, msgbuf,
+                          sizeof(msgbuf), &freelist);
+        if (msg) {
+            seterror(i+1, msg, levels, fname, msg);
+            return cleanreturn(0, freelist);
+        }
+    }
+
+    if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) &&
+        *format != '(' &&
+        *format != '|' && *format != ':' && *format != ';') {
+        PyErr_Format(PyExc_SystemError,
+                     "bad format string: %.200s", formatsave);
+        return cleanreturn(0, freelist);
+    }
+
+    return cleanreturn(1, freelist);
 }
 
 
@@ -358,37 +357,37 @@
 seterror(int iarg, const char *msg, int *levels, const char *fname,
          const char *message)
 {
-	char buf[512];
-	int i;
-	char *p = buf;
+    char buf[512];
+    int i;
+    char *p = buf;
 
-	if (PyErr_Occurred())
-		return;
-	else if (message == NULL) {
-		if (fname != NULL) {
-			PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname);
-			p += strlen(p);
-		}
-		if (iarg != 0) {
-			PyOS_snprintf(p, sizeof(buf) - (p - buf),
-				      "argument %d", iarg);
-			i = 0;
-			p += strlen(p);
-			while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) {
-				PyOS_snprintf(p, sizeof(buf) - (p - buf),
-					      ", item %d", levels[i]-1);
-				p += strlen(p);
-				i++;
-			}
-		}
-		else {
-			PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument");
-			p += strlen(p);
-		}
-		PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg);
-		message = buf;
-	}
-	PyErr_SetString(PyExc_TypeError, message);
+    if (PyErr_Occurred())
+        return;
+    else if (message == NULL) {
+        if (fname != NULL) {
+            PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname);
+            p += strlen(p);
+        }
+        if (iarg != 0) {
+            PyOS_snprintf(p, sizeof(buf) - (p - buf),
+                          "argument %d", iarg);
+            i = 0;
+            p += strlen(p);
+            while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) {
+                PyOS_snprintf(p, sizeof(buf) - (p - buf),
+                              ", item %d", levels[i]-1);
+                p += strlen(p);
+                i++;
+            }
+        }
+        else {
+            PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument");
+            p += strlen(p);
+        }
+        PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg);
+        message = buf;
+    }
+    PyErr_SetString(PyExc_TypeError, message);
 }
 
 
@@ -404,85 +403,84 @@
       *p_va is undefined,
       *levels is a 0-terminated list of item numbers,
       *msgbuf contains an error message, whose format is:
-         "must be <typename1>, not <typename2>", where:
-            <typename1> is the name of the expected type, and
-            <typename2> is the name of the actual type,
+     "must be <typename1>, not <typename2>", where:
+        <typename1> is the name of the expected type, and
+        <typename2> is the name of the actual type,
       and msgbuf is returned.
 */
 
 static char *
 converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
-             int *levels, char *msgbuf, size_t bufsize, int toplevel, 
-             freelist_t *freelist)
+             int *levels, char *msgbuf, size_t bufsize, int toplevel,
+             PyObject **freelist)
 {
-	int level = 0;
-	int n = 0;
-	const char *format = *p_format;
-	int i;
-	
-	for (;;) {
-		int c = *format++;
-		if (c == '(') {
-			if (level == 0)
-				n++;
-			level++;
-		}
-		else if (c == ')') {
-			if (level == 0)
-				break;
-			level--;
-		}
-		else if (c == ':' || c == ';' || c == '\0')
-			break;
-		else if (level == 0 && isalpha(Py_CHARMASK(c)))
-			n++;
-	}
-	
-	if (!PySequence_Check(arg) || PyString_Check(arg)) {
-		levels[0] = 0;
-		PyOS_snprintf(msgbuf, bufsize,
-			      toplevel ? "expected %d arguments, not %.50s" :
-			              "must be %d-item sequence, not %.50s",
-			      n, 
-			      arg == Py_None ? "None" : arg->ob_type->tp_name);
-		return msgbuf;
-	}
-	
-	if ((i = PySequence_Size(arg)) != n) {
-		levels[0] = 0;
-		PyOS_snprintf(msgbuf, bufsize,
-			      toplevel ? "expected %d arguments, not %d" :
-			             "must be sequence of length %d, not %d",
-			      n, i);
-		return msgbuf;
-	}
+    int level = 0;
+    int n = 0;
+    const char *format = *p_format;
+    int i;
 
-	format = *p_format;
-	for (i = 0; i < n; i++) {
-		char *msg;
-		PyObject *item;
+    for (;;) {
+        int c = *format++;
+        if (c == '(') {
+            if (level == 0)
+                n++;
+            level++;
+        }
+        else if (c == ')') {
+            if (level == 0)
+                break;
+            level--;
+        }
+        else if (c == ':' || c == ';' || c == '\0')
+            break;
+        else if (level == 0 && isalpha(Py_CHARMASK(c)))
+            n++;
+    }
+
+    if (!PySequence_Check(arg) || PyString_Check(arg)) {
+        levels[0] = 0;
+        PyOS_snprintf(msgbuf, bufsize,
+                      toplevel ? "expected %d arguments, not %.50s" :
+                      "must be %d-item sequence, not %.50s",
+                  n,
+                  arg == Py_None ? "None" : arg->ob_type->tp_name);
+        return msgbuf;
+    }
+
+    if ((i = PySequence_Size(arg)) != n) {
+        levels[0] = 0;
+        PyOS_snprintf(msgbuf, bufsize,
+                      toplevel ? "expected %d arguments, not %d" :
+                     "must be sequence of length %d, not %d",
+                  n, i);
+        return msgbuf;
+    }
+
+    format = *p_format;
+    for (i = 0; i < n; i++) {
+        char *msg;
+        PyObject *item;
         item = PySequence_GetItem(arg, i);
-		if (item == NULL) {
-			PyErr_Clear();
-			levels[0] = i+1;
-			levels[1] = 0;
-			strncpy(msgbuf, "is not retrievable",
-				        bufsize);
-			return msgbuf;
-		}
-                PyPy_Borrow(arg, item);
-		msg = convertitem(item, &format, p_va, flags, levels+1, 
-				  msgbuf, bufsize, freelist);
+        if (item == NULL) {
+            PyErr_Clear();
+            levels[0] = i+1;
+            levels[1] = 0;
+            strncpy(msgbuf, "is not retrievable", bufsize);
+            return msgbuf;
+        }
+	PyPy_Borrow(arg, item);
+        msg = convertitem(item, &format, p_va, flags, levels+1,
+                          msgbuf, bufsize, freelist);
         /* PySequence_GetItem calls tp->sq_item, which INCREFs */
         Py_XDECREF(item);
-		if (msg != NULL) {
-			levels[0] = i+1;
-			return msg;
-		}
-	}
+        if (msg != NULL) {
+            levels[0] = i+1;
+            return msg;
+        }
+    }
 
-	*p_format = format;
-	return NULL;
+    *p_format = format;
+    return NULL;
 }
 
 
@@ -490,45 +488,45 @@
 
 static char *
 convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags,
-            int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist)
+            int *levels, char *msgbuf, size_t bufsize, PyObject **freelist)
 {
-	char *msg;
-	const char *format = *p_format;
-	
-	if (*format == '(' /* ')' */) {
-		format++;
-		msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, 
-				   bufsize, 0, freelist);
-		if (msg == NULL)
-			format++;
-	}
-	else {
-		msg = convertsimple(arg, &format, p_va, flags, 
-				    msgbuf, bufsize, freelist);
-		if (msg != NULL)
-			levels[0] = 0;
-	}
-	if (msg == NULL)
-		*p_format = format;
-	return msg;
+    char *msg;
+    const char *format = *p_format;
+
+    if (*format == '(' /* ')' */) {
+        format++;
+        msg = converttuple(arg, &format, p_va, flags, levels, msgbuf,
+                           bufsize, 0, freelist);
+        if (msg == NULL)
+            format++;
+    }
+    else {
+        msg = convertsimple(arg, &format, p_va, flags,
+                            msgbuf, bufsize, freelist);
+        if (msg != NULL)
+            levels[0] = 0;
+    }
+    if (msg == NULL)
+        *p_format = format;
+    return msg;
 }
 
 
 
 #define UNICODE_DEFAULT_ENCODING(arg) \
-        _PyUnicode_AsDefaultEncodedString(arg, NULL)
+    _PyUnicode_AsDefaultEncodedString(arg, NULL)
 
 /* Format an error message generated by convertsimple(). */
 
 static char *
 converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize)
 {
-	assert(expected != NULL);
-	assert(arg != NULL); 
-	PyOS_snprintf(msgbuf, bufsize,
-		      "must be %.50s, not %.50s", expected,
-		      arg == Py_None ? "None" : arg->ob_type->tp_name);
-	return msgbuf;
+    assert(expected != NULL);
+    assert(arg != NULL);
+    PyOS_snprintf(msgbuf, bufsize,
+                  "must be %.50s, not %.50s", expected,
+                  arg == Py_None ? "None" : arg->ob_type->tp_name);
+    return msgbuf;
 }
 
 #define CONV_UNICODE "(unicode conversion error)"
@@ -536,14 +534,28 @@
 /* explicitly check for float arguments when integers are expected.  For now
  * signal a warning.  Returns true if an exception was raised. */
 static int
+float_argument_warning(PyObject *arg)
+{
+    if (PyFloat_Check(arg) &&
+        PyErr_Warn(PyExc_DeprecationWarning,
+                   "integer argument expected, got float" ))
+        return 1;
+    else
+        return 0;
+}
+
+/* explicitly check for float arguments when integers are expected.  Raises
+   TypeError and returns true for float arguments. */
+static int
 float_argument_error(PyObject *arg)
 {
-	if (PyFloat_Check(arg) &&
-	    PyErr_Warn(PyExc_DeprecationWarning,
-		       "integer argument expected, got float" ))
-		return 1;
-	else
-		return 0;
+    if (PyFloat_Check(arg)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "integer argument expected, got float");
+        return 1;
+    }
+    else
+        return 0;
 }
 
 /* Convert a non-tuple argument.  Return NULL if conversion went OK,
@@ -557,836 +569,839 @@
 
 static char *
 convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
-              char *msgbuf, size_t bufsize, freelist_t *freelist)
+              char *msgbuf, size_t bufsize, PyObject **freelist)
 {
-	/* For # codes */
-#define FETCH_SIZE	int *q=NULL;Py_ssize_t *q2=NULL;\
-	if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \
-	else q=va_arg(*p_va, int*);
-#define STORE_SIZE(s)   if (flags & FLAG_SIZE_T) *q2=s; else *q=s;
+    /* For # codes */
+#define FETCH_SIZE      int *q=NULL;Py_ssize_t *q2=NULL;\
+    if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \
+    else q=va_arg(*p_va, int*);
+#define STORE_SIZE(s)   \
+    if (flags & FLAG_SIZE_T) \
+        *q2=s; \
+    else { \
+        if (INT_MAX < s) { \
+            PyErr_SetString(PyExc_OverflowError, \
+                "size does not fit in an int"); \
+            return converterr("", arg, msgbuf, bufsize); \
+        } \
+        *q=s; \
+    }
 #define BUFFER_LEN      ((flags & FLAG_SIZE_T) ? *q2:*q)
 
-	const char *format = *p_format;
-	char c = *format++;
+    const char *format = *p_format;
+    char c = *format++;
 #ifdef Py_USING_UNICODE
-	PyObject *uarg;
-#endif
-	
-	switch (c) {
-	
-	case 'b': { /* unsigned byte -- very short int */
-		char *p = va_arg(*p_va, char *);
-		long ival;
-		if (float_argument_error(arg))
-			return converterr("integer<b>", arg, msgbuf, bufsize);
-		ival = PyInt_AsLong(arg);
-		if (ival == -1 && PyErr_Occurred())
-			return converterr("integer<b>", arg, msgbuf, bufsize);
-		else if (ival < 0) {
-			PyErr_SetString(PyExc_OverflowError,
-			"unsigned byte integer is less than minimum");
-			return converterr("integer<b>", arg, msgbuf, bufsize);
-		}
-		else if (ival > UCHAR_MAX) {
-			PyErr_SetString(PyExc_OverflowError,
-			"unsigned byte integer is greater than maximum");
-			return converterr("integer<b>", arg, msgbuf, bufsize);
-		}
-		else
-			*p = (unsigned char) ival;
-		break;
-	}
-	
-	case 'B': {/* byte sized bitfield - both signed and unsigned
-		      values allowed */  
-		char *p = va_arg(*p_va, char *);
-		long ival;
-		if (float_argument_error(arg))
-			return converterr("integer<B>", arg, msgbuf, bufsize);
-		ival = PyInt_AsUnsignedLongMask(arg);
-		if (ival == -1 && PyErr_Occurred())
-			return converterr("integer<B>", arg, msgbuf, bufsize);
-		else
-			*p = (unsigned char) ival;
-		break;
-	}
-	
-	case 'h': {/* signed short int */
-		short *p = va_arg(*p_va, short *);
-		long ival;
-		if (float_argument_error(arg))
-			return converterr("integer<h>", arg, msgbuf, bufsize);
-		ival = PyInt_AsLong(arg);
-		if (ival == -1 && PyErr_Occurred())
-			return converterr("integer<h>", arg, msgbuf, bufsize);
-		else if (ival < SHRT_MIN) {
-			PyErr_SetString(PyExc_OverflowError,
-			"signed short integer is less than minimum");
-			return converterr("integer<h>", arg, msgbuf, bufsize);
-		}
-		else if (ival > SHRT_MAX) {
-			PyErr_SetString(PyExc_OverflowError,
-			"signed short integer is greater than maximum");
-			return converterr("integer<h>", arg, msgbuf, bufsize);
-		}
-		else
-			*p = (short) ival;
-		break;
-	}
-	
-	case 'H': { /* short int sized bitfield, both signed and
-		       unsigned allowed */ 
-		unsigned short *p = va_arg(*p_va, unsigned short *);
-		long ival;
-		if (float_argument_error(arg))
-			return converterr("integer<H>", arg, msgbuf, bufsize);
-		ival = PyInt_AsUnsignedLongMask(arg);
-		if (ival == -1 && PyErr_Occurred())
-			return converterr("integer<H>", arg, msgbuf, bufsize);
-		else
-			*p = (unsigned short) ival;
-		break;
-	}
-	case 'i': {/* signed int */
-		int *p = va_arg(*p_va, int *);
-		long ival;
-		if (float_argument_error(arg))
-			return converterr("integer<i>", arg, msgbuf, bufsize);
-		ival = PyInt_AsLong(arg);
-		if (ival == -1 && PyErr_Occurred())
-			return converterr("integer<i>", arg, msgbuf, bufsize);
-		else if (ival > INT_MAX) {
-			PyErr_SetString(PyExc_OverflowError,
-				"signed integer is greater than maximum");
-			return converterr("integer<i>", arg, msgbuf, bufsize);
-		}
-		else if (ival < INT_MIN) {
-			PyErr_SetString(PyExc_OverflowError,
-				"signed integer is less than minimum");
-			return converterr("integer<i>", arg, msgbuf, bufsize);
-		}
-		else
-			*p = ival;
-		break;
-	}
-	case 'I': { /* int sized bitfield, both signed and
-		       unsigned allowed */ 
-		unsigned int *p = va_arg(*p_va, unsigned int *);
-		unsigned int ival;
-		if (float_argument_error(arg))
-			return converterr("integer<I>", arg, msgbuf, bufsize);
-		ival = (unsigned int)PyInt_AsUnsignedLongMask(arg);
-		if (ival == (unsigned int)-1 && PyErr_Occurred())
-			return converterr("integer<I>", arg, msgbuf, bufsize);
-		else
-			*p = ival;
-		break;
-	}
-	case 'n': /* Py_ssize_t */
-#if SIZEOF_SIZE_T != SIZEOF_LONG
-	{
-		Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *);
-		Py_ssize_t ival;
-		if (float_argument_error(arg))
-			return converterr("integer<n>", arg, msgbuf, bufsize);
-		ival = PyInt_AsSsize_t(arg);
-		if (ival == -1 && PyErr_Occurred())
-			return converterr("integer<n>", arg, msgbuf, bufsize);
-		*p = ival;
-		break;
-	}
-#endif
-	/* Fall through from 'n' to 'l' if Py_ssize_t is int */
-	case 'l': {/* long int */
-		long *p = va_arg(*p_va, long *);
-		long ival;
-		if (float_argument_error(arg))
-			return converterr("integer<l>", arg, msgbuf, bufsize);
-		ival = PyInt_AsLong(arg);
-		if (ival == -1 && PyErr_Occurred())
-			return converterr("integer<l>", arg, msgbuf, bufsize);
-		else
-			*p = ival;
-		break;
-	}
-
-	case 'k': { /* long sized bitfield */
-		unsigned long *p = va_arg(*p_va, unsigned long *);
-		unsigned long ival;
-		if (PyInt_Check(arg))
-			ival = PyInt_AsUnsignedLongMask(arg);
-		else if (PyLong_Check(arg))
-			ival = PyLong_AsUnsignedLongMask(arg);
-		else
-			return converterr("integer<k>", arg, msgbuf, bufsize);
-		*p = ival;
-		break;
-	}
-	
-#ifdef HAVE_LONG_LONG
-	case 'L': {/* PY_LONG_LONG */
-		PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * );
-		PY_LONG_LONG ival = PyLong_AsLongLong( arg );
-		if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) {
-			return converterr("long<L>", arg, msgbuf, bufsize);
-		} else {
-			*p = ival;
-		}
-		break;
-	}
-
-	case 'K': { /* long long sized bitfield */
-		unsigned PY_LONG_LONG *p = va_arg(*p_va, unsigned PY_LONG_LONG *);
-		unsigned PY_LONG_LONG ival;
-		if (PyInt_Check(arg))
-			ival = PyInt_AsUnsignedLongMask(arg);
-		else if (PyLong_Check(arg))
-			ival = PyLong_AsUnsignedLongLongMask(arg);
-		else
-			return converterr("integer<K>", arg, msgbuf, bufsize);
-		*p = ival;
-		break;
-  }
-#endif // HAVE_LONG_LONG
-
-	case 'f': {/* float */
-		float *p = va_arg(*p_va, float *);
-		double dval = PyFloat_AsDouble(arg);
-		if (PyErr_Occurred())
-			return converterr("float<f>", arg, msgbuf, bufsize);
-		else
-			*p = (float) dval;
-		break;
-	}
-	
-	case 'd': {/* double */
-		double *p = va_arg(*p_va, double *);
-		double dval = PyFloat_AsDouble(arg);
-		if (PyErr_Occurred())
-			return converterr("float<d>", arg, msgbuf, bufsize);
-		else
-			*p = dval;
-		break;
-	}
-	
-#ifndef WITHOUT_COMPLEX
-	case 'D': {/* complex double */
-		Py_complex *p = va_arg(*p_va, Py_complex *);
-		Py_complex cval;
-		cval = PyComplex_AsCComplex(arg);
-		if (PyErr_Occurred())
-			return converterr("complex<D>", arg, msgbuf, bufsize);
-		else
-			*p = cval;
-		break;
-	}
-#endif /* WITHOUT_COMPLEX */
-	
-	case 'c': {/* char */
-		char *p = va_arg(*p_va, char *);
-		if (PyString_Check(arg) && PyString_Size(arg) == 1)
-			*p = PyString_AS_STRING(arg)[0];
-		else
-			return converterr("char", arg, msgbuf, bufsize);
-		break;
-	}
-	case 's': {/* string */
-		if (*format == '*') {
-			Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
-
-			if (PyString_Check(arg)) {
-                            fflush(stdout);
-				PyBuffer_FillInfo(p, arg,
-						  PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
-						  1, 0);
-			}
-#ifdef Py_USING_UNICODE
-			else if (PyUnicode_Check(arg)) {
-#if 0
-				uarg = UNICODE_DEFAULT_ENCODING(arg);
-				if (uarg == NULL)
-					return converterr(CONV_UNICODE,
-							  arg, msgbuf, bufsize);
-				PyBuffer_FillInfo(p, arg,
-						  PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg),
-						  1, 0);
-#else
-                                return converterr("string or buffer", arg, msgbuf, bufsize);
-#endif
-			}
-#endif
-			else { /* any buffer-like object */
-				char *buf;
-				if (getbuffer(arg, p, &buf) < 0)
-					return converterr(buf, arg, msgbuf, bufsize);
-			}
-			if (addcleanup(p, freelist, cleanup_buffer)) {
-				return converterr(
-					"(cleanup problem)",
-					arg, msgbuf, bufsize);
-			}
-			format++;
-		} else if (*format == '#') {
-			void **p = (void **)va_arg(*p_va, char **);
-			FETCH_SIZE;
-			
-			if (PyString_Check(arg)) {
-				*p = PyString_AS_STRING(arg);
-				STORE_SIZE(PyString_GET_SIZE(arg));
-			}
-#ifdef Py_USING_UNICODE
-			else if (PyUnicode_Check(arg)) {
-				uarg = UNICODE_DEFAULT_ENCODING(arg);
-				if (uarg == NULL)
-					return converterr(CONV_UNICODE,
-							  arg, msgbuf, bufsize);
-				*p = PyString_AS_STRING(uarg);
-				STORE_SIZE(PyString_GET_SIZE(uarg));
-			}
-#endif
-			else { /* any buffer-like object */
-				char *buf;
-				Py_ssize_t count = convertbuffer(arg, p, &buf);
-				if (count < 0)
-					return converterr(buf, arg, msgbuf, bufsize);
-				STORE_SIZE(count);
-			}
-			format++;
-		} else {
-			char **p = va_arg(*p_va, char **);
-			
-			if (PyString_Check(arg))
-				*p = PyString_AS_STRING(arg);
-#ifdef Py_USING_UNICODE
-			else if (PyUnicode_Check(arg)) {
-				uarg = UNICODE_DEFAULT_ENCODING(arg);
-				if (uarg == NULL)
-					return converterr(CONV_UNICODE,
-							  arg, msgbuf, bufsize);
-				*p = PyString_AS_STRING(uarg);
-			}
-#endif
-			else
-				return converterr("string", arg, msgbuf, bufsize);
-			if ((Py_ssize_t)strlen(*p) != PyString_Size(arg))
-				return converterr("string without null bytes",
-						  arg, msgbuf, bufsize);
-		}
-		break;
-	}
-
-	case 'z': {/* string, may be NULL (None) */
-		if (*format == '*') {
-      Py_FatalError("'*' format not supported in PyArg_*\n");
-#if 0
-			Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
-
-			if (arg == Py_None)
-				PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);
-			else if (PyString_Check(arg)) {
-				PyBuffer_FillInfo(p, arg,
-						  PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
-						  1, 0);
-			}
-#ifdef Py_USING_UNICODE
-			else if (PyUnicode_Check(arg)) {
-				uarg = UNICODE_DEFAULT_ENCODING(arg);
-				if (uarg == NULL)
-					return converterr(CONV_UNICODE,
-							  arg, msgbuf, bufsize);
-				PyBuffer_FillInfo(p, arg,
-						  PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg),
-						  1, 0);
-			}
-#endif
-			else { /* any buffer-like object */
-				char *buf;
-				if (getbuffer(arg, p, &buf) < 0)
-					return converterr(buf, arg, msgbuf, bufsize);
-			}
-			if (addcleanup(p, freelist, cleanup_buffer)) {
-				return converterr(
-					"(cleanup problem)",
-					arg, msgbuf, bufsize);
-			}
-			format++;
-#endif
-		} else if (*format == '#') { /* any buffer-like object */
-			void **p = (void **)va_arg(*p_va, char **);
-			FETCH_SIZE;
-			
-			if (arg == Py_None) {
-				*p = 0;
-				STORE_SIZE(0);
-			}
-			else if (PyString_Check(arg)) {
-				*p = PyString_AS_STRING(arg);
-				STORE_SIZE(PyString_GET_SIZE(arg));
-			}
-#ifdef Py_USING_UNICODE
-			else if (PyUnicode_Check(arg)) {
-				uarg = UNICODE_DEFAULT_ENCODING(arg);
-				if (uarg == NULL)
-					return converterr(CONV_UNICODE,
-							  arg, msgbuf, bufsize);
-				*p = PyString_AS_STRING(uarg);
-				STORE_SIZE(PyString_GET_SIZE(uarg));
-			}
-#endif
-			else { /* any buffer-like object */
-				char *buf;
-				Py_ssize_t count = convertbuffer(arg, p, &buf);
-				if (count < 0)
-					return converterr(buf, arg, msgbuf, bufsize);
-				STORE_SIZE(count);
-			}
-			format++;
-		} else {
-			char **p = va_arg(*p_va, char **);
-			
-			if (arg == Py_None)
-				*p = 0;
-			else if (PyString_Check(arg))
-				*p = PyString_AS_STRING(arg);
-#ifdef Py_USING_UNICODE
-			else if (PyUnicode_Check(arg)) {
-				uarg = UNICODE_DEFAULT_ENCODING(arg);
-				if (uarg == NULL)
-					return converterr(CONV_UNICODE,
-							  arg, msgbuf, bufsize);
-				*p = PyString_AS_STRING(uarg);
-			}
-#endif
-			else
-				return converterr("string or None", 
-						  arg, msgbuf, bufsize);
-			if (*format == '#') {
-				FETCH_SIZE;
-				assert(0); /* XXX redundant with if-case */
-				if (arg == Py_None)
-					*q = 0;
-				else
-					*q = PyString_Size(arg);
-				format++;
-			}
-			else if (*p != NULL &&
-				 (Py_ssize_t)strlen(*p) != PyString_Size(arg))
-				return converterr(
-					"string without null bytes or None", 
-					arg, msgbuf, bufsize);
-		}
-		break;
-	}
-	case 'e': {/* encoded string */
-		char **buffer;
-		const char *encoding;
-		PyObject *s;
-		Py_ssize_t size;
-		int recode_strings;
-
-		/* Get 'e' parameter: the encoding name */
-		encoding = (const char *)va_arg(*p_va, const char *);
-#ifdef Py_USING_UNICODE
-		if (encoding == NULL)
-			encoding = PyUnicode_GetDefaultEncoding();
+    PyObject *uarg;
 #endif
 
-		/* Get output buffer parameter:
-		   's' (recode all objects via Unicode) or
-		   't' (only recode non-string objects) 
-		*/
-		if (*format == 's')
-			recode_strings = 1;
-		else if (*format == 't')
-			recode_strings = 0;
-		else
-			return converterr(
-				"(unknown parser marker combination)",
-				arg, msgbuf, bufsize);
-		buffer = (char **)va_arg(*p_va, char **);
-		format++;
-		if (buffer == NULL)
-			return converterr("(buffer is NULL)", 
-					  arg, msgbuf, bufsize);
-			
-		/* Encode object */
-		if (!recode_strings && PyString_Check(arg)) {
-			s = arg;
-			Py_INCREF(s);
-		}
-		else {
+    switch (c) {
+
+    case 'b': { /* unsigned byte -- very short int */
+        char *p = va_arg(*p_va, char *);
+        long ival;
+        if (float_argument_error(arg))
+            return converterr("integer<b>", arg, msgbuf, bufsize);
+        ival = PyInt_AsLong(arg);
+        if (ival == -1 && PyErr_Occurred())
+            return converterr("integer<b>", arg, msgbuf, bufsize);
+        else if (ival < 0) {
+            PyErr_SetString(PyExc_OverflowError,
+            "unsigned byte integer is less than minimum");
+            return converterr("integer<b>", arg, msgbuf, bufsize);
+        }
+        else if (ival > UCHAR_MAX) {
+            PyErr_SetString(PyExc_OverflowError,
+            "unsigned byte integer is greater than maximum");
+            return converterr("integer<b>", arg, msgbuf, bufsize);
+        }
+        else
+            *p = (unsigned char) ival;
+        break;
+    }
+
+    case 'B': {/* byte sized bitfield - both signed and unsigned
+                  values allowed */
+        char *p = va_arg(*p_va, char *);
+        long ival;
+        if (float_argument_error(arg))
+            return converterr("integer<B>", arg, msgbuf, bufsize);
+        ival = PyInt_AsUnsignedLongMask(arg);
+        if (ival == -1 && PyErr_Occurred())
+            return converterr("integer<B>", arg, msgbuf, bufsize);
+        else
+            *p = (unsigned char) ival;
+        break;
+    }
+
+    case 'h': {/* signed short int */
+        short *p = va_arg(*p_va, short *);
+        long ival;
+        if (float_argument_error(arg))
+            return converterr("integer<h>", arg, msgbuf, bufsize);
+        ival = PyInt_AsLong(arg);
+        if (ival == -1 && PyErr_Occurred())
+            return converterr("integer<h>", arg, msgbuf, bufsize);
+        else if (ival < SHRT_MIN) {
+            PyErr_SetString(PyExc_OverflowError,
+            "signed short integer is less than minimum");
+            return converterr("integer<h>", arg, msgbuf, bufsize);
+        }
+        else if (ival > SHRT_MAX) {
+            PyErr_SetString(PyExc_OverflowError,
+            "signed short integer is greater than maximum");
+            return converterr("integer<h>", arg, msgbuf, bufsize);
+        }
+        else
+            *p = (short) ival;
+        break;
+    }
+
+    case 'H': { /* short int sized bitfield, both signed and
+                   unsigned allowed */
+        unsigned short *p = va_arg(*p_va, unsigned short *);
+        long ival;
+        if (float_argument_error(arg))
+            return converterr("integer<H>", arg, msgbuf, bufsize);
+        ival = PyInt_AsUnsignedLongMask(arg);
+        if (ival == -1 && PyErr_Occurred())
+            return converterr("integer<H>", arg, msgbuf, bufsize);
+        else
+            *p = (unsigned short) ival;
+        break;
+    }
+
+    case 'i': {/* signed int */
+        int *p = va_arg(*p_va, int *);
+        long ival;
+        if (float_argument_error(arg))
+            return converterr("integer<i>", arg, msgbuf, bufsize);
+        ival = PyInt_AsLong(arg);
+        if (ival == -1 && PyErr_Occurred())
+            return converterr("integer<i>", arg, msgbuf, bufsize);
+        else if (ival > INT_MAX) {
+            PyErr_SetString(PyExc_OverflowError,
+                "signed integer is greater than maximum");
+            return converterr("integer<i>", arg, msgbuf, bufsize);
+        }
+        else if (ival < INT_MIN) {
+            PyErr_SetString(PyExc_OverflowError,
+                "signed integer is less than minimum");
+            return converterr("integer<i>", arg, msgbuf, bufsize);
+        }
+        else
+            *p = ival;
+        break;
+    }
+
+    case 'I': { /* int sized bitfield, both signed and
+                   unsigned allowed */
+        unsigned int *p = va_arg(*p_va, unsigned int *);
+        unsigned int ival;
+        if (float_argument_error(arg))
+            return converterr("integer<I>", arg, msgbuf, bufsize);
+        ival = (unsigned int)PyInt_AsUnsignedLongMask(arg);
+        if (ival == (unsigned int)-1 && PyErr_Occurred())
+            return converterr("integer<I>", arg, msgbuf, bufsize);
+        else
+            *p = ival;
+        break;
+    }
+
+    case 'n': /* Py_ssize_t */
+#if SIZEOF_SIZE_T != SIZEOF_LONG
+    {
+        Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *);
+        Py_ssize_t ival;
+        if (float_argument_error(arg))
+            return converterr("integer<n>", arg, msgbuf, bufsize);
+        ival = PyInt_AsSsize_t(arg);
+        if (ival == -1 && PyErr_Occurred())
+            return converterr("integer<n>", arg, msgbuf, bufsize);
+        *p = ival;
+        break;
+    }
+#endif
+    /* Fall through from 'n' to 'l' if Py_ssize_t is int */
+    case 'l': {/* long int */
+        long *p = va_arg(*p_va, long *);
+        long ival;
+        if (float_argument_error(arg))
+            return converterr("integer<l>", arg, msgbuf, bufsize);
+        ival = PyInt_AsLong(arg);
+        if (ival == -1 && PyErr_Occurred())
+            return converterr("integer<l>", arg, msgbuf, bufsize);
+        else
+            *p = ival;
+        break;
+    }
+
+    case 'k': { /* long sized bitfield */
+        unsigned long *p = va_arg(*p_va, unsigned long *);
+        unsigned long ival;
+        if (PyInt_Check(arg))
+            ival = PyInt_AsUnsignedLongMask(arg);
+        else if (PyLong_Check(arg))
+            ival = PyLong_AsUnsignedLongMask(arg);
+        else
+            return converterr("integer<k>", arg, msgbuf, bufsize);
+        *p = ival;
+        break;
+    }
+
+#ifdef HAVE_LONG_LONG
+    case 'L': {/* PY_LONG_LONG */
+        PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * );
+        PY_LONG_LONG ival;
+        if (float_argument_warning(arg))
+            return converterr("long<L>", arg, msgbuf, bufsize);
+        ival = PyLong_AsLongLong(arg);
+        if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) {
+            return converterr("long<L>", arg, msgbuf, bufsize);
+        } else {
+            *p = ival;
+        }
+        break;
+    }
+
+    case 'K': { /* long long sized bitfield */
+        unsigned PY_LONG_LONG *p = va_arg(*p_va, unsigned PY_LONG_LONG *);
+        unsigned PY_LONG_LONG ival;
+        if (PyInt_Check(arg))
+            ival = PyInt_AsUnsignedLongMask(arg);
+        else if (PyLong_Check(arg))
+            ival = PyLong_AsUnsignedLongLongMask(arg);
+        else
+            return converterr("integer<K>", arg, msgbuf, bufsize);
+        *p = ival;
+        break;
+    }
+#endif
+
+    case 'f': {/* float */
+        float *p = va_arg(*p_va, float *);
+        double dval = PyFloat_AsDouble(arg);
+        if (PyErr_Occurred())
+            return converterr("float<f>", arg, msgbuf, bufsize);
+        else
+            *p = (float) dval;
+        break;
+    }
+
+    case 'd': {/* double */
+        double *p = va_arg(*p_va, double *);
+        double dval = PyFloat_AsDouble(arg);
+        if (PyErr_Occurred())
+            return converterr("float<d>", arg, msgbuf, bufsize);
+        else
+            *p = dval;
+        break;
+    }
+
+#ifndef WITHOUT_COMPLEX
+    case 'D': {/* complex double */
+        Py_complex *p = va_arg(*p_va, Py_complex *);
+        Py_complex cval;
+        cval = PyComplex_AsCComplex(arg);
+        if (PyErr_Occurred())
+            return converterr("complex<D>", arg, msgbuf, bufsize);
+        else
+            *p = cval;
+        break;
+    }
+#endif /* WITHOUT_COMPLEX */
+
+    case 'c': {/* char */
+        char *p = va_arg(*p_va, char *);
+        if (PyString_Check(arg) && PyString_Size(arg) == 1)
+            *p = PyString_AS_STRING(arg)[0];
+        else
+            return converterr("char", arg, msgbuf, bufsize);
+        break;
+    }
+
+    case 's': {/* string */
+        if (*format == '*') {
+            Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
+
+            if (PyString_Check(arg)) {
+                PyBuffer_FillInfo(p, arg,
+                                  PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
+                                  1, 0);
+            }
 #ifdef Py_USING_UNICODE
-		    	PyObject *u;
+            else if (PyUnicode_Check(arg)) {
+                uarg = UNICODE_DEFAULT_ENCODING(arg);
+                if (uarg == NULL)
+                    return converterr(CONV_UNICODE,
+                                      arg, msgbuf, bufsize);
+                PyBuffer_FillInfo(p, arg,
+                                  PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg),
+                                  1, 0);
+            }
+#endif
+            else { /* any buffer-like object */
+                char *buf;
+                if (getbuffer(arg, p, &buf) < 0)
+                    return converterr(buf, arg, msgbuf, bufsize);
+            }
+            if (addcleanup(p, freelist, cleanup_buffer)) {
+                return converterr(
+                    "(cleanup problem)",
+                    arg, msgbuf, bufsize);
+            }
+            format++;
+        } else if (*format == '#') {
+            void **p = (void **)va_arg(*p_va, char **);
+            FETCH_SIZE;
 
-			/* Convert object to Unicode */
-			u = PyUnicode_FromObject(arg);
-			if (u == NULL)
-				return converterr(
-					"string or unicode or text buffer", 
-					arg, msgbuf, bufsize);
-			
-			/* Encode object; use default error handling */
-			s = PyUnicode_AsEncodedString(u,
-						      encoding,
-						      NULL);
-			Py_DECREF(u);
-			if (s == NULL)
-				return converterr("(encoding failed)",
-						  arg, msgbuf, bufsize);
-			if (!PyString_Check(s)) {
-				Py_DECREF(s);
-				return converterr(
-					"(encoder failed to return a string)",
-					arg, msgbuf, bufsize);
-			}
+            if (PyString_Check(arg)) {
+                *p = PyString_AS_STRING(arg);
+                STORE_SIZE(PyString_GET_SIZE(arg));
+            }
+#ifdef Py_USING_UNICODE
+            else if (PyUnicode_Check(arg)) {
+                uarg = UNICODE_DEFAULT_ENCODING(arg);
+                if (uarg == NULL)
+                    return converterr(CONV_UNICODE,
+                                      arg, msgbuf, bufsize);
+                *p = PyString_AS_STRING(uarg);
+                STORE_SIZE(PyString_GET_SIZE(uarg));
+            }
+#endif
+            else { /* any buffer-like object */
+                char *buf;
+                Py_ssize_t count = convertbuffer(arg, p, &buf);
+                if (count < 0)
+                    return converterr(buf, arg, msgbuf, bufsize);
+                STORE_SIZE(count);
+            }
+            format++;
+        } else {
+            char **p = va_arg(*p_va, char **);
+
+            if (PyString_Check(arg))
+                *p = PyString_AS_STRING(arg);
+#ifdef Py_USING_UNICODE
+            else if (PyUnicode_Check(arg)) {
+                uarg = UNICODE_DEFAULT_ENCODING(arg);
+                if (uarg == NULL)
+                    return converterr(CONV_UNICODE,
+                                      arg, msgbuf, bufsize);
+                *p = PyString_AS_STRING(uarg);
+            }
+#endif
+            else
+                return converterr("string", arg, msgbuf, bufsize);
+            if ((Py_ssize_t)strlen(*p) != PyString_Size(arg))
+                return converterr("string without null bytes",
+                                  arg, msgbuf, bufsize);
+        }
+        break;
+    }
+
+    case 'z': {/* string, may be NULL (None) */
+        if (*format == '*') {
+            Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
+
+            if (arg == Py_None)
+                PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);
+            else if (PyString_Check(arg)) {
+                PyBuffer_FillInfo(p, arg,
+                                  PyString_AS_STRING(arg), PyString_GET_SIZE(arg),
+                                  1, 0);
+            }
+#ifdef Py_USING_UNICODE
+            else if (PyUnicode_Check(arg)) {
+                uarg = UNICODE_DEFAULT_ENCODING(arg);
+                if (uarg == NULL)
+                    return converterr(CONV_UNICODE,
+                                      arg, msgbuf, bufsize);
+                PyBuffer_FillInfo(p, arg,
+                                  PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg),
+                                  1, 0);
+            }
+#endif
+            else { /* any buffer-like object */
+                char *buf;
+                if (getbuffer(arg, p, &buf) < 0)
+                    return converterr(buf, arg, msgbuf, bufsize);
+            }
+            if (addcleanup(p, freelist, cleanup_buffer)) {
+                return converterr(
+                    "(cleanup problem)",
+                    arg, msgbuf, bufsize);
+            }
+            format++;
+        } else if (*format == '#') { /* any buffer-like object */
+            void **p = (void **)va_arg(*p_va, char **);
+            FETCH_SIZE;
+
+            if (arg == Py_None) {
+                *p = 0;
+                STORE_SIZE(0);
+            }
+            else if (PyString_Check(arg)) {
+                *p = PyString_AS_STRING(arg);
+                STORE_SIZE(PyString_GET_SIZE(arg));
+            }
+#ifdef Py_USING_UNICODE
+            else if (PyUnicode_Check(arg)) {
+                uarg = UNICODE_DEFAULT_ENCODING(arg);
+                if (uarg == NULL)
+                    return converterr(CONV_UNICODE,
+                                      arg, msgbuf, bufsize);
+                *p = PyString_AS_STRING(uarg);
+                STORE_SIZE(PyString_GET_SIZE(uarg));
+            }
+#endif
+            else { /* any buffer-like object */
+                char *buf;
+                Py_ssize_t count = convertbuffer(arg, p, &buf);
+                if (count < 0)
+                    return converterr(buf, arg, msgbuf, bufsize);
+                STORE_SIZE(count);
+            }
+            format++;
+        } else {
+            char **p = va_arg(*p_va, char **);
+
+            if (arg == Py_None)
+                *p = 0;
+            else if (PyString_Check(arg))
+                *p = PyString_AS_STRING(arg);
+#ifdef Py_USING_UNICODE
+            else if (PyUnicode_Check(arg)) {
+                uarg = UNICODE_DEFAULT_ENCODING(arg);
+                if (uarg == NULL)
+                    return converterr(CONV_UNICODE,
+                                      arg, msgbuf, bufsize);
+                *p = PyString_AS_STRING(uarg);
+            }
+#endif
+            else
+                return converterr("string or None",
+                                  arg, msgbuf, bufsize);
+            if (*format == '#') {
+                FETCH_SIZE;
+                assert(0); /* XXX redundant with if-case */
+                if (arg == Py_None) {
+                    STORE_SIZE(0);
+                } else {
+                    STORE_SIZE(PyString_Size(arg));
+                }
+                format++;
+            }
+            else if (*p != NULL &&
+                     (Py_ssize_t)strlen(*p) != PyString_Size(arg))
+                return converterr(
+                    "string without null bytes or None",
+                    arg, msgbuf, bufsize);
+        }
+        break;
+    }
+
+    case 'e': {/* encoded string */
+        char **buffer;
+        const char *encoding;
+        PyObject *s;
+        Py_ssize_t size;
+        int recode_strings;
+
+        /* Get 'e' parameter: the encoding name */
+        encoding = (const char *)va_arg(*p_va, const char *);
+#ifdef Py_USING_UNICODE
+        if (encoding == NULL)
+            encoding = PyUnicode_GetDefaultEncoding();
+#endif
+
+        /* Get output buffer parameter:
+           's' (recode all objects via Unicode) or
+           't' (only recode non-string objects)
+        */
+        if (*format == 's')
+            recode_strings = 1;
+        else if (*format == 't')
+            recode_strings = 0;
+        else
+            return converterr(
+                "(unknown parser marker combination)",
+                arg, msgbuf, bufsize);
+        buffer = (char **)va_arg(*p_va, char **);
+        format++;
+        if (buffer == NULL)
+            return converterr("(buffer is NULL)",
+                              arg, msgbuf, bufsize);
+
+        /* Encode object */
+        if (!recode_strings && PyString_Check(arg)) {
+            s = arg;
+            Py_INCREF(s);
+        }
+        else {
+#ifdef Py_USING_UNICODE
+            PyObject *u;
+
+            /* Convert object to Unicode */
+            u = PyUnicode_FromObject(arg);
+            if (u == NULL)
+                return converterr(
+                    "string or unicode or text buffer",
+                    arg, msgbuf, bufsize);
+
+            /* Encode object; use default error handling */
+            s = PyUnicode_AsEncodedString(u,
+                                          encoding,
+                                          NULL);
+            Py_DECREF(u);
+            if (s == NULL)
+                return converterr("(encoding failed)",
+                                  arg, msgbuf, bufsize);
+            if (!PyString_Check(s)) {
+                Py_DECREF(s);
+                return converterr(
+                    "(encoder failed to return a string)",
+                    arg, msgbuf, bufsize);
+            }
 #else
-			return converterr("string<e>", arg, msgbuf, bufsize);
+            return converterr("string<e>", arg, msgbuf, bufsize);
 #endif
-		}
-		size = PyString_GET_SIZE(s);
+        }
+        size = PyString_GET_SIZE(s);
 
-		/* Write output; output is guaranteed to be 0-terminated */
-		if (*format == '#') { 
-			/* Using buffer length parameter '#':
-				   
-			   - if *buffer is NULL, a new buffer of the
-			   needed size is allocated and the data
-			   copied into it; *buffer is updated to point
-			   to the new buffer; the caller is
-			   responsible for PyMem_Free()ing it after
-			   usage 
+        /* Write output; output is guaranteed to be 0-terminated */
+        if (*format == '#') {
+            /* Using buffer length parameter '#':
 
-			   - if *buffer is not NULL, the data is
-			   copied to *buffer; *buffer_len has to be
-			   set to the size of the buffer on input;
-			   buffer overflow is signalled with an error;
-			   buffer has to provide enough room for the
-			   encoded string plus the trailing 0-byte
-			   
-			   - in both cases, *buffer_len is updated to
-			   the size of the buffer /excluding/ the
-			   trailing 0-byte 
-			   
-			*/
-			FETCH_SIZE;
+               - if *buffer is NULL, a new buffer of the
+               needed size is allocated and the data
+               copied into it; *buffer is updated to point
+               to the new buffer; the caller is
+               responsible for PyMem_Free()ing it after
+               usage
 
-			format++;
-			if (q == NULL && q2 == NULL) {
-				Py_DECREF(s);
-				return converterr(
-					"(buffer_len is NULL)",
-					arg, msgbuf, bufsize);
-			}
-			if (*buffer == NULL) {
-				*buffer = PyMem_NEW(char, size + 1);
-				if (*buffer == NULL) {
-					Py_DECREF(s);
-					return converterr(
-						"(memory error)",
-						arg, msgbuf, bufsize);
-				}
-				if (addcleanup(*buffer, freelist, cleanup_ptr)) {
-					Py_DECREF(s);
-					return converterr(
-						"(cleanup problem)",
-						arg, msgbuf, bufsize);
-				}
-			} else {
-				if (size + 1 > BUFFER_LEN) {
-					Py_DECREF(s);
-					return converterr(
-						"(buffer overflow)", 
-						arg, msgbuf, bufsize);
-				}
-			}
-			memcpy(*buffer,
-			       PyString_AS_STRING(s),
-			       size + 1);
-			STORE_SIZE(size);
-		} else {
-			/* Using a 0-terminated buffer:
-				   
-			   - the encoded string has to be 0-terminated
-			   for this variant to work; if it is not, an
-			   error raised 
+               - if *buffer is not NULL, the data is
+               copied to *buffer; *buffer_len has to be
+               set to the size of the buffer on input;
+               buffer overflow is signalled with an error;
+               buffer has to provide enough room for the
+               encoded string plus the trailing 0-byte
 
-			   - a new buffer of the needed size is
-			   allocated and the data copied into it;
-			   *buffer is updated to point to the new
-			   buffer; the caller is responsible for
-			   PyMem_Free()ing it after usage
+               - in both cases, *buffer_len is updated to
+               the size of the buffer /excluding/ the
+               trailing 0-byte
 
-			*/
-			if ((Py_ssize_t)strlen(PyString_AS_STRING(s))
-								!= size) {
-				Py_DECREF(s);
-				return converterr(
-					"encoded string without NULL bytes",
-					arg, msgbuf, bufsize);
-			}
-			*buffer = PyMem_NEW(char, size + 1);
-			if (*buffer == NULL) {
-				Py_DECREF(s);
-				return converterr("(memory error)",
-						  arg, msgbuf, bufsize);
-			}
-			if (addcleanup(*buffer, freelist, cleanup_ptr)) {
-				Py_DECREF(s);
-				return converterr("(cleanup problem)",
-						arg, msgbuf, bufsize);
-			}
-			memcpy(*buffer,
-			       PyString_AS_STRING(s),
-			       size + 1);
-		}
-		Py_DECREF(s);
-		break;
-	}
+            */
+            FETCH_SIZE;
+
+            format++;
+            if (q == NULL && q2 == NULL) {
+                Py_DECREF(s);
+                return converterr(
+                    "(buffer_len is NULL)",
+                    arg, msgbuf, bufsize);
+            }
+            if (*buffer == NULL) {
+                *buffer = PyMem_NEW(char, size + 1);
+                if (*buffer == NULL) {
+                    Py_DECREF(s);
+                    return converterr(
+                        "(memory error)",
+                        arg, msgbuf, bufsize);
+                }
+                if (addcleanup(*buffer, freelist, cleanup_ptr)) {
+                    Py_DECREF(s);
+                    return converterr(
+                        "(cleanup problem)",
+                        arg, msgbuf, bufsize);
+                }
+            } else {
+                if (size + 1 > BUFFER_LEN) {
+                    Py_DECREF(s);
+                    return converterr(
+                        "(buffer overflow)",
+                        arg, msgbuf, bufsize);
+                }
+            }
+            memcpy(*buffer,
+                   PyString_AS_STRING(s),
+                   size + 1);
+            STORE_SIZE(size);
+        } else {
+            /* Using a 0-terminated buffer:
+
+               - the encoded string has to be 0-terminated
+               for this variant to work; if it is not, an
+               error raised
+
+               - a new buffer of the needed size is
+               allocated and the data copied into it;
+               *buffer is updated to point to the new
+               buffer; the caller is responsible for
+               PyMem_Free()ing it after usage
+
+            */
+            if ((Py_ssize_t)strlen(PyString_AS_STRING(s))
+                                                    != size) {
+                Py_DECREF(s);
+                return converterr(
+                    "encoded string without NULL bytes",
+                    arg, msgbuf, bufsize);
+            }
+            *buffer = PyMem_NEW(char, size + 1);
+            if (*buffer == NULL) {
+                Py_DECREF(s);
+                return converterr("(memory error)",
+                                  arg, msgbuf, bufsize);
+            }
+            if (addcleanup(*buffer, freelist, cleanup_ptr)) {
+                Py_DECREF(s);
+                return converterr("(cleanup problem)",
+                                arg, msgbuf, bufsize);
+            }
+            memcpy(*buffer,
+                   PyString_AS_STRING(s),
+                   size + 1);
+        }
+        Py_DECREF(s);
+        break;
+    }
 
 #ifdef Py_USING_UNICODE
-	case 'u': {/* raw unicode buffer (Py_UNICODE *) */
-		if (*format == '#') { /* any buffer-like object */
-			void **p = (void **)va_arg(*p_va, char **);
-			FETCH_SIZE;
-			if (PyUnicode_Check(arg)) {
-			    	*p = PyUnicode_AS_UNICODE(arg);
-				STORE_SIZE(PyUnicode_GET_SIZE(arg));
-			}
-			else {
-				return converterr("cannot convert raw buffers",
-						  arg, msgbuf, bufsize);
-			}
-			format++;
-		} else {
-			Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
-			if (PyUnicode_Check(arg))
-				*p = PyUnicode_AS_UNICODE(arg);
-			else
-				return converterr("unicode", arg, msgbuf, bufsize);
-		}
-		break;
-	}
+    case 'u': {/* raw unicode buffer (Py_UNICODE *) */
+        if (*format == '#') { /* any buffer-like object */
+            void **p = (void **)va_arg(*p_va, char **);
+            FETCH_SIZE;
+            if (PyUnicode_Check(arg)) {
+                *p = PyUnicode_AS_UNICODE(arg);
+                STORE_SIZE(PyUnicode_GET_SIZE(arg));
+            }
+            else {
+                return converterr("cannot convert raw buffers",
+                                  arg, msgbuf, bufsize);
+            }
+            format++;
+        } else {
+            Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
+            if (PyUnicode_Check(arg))
+                *p = PyUnicode_AS_UNICODE(arg);
+            else
+                return converterr("unicode", arg, msgbuf, bufsize);
+        }
+        break;
+    }
 #endif
 
-	case 'S': { /* string object */
-		PyObject **p = va_arg(*p_va, PyObject **);
-		if (PyString_Check(arg))
-			*p = arg;
-		else
-			return converterr("string", arg, msgbuf, bufsize);
-		break;
-	}
-	
+    case 'S': { /* string object */
+        PyObject **p = va_arg(*p_va, PyObject **);
+        if (PyString_Check(arg))
+            *p = arg;
+        else
+            return converterr("string", arg, msgbuf, bufsize);
+        break;
+    }
+
 #ifdef Py_USING_UNICODE
-	case 'U': { /* Unicode object */
-		PyObject **p = va_arg(*p_va, PyObject **);
-		if (PyUnicode_Check(arg))
-			*p = arg;
-		else
-			return converterr("unicode", arg, msgbuf, bufsize);
-		break;
-	}
+    case 'U': { /* Unicode object */
+        PyObject **p = va_arg(*p_va, PyObject **);
+        if (PyUnicode_Check(arg))
+            *p = arg;
+        else
+            return converterr("unicode", arg, msgbuf, bufsize);
+        break;
+    }
 #endif
-	case 'O': { /* object */
-		PyTypeObject *type;
-		PyObject **p;
-		if (*format == '!') {
-			type = va_arg(*p_va, PyTypeObject*);
-			p = va_arg(*p_va, PyObject **);
-			format++;
-			if (PyType_IsSubtype(arg->ob_type, type))
-				*p = arg;
-			else
-				return converterr(type->tp_name, arg, msgbuf, bufsize);
 
-		}
-		else if (*format == '?') {
-			inquiry pred = va_arg(*p_va, inquiry);
-			p = va_arg(*p_va, PyObject **);
-			format++;
-			if ((*pred)(arg))
-				*p = arg;
-			else
-				return converterr("(unspecified)", 
-						  arg, msgbuf, bufsize);
-				
-		}
-		else if (*format == '&') {
-			typedef int (*converter)(PyObject *, void *);
-			converter convert = va_arg(*p_va, converter);
-			void *addr = va_arg(*p_va, void *);
-			format++;
-			if (! (*convert)(arg, addr))
-				return converterr("(unspecified)", 
-						  arg, msgbuf, bufsize);
-		}
-		else {
-			p = va_arg(*p_va, PyObject **);
-			*p = arg;
-		}
-		break;
-	}
-		
-	case 'w': { /* memory buffer, read-write access */
-    Py_FatalError("'w' unsupported\n");
-#if 0
-		void **p = va_arg(*p_va, void **);
-		void *res;
-		PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
-		Py_ssize_t count;
+    case 'O': { /* object */
+        PyTypeObject *type;
+        PyObject **p;
+        if (*format == '!') {
+            type = va_arg(*p_va, PyTypeObject*);
+            p = va_arg(*p_va, PyObject **);
+            format++;
+            if (PyType_IsSubtype(arg->ob_type, type))
+                *p = arg;
+            else
+                return converterr(type->tp_name, arg, msgbuf, bufsize);
 
-		if (pb && pb->bf_releasebuffer && *format != '*')
-			/* Buffer must be released, yet caller does not use
-			   the Py_buffer protocol. */
-			return converterr("pinned buffer", arg, msgbuf, bufsize);
+        }
+        else if (*format == '?') {
+            inquiry pred = va_arg(*p_va, inquiry);
+            p = va_arg(*p_va, PyObject **);
+            format++;
+            if ((*pred)(arg))
+                *p = arg;
+            else
+                return converterr("(unspecified)",
+                                  arg, msgbuf, bufsize);
 
-		if (pb && pb->bf_getbuffer && *format == '*') {
-			/* Caller is interested in Py_buffer, and the object
-			   supports it directly. */
-			format++;
-			if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
-				PyErr_Clear();
-				return converterr("read-write buffer", arg, msgbuf, bufsize);
-			}
-			if (addcleanup(p, freelist, cleanup_buffer)) {
-				return converterr(
-					"(cleanup problem)",
-					arg, msgbuf, bufsize);
-			}
-			if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C'))
-				return converterr("contiguous buffer", arg, msgbuf, bufsize);
-			break;
-		}
+        }
+        else if (*format == '&') {
+            typedef int (*converter)(PyObject *, void *);
+            converter convert = va_arg(*p_va, converter);
+            void *addr = va_arg(*p_va, void *);
+            format++;
+            if (! (*convert)(arg, addr))
+                return converterr("(unspecified)",
+                                  arg, msgbuf, bufsize);
+        }
+        else {
+            p = va_arg(*p_va, PyObject **);
+            *p = arg;
+        }
+        break;
+    }
 
-		if (pb == NULL ||
-		    pb->bf_getwritebuffer == NULL ||
-		    pb->bf_getsegcount == NULL)
-			return converterr("read-write buffer", arg, msgbuf, bufsize);
-		if ((*pb->bf_getsegcount)(arg, NULL) != 1)
-			return converterr("single-segment read-write buffer", 
-					  arg, msgbuf, bufsize);
-		if ((count = pb->bf_getwritebuffer(arg, 0, &res)) < 0)
-			return converterr("(unspecified)", arg, msgbuf, bufsize);
-		if (*format == '*') {
-			PyBuffer_FillInfo((Py_buffer*)p, arg, res, count, 1, 0);
-			format++;
-		}
-		else {
-			*p = res;
-			if (*format == '#') {
-				FETCH_SIZE;
-				STORE_SIZE(count);
-				format++;
-			}
-		}
-		break;
-#endif
-	}
-		
-	case 't': { /* 8-bit character buffer, read-only access */
-		char **p = va_arg(*p_va, char **);
-		PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
-		Py_ssize_t count;
 
-#if 0
-		if (*format++ != '#')
-			return converterr(
-				"invalid use of 't' format character", 
-				arg, msgbuf, bufsize);
-#endif
-               if (!PyType_HasFeature(arg->ob_type,
-				       Py_TPFLAGS_HAVE_GETCHARBUFFER)
-#if 0
-		    || pb == NULL || pb->bf_getcharbuffer == NULL ||
-		    pb->bf_getsegcount == NULL
-#endif
-                    )
-			return converterr(
-				"string or read-only character buffer",
-				arg, msgbuf, bufsize);
-#if 0
-		if (pb->bf_getsegcount(arg, NULL) != 1)
-			return converterr(
-				"string or single-segment read-only buffer",
-				arg, msgbuf, bufsize);
+    case 'w': { /* memory buffer, read-write access */
+        void **p = va_arg(*p_va, void **);
+        void *res;
+        PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
+        Py_ssize_t count;
 
-		if (pb->bf_releasebuffer)
-			return converterr(
-				"string or pinned buffer",
-				arg, msgbuf, bufsize);
-#endif
-		count = pb->bf_getcharbuffer(arg, 0, p);
-#if 0
-		if (count < 0)
-			return converterr("(unspecified)", arg, msgbuf, bufsize);
-#endif
-		{
-			FETCH_SIZE;
-			STORE_SIZE(count);
-                        ++format;
-		}
-		break;
-	}
-	default:
-		return converterr("impossible<bad format char>", arg, msgbuf, bufsize);
-	
-	}
-	
-	*p_format = format;
-	return NULL;
+        if (pb && pb->bf_releasebuffer && *format != '*')
+            /* Buffer must be released, yet caller does not use
+               the Py_buffer protocol. */
+            return converterr("pinned buffer", arg, msgbuf, bufsize);
+
+        if (pb && pb->bf_getbuffer && *format == '*') {
+            /* Caller is interested in Py_buffer, and the object
+               supports it directly. */
+            format++;
+            if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
+                PyErr_Clear();
+                return converterr("read-write buffer", arg, msgbuf, bufsize);
+            }
+            if (addcleanup(p, freelist, cleanup_buffer)) {
+                return converterr(
+                    "(cleanup problem)",
+                    arg, msgbuf, bufsize);
+            }
+            if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C'))
+                return converterr("contiguous buffer", arg, msgbuf, bufsize);
+            break;
+        }
+
+        if (pb == NULL ||
+            pb->bf_getwritebuffer == NULL ||
+            pb->bf_getsegcount == NULL)
+            return converterr("read-write buffer", arg, msgbuf, bufsize);
+        if ((*pb->bf_getsegcount)(arg, NULL) != 1)
+            return converterr("single-segment read-write buffer",
+                              arg, msgbuf, bufsize);
+        if ((count = pb->bf_getwritebuffer(arg, 0, &res)) < 0)
+            return converterr("(unspecified)", arg, msgbuf, bufsize);
+        if (*format == '*') {
+            PyBuffer_FillInfo((Py_buffer*)p, arg, res, count, 1, 0);
+            format++;
+        }
+        else {
+            *p = res;
+            if (*format == '#') {
+                FETCH_SIZE;
+                STORE_SIZE(count);
+                format++;
+            }
+        }
+        break;
+    }
+
+    case 't': { /* 8-bit character buffer, read-only access */
+        char **p = va_arg(*p_va, char **);
+        PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
+        Py_ssize_t count;
+
+        if (*format++ != '#')
+            return converterr(
+                "invalid use of 't' format character",
+                arg, msgbuf, bufsize);
+        if (!PyType_HasFeature(arg->ob_type,
+                               Py_TPFLAGS_HAVE_GETCHARBUFFER) ||
+            pb == NULL || pb->bf_getcharbuffer == NULL ||
+            pb->bf_getsegcount == NULL)
+            return converterr(
+                "string or read-only character buffer",
+                arg, msgbuf, bufsize);
+
+        if (pb->bf_getsegcount(arg, NULL) != 1)
+            return converterr(
+                "string or single-segment read-only buffer",
+                arg, msgbuf, bufsize);
+
+        if (pb->bf_releasebuffer)
+            return converterr(
+                "string or pinned buffer",
+                arg, msgbuf, bufsize);
+
+        count = pb->bf_getcharbuffer(arg, 0, p);
+        if (count < 0)
+            return converterr("(unspecified)", arg, msgbuf, bufsize);
+        {
+            FETCH_SIZE;
+            STORE_SIZE(count);
+        }
+        break;
+    }
+
+    default:
+        return converterr("impossible<bad format char>", arg, msgbuf, bufsize);
+
+    }
+
+    *p_format = format;
+    return NULL;
 }
 
 static Py_ssize_t
 convertbuffer(PyObject *arg, void **p, char **errmsg)
 {
-	PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
-	Py_ssize_t count;
-	if (pb == NULL ||
-	    pb->bf_getreadbuffer == NULL ||
-	    pb->bf_getsegcount == NULL ||
-	    pb->bf_releasebuffer != NULL) {
-		*errmsg = "string or read-only buffer";
-		return -1;
-	}
-	if ((*pb->bf_getsegcount)(arg, NULL) != 1) {
-		*errmsg = "string or single-segment read-only buffer";
-		return -1;
-	}
-	if ((count = (*pb->bf_getreadbuffer)(arg, 0, p)) < 0) {
-		*errmsg = "(unspecified)";
-	}
-	return count;
+    PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
+    Py_ssize_t count;
+    if (pb == NULL ||
+        pb->bf_getreadbuffer == NULL ||
+        pb->bf_getsegcount == NULL ||
+        pb->bf_releasebuffer != NULL) {
+        *errmsg = "string or read-only buffer";
+        return -1;
+    }
+    if ((*pb->bf_getsegcount)(arg, NULL) != 1) {
+        *errmsg = "string or single-segment read-only buffer";
+        return -1;
+    }
+    if ((count = (*pb->bf_getreadbuffer)(arg, 0, p)) < 0) {
+        *errmsg = "(unspecified)";
+    }
+    return count;
 }
 
 static int
 getbuffer(PyObject *arg, Py_buffer *view, char **errmsg)
 {
-	void *buf;
-	Py_ssize_t count;
-	PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
-	if (pb == NULL) {
-		*errmsg = "string or buffer";
-		return -1;
-	}
-	if (pb->bf_getbuffer) {
-		if (pb->bf_getbuffer(arg, view, 0) < 0) {
-			*errmsg = "convertible to a buffer";
-			return -1;
-		}
-		if (!PyBuffer_IsContiguous(view, 'C')) {
-			*errmsg = "contiguous buffer";
-			return -1;
-		}
-		return 0;
-	}
+    void *buf;
+    Py_ssize_t count;
+    PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
+    if (pb == NULL) {
+        *errmsg = "string or buffer";
+        return -1;
+    }
+    if (pb->bf_getbuffer) {
+        if (pb->bf_getbuffer(arg, view, 0) < 0) {
+            *errmsg = "convertible to a buffer";
+            return -1;
+        }
+        if (!PyBuffer_IsContiguous(view, 'C')) {
+            *errmsg = "contiguous buffer";
+            return -1;
+        }
+        return 0;
+    }
 
-	count = convertbuffer(arg, &buf, errmsg);
-	if (count < 0) {
-		*errmsg = "convertible to a buffer";
-		return count;
-	}
-	PyBuffer_FillInfo(view, NULL, buf, count, 1, 0);
-	return 0;
+    count = convertbuffer(arg, &buf, errmsg);
+    if (count < 0) {
+        *errmsg = "convertible to a buffer";
+        return count;
+    }
+    PyBuffer_FillInfo(view, arg, buf, count, 1, 0);
+    return 0;
 }
 
 /* Support for keyword arguments donated by
@@ -1395,501 +1410,487 @@
 /* Return false (0) for error, else true. */
 int
 PyArg_ParseTupleAndKeywords(PyObject *args,
-			    PyObject *keywords,
-			    const char *format, 
-			    char **kwlist, ...)
+                            PyObject *keywords,
+                            const char *format,
+                            char **kwlist, ...)
 {
-	int retval;
-	va_list va;
+    int retval;
+    va_list va;
 
-	if ((args == NULL || !PyTuple_Check(args)) ||
-      (keywords != NULL && !PyDict_Check(keywords)) ||
-	    format == NULL ||
-	    kwlist == NULL)
-	{
-		PyErr_BadInternalCall();
-		return 0;
-	}
+    if ((args == NULL || !PyTuple_Check(args)) ||
+        (keywords != NULL && !PyDict_Check(keywords)) ||
+        format == NULL ||
+        kwlist == NULL)
+    {
+        PyErr_BadInternalCall();
+        return 0;
+    }
 
-	va_start(va, kwlist);
-	retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0);	
-	va_end(va);
-	return retval;
+    va_start(va, kwlist);
+    retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0);
+    va_end(va);
+    return retval;
 }
 
 int
 _PyArg_ParseTupleAndKeywords_SizeT(PyObject *args,
-				  PyObject *keywords,
-				  const char *format, 
-				  char **kwlist, ...)
+                                  PyObject *keywords,
+                                  const char *format,
+                                  char **kwlist, ...)
 {
-	int retval;
-	va_list va;
+    int retval;
+    va_list va;
 
-	if ((args == NULL || !PyTuple_Check(args)) ||
-	    (keywords != NULL && !PyDict_Check(keywords)) ||
-	    format == NULL ||
-	    kwlist == NULL)
-	{
-		PyErr_BadInternalCall();
-		return 0;
-	}
+    if ((args == NULL || !PyTuple_Check(args)) ||
+        (keywords != NULL && !PyDict_Check(keywords)) ||
+        format == NULL ||
+        kwlist == NULL)
+    {
+        PyErr_BadInternalCall();
+        return 0;
+    }
 
-	va_start(va, kwlist);
-	retval = vgetargskeywords(args, keywords, format, 
-				  kwlist, &va, FLAG_SIZE_T);
-	va_end(va);
-	return retval;
+    va_start(va, kwlist);
+    retval = vgetargskeywords(args, keywords, format,
+                              kwlist, &va, FLAG_SIZE_T);
+    va_end(va);
+    return retval;
 }
 
 
 int
 PyArg_VaParseTupleAndKeywords(PyObject *args,
                               PyObject *keywords,
-                              const char *format, 
+                              const char *format,
                               char **kwlist, va_list va)
 {
-	int retval;
-	va_list lva;
+    int retval;
+    va_list lva;
 
-	if ((args == NULL || !PyTuple_Check(args)) ||
-	    (keywords != NULL && !PyDict_Check(keywords)) ||
-	    format == NULL ||
-	    kwlist == NULL)
-	{
-		PyErr_BadInternalCall();
-		return 0;
-	}
+    if ((args == NULL || !PyTuple_Check(args)) ||
+        (keywords != NULL && !PyDict_Check(keywords)) ||
+        format == NULL ||
+        kwlist == NULL)
+    {
+        PyErr_BadInternalCall();
+        return 0;
+    }
 
 #ifdef VA_LIST_IS_ARRAY
-	memcpy(lva, va, sizeof(va_list));
+    memcpy(lva, va, sizeof(va_list));
 #else
 #ifdef __va_copy
-	__va_copy(lva, va);
+    __va_copy(lva, va);
 #else
-	lva = va;
+    lva = va;
 #endif
 #endif
 
-	retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0);	
-	return retval;
+    retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0);
+    return retval;
 }
 
 int
 _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args,
-				    PyObject *keywords,
-				    const char *format, 
-				    char **kwlist, va_list va)
+                                    PyObject *keywords,
+                                    const char *format,
+                                    char **kwlist, va_list va)
 {
-	int retval;
-	va_list lva;
+    int retval;
+    va_list lva;
 
-	if ((args == NULL || !PyTuple_Check(args)) ||
-	    (keywords != NULL && !PyDict_Check(keywords)) ||
-	    format == NULL ||
-	    kwlist == NULL)
-	{
-		PyErr_BadInternalCall();
-		return 0;
-	}
+    if ((args == NULL || !PyTuple_Check(args)) ||
+        (keywords != NULL && !PyDict_Check(keywords)) ||
+        format == NULL ||
+        kwlist == NULL)
+    {
+        PyErr_BadInternalCall();
+        return 0;
+    }
 
 #ifdef VA_LIST_IS_ARRAY
-	memcpy(lva, va, sizeof(va_list));
+    memcpy(lva, va, sizeof(va_list));
 #else
 #ifdef __va_copy
-	__va_copy(lva, va);
+    __va_copy(lva, va);
 #else
-	lva = va;
+    lva = va;
 #endif
 #endif
 
-	retval = vgetargskeywords(args, keywords, format, 
-				  kwlist, &lva, FLAG_SIZE_T);
-	return retval;
+    retval = vgetargskeywords(args, keywords, format,
+                              kwlist, &lva, FLAG_SIZE_T);
+    return retval;
 }
 
 #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':')
 
 static int
 vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
-	         char **kwlist, va_list *p_va, int flags)
+                 char **kwlist, va_list *p_va, int flags)
 {
-	char msgbuf[512];
-	int levels[32];
-	const char *fname, *msg, *custom_msg, *keyword;
-	int min = INT_MAX;
-	int i, len, nargs, nkeywords;
-	PyObject *current_arg;
-	freelist_t freelist = {0, NULL};
+    char msgbuf[512];
+    int levels[32];
+    const char *fname, *msg, *custom_msg, *keyword;
+    int min = INT_MAX;
+    int i, len, nargs, nkeywords;
+    PyObject *freelist = NULL, *current_arg;
 
+    assert(args != NULL && PyTuple_Check(args));
+    assert(keywords == NULL || PyDict_Check(keywords));
+    assert(format != NULL);
+    assert(kwlist != NULL);
+    assert(p_va != NULL);
 
-	assert(args != NULL && PyTuple_Check(args));
-	assert(keywords == NULL || PyDict_Check(keywords));
-	assert(format != NULL);
-	assert(kwlist != NULL);
-	assert(p_va != NULL);
+    /* grab the function name or custom error msg first (mutually exclusive) */
+    fname = strchr(format, ':');
+    if (fname) {
+        fname++;
+        custom_msg = NULL;
+    }
+    else {
+        custom_msg = strchr(format,';');
+        if (custom_msg)
+            custom_msg++;
+    }
 
-	/* grab the function name or custom error msg first (mutually exclusive) */
-	fname = strchr(format, ':');
-	if (fname) {
-		fname++;
-		custom_msg = NULL;
-	}
-	else {
-		custom_msg = strchr(format,';');
-		if (custom_msg)
-			custom_msg++;
-	}
+    /* scan kwlist and get greatest possible nbr of args */
+    for (len=0; kwlist[len]; len++)
+        continue;
 
-	/* scan kwlist and get greatest possible nbr of args */
-	for (len=0; kwlist[len]; len++)
-		continue;
+    nargs = PyTuple_GET_SIZE(args);
+    nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords);
+    if (nargs + nkeywords > len) {
+        PyErr_Format(PyExc_TypeError, "%s%s takes at most %d "
+                     "argument%s (%d given)",
+                     (fname == NULL) ? "function" : fname,
+                     (fname == NULL) ? "" : "()",
+                     len,
+                     (len == 1) ? "" : "s",
+                     nargs + nkeywords);
+        return 0;
+    }
 
-	freelist.entries = PyMem_New(freelistentry_t, len);
+    /* convert tuple args and keyword args in same loop, using kwlist to drive process */
+    for (i = 0; i < len; i++) {
+        keyword = kwlist[i];
+        if (*format == '|') {
+            min = i;
+            format++;
+        }
+        if (IS_END_OF_FORMAT(*format)) {
+            PyErr_Format(PyExc_RuntimeError,
+                         "More keyword list entries (%d) than "
+                         "format specifiers (%d)", len, i);
+            return cleanreturn(0, freelist);
+        }
+        current_arg = NULL;
+        if (nkeywords) {
+            current_arg = PyDict_GetItemString(keywords, keyword);
+        }
+        if (current_arg) {
+            --nkeywords;
+            if (i < nargs) {
+                /* arg present in tuple and in dict */
+                PyErr_Format(PyExc_TypeError,
+                             "Argument given by name ('%s') "
+                             "and position (%d)",
+                             keyword, i+1);
+                return cleanreturn(0, freelist);
+            }
+        }
+        else if (nkeywords && PyErr_Occurred())
+            return cleanreturn(0, freelist);
+        else if (i < nargs)
+            current_arg = PyTuple_GET_ITEM(args, i);
 
-	nargs = PyTuple_GET_SIZE(args);
-	nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords);
-	if (nargs + nkeywords > len) {
-		PyErr_Format(PyExc_TypeError, "%s%s takes at most %d "
-			     "argument%s (%d given)",
-			     (fname == NULL) ? "function" : fname,
-			     (fname == NULL) ? "" : "()",
-			     len,
-			     (len == 1) ? "" : "s",
-			     nargs + nkeywords);
-		return cleanreturn(0, &freelist);
-	}
+        if (current_arg) {
+            msg = convertitem(current_arg, &format, p_va, flags,
+                levels, msgbuf, sizeof(msgbuf), &freelist);
+            if (msg) {
+                seterror(i+1, msg, levels, fname, custom_msg);
+                return cleanreturn(0, freelist);
+            }
+            continue;
+        }
 
-	/* convert tuple args and keyword args in same loop, using kwlist to drive process */
-	for (i = 0; i < len; i++) {
-		keyword = kwlist[i];
-		if (*format == '|') {
-			min = i;
-			format++;
-		}
-		if (IS_END_OF_FORMAT(*format)) {
-			PyErr_Format(PyExc_RuntimeError,
-				     "More keyword list entries (%d) than "
-				     "format specifiers (%d)", len, i);
-			return cleanreturn(0, &freelist);
-		}
-		current_arg = NULL;
-		if (nkeywords) {
-			current_arg = PyDict_GetItemString(keywords, keyword);
-		}
-		if (current_arg) {
-			--nkeywords;
-			if (i < nargs) {
-				/* arg present in tuple and in dict */
-				PyErr_Format(PyExc_TypeError,
-					     "Argument given by name ('%s') "
-					     "and position (%d)",
-					     keyword, i+1);
-				return cleanreturn(0, &freelist);
-			}
-		}
-		else if (nkeywords && PyErr_Occurred())
-			return cleanreturn(0, &freelist);
-		else if (i < nargs)
-			current_arg = PyTuple_GET_ITEM(args, i);
-			
-		if (current_arg) {
-			msg = convertitem(current_arg, &format, p_va, flags,
-				levels, msgbuf, sizeof(msgbuf), &freelist);
-			if (msg) {
-				seterror(i+1, msg, levels, fname, custom_msg);
-				return cleanreturn(0, &freelist);
-			}
-			continue;
-		}
+        if (i < min) {
+            PyErr_Format(PyExc_TypeError, "Required argument "
+                         "'%s' (pos %d) not found",
+                         keyword, i+1);
+            return cleanreturn(0, freelist);
+        }
+        /* current code reports success when all required args
+         * fulfilled and no keyword args left, with no further
+         * validation. XXX Maybe skip this in debug build ?
+         */
+        if (!nkeywords)
+            return cleanreturn(1, freelist);
 
-		if (i < min) {
-			PyErr_Format(PyExc_TypeError, "Required argument "
-				     "'%s' (pos %d) not found",
-				     keyword, i+1);
-			return cleanreturn(0, &freelist);
-		}
-		/* current code reports success when all required args
-		 * fulfilled and no keyword args left, with no further
-		 * validation. XXX Maybe skip this in debug build ?
-		 */
-		if (!nkeywords)
-			return cleanreturn(1, &freelist);
+        /* We are into optional args, skip thru to any remaining
+         * keyword args */
+        msg = skipitem(&format, p_va, flags);
+        if (msg) {
+            PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg,
+                         format);
+            return cleanreturn(0, freelist);
+        }
+    }
 
-		/* We are into optional args, skip thru to any remaining
-		 * keyword args */
-		msg = skipitem(&format, p_va, flags);
-		if (msg) {
-			PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg,
-				     format);
-			return cleanreturn(0, &freelist);
-		}
-	}
+    if (!IS_END_OF_FORMAT(*format) && *format != '|') {
+        PyErr_Format(PyExc_RuntimeError,
+            "more argument specifiers than keyword list entries "
+            "(remaining format:'%s')", format);
+        return cleanreturn(0, freelist);
+    }
 
-	if (!IS_END_OF_FORMAT(*format) && *format != '|') {
-		PyErr_Format(PyExc_RuntimeError,
-			"more argument specifiers than keyword list entries "
-			"(remaining format:'%s')", format);
-		return cleanreturn(0, &freelist);
-	}
+    /* make sure there are no extraneous keyword arguments */
+    if (nkeywords > 0) {
+        PyObject *key, *value;
+        Py_ssize_t pos = 0;
+        while (PyDict_Next(keywords, &pos, &key, &value)) {
+            int match = 0;
+            char *ks;
+            if (!PyString_Check(key)) {
+                PyErr_SetString(PyExc_TypeError,
+                                "keywords must be strings");
+                return cleanreturn(0, freelist);
+            }
+            ks = PyString_AsString(key);
+            for (i = 0; i < len; i++) {
+                if (!strcmp(ks, kwlist[i])) {
+                    match = 1;
+                    break;
+                }
+            }
+            if (!match) {
+                PyErr_Format(PyExc_TypeError,
+                             "'%s' is an invalid keyword "
+                             "argument for this function",
+                             ks);
+                return cleanreturn(0, freelist);
+            }
+        }
+    }
 
-	/* make sure there are no extraneous keyword arguments */
-	if (nkeywords > 0) {
-		PyObject *key, *value;
-		Py_ssize_t pos = 0;
-		while (PyDict_Next(keywords, &pos, &key, &value)) {
-			int match = 0;
-			char *ks;
-			if (!PyString_Check(key)) {
-                            PyErr_SetString(PyExc_TypeError, 
-					        "keywords must be strings");
-				return cleanreturn(0, &freelist);
-			}
-			ks = PyString_AsString(key);
-			for (i = 0; i < len; i++) {
-				if (!strcmp(ks, kwlist[i])) {
-					match = 1;
-					break;
-				}
-			}
-			if (!match) {
-				PyErr_Format(PyExc_TypeError,
-					     "'%s' is an invalid keyword "
-					     "argument for this function",
-					     ks);
-				return cleanreturn(0, &freelist);
-			}
-		}
-	}
-
-	return cleanreturn(1, &freelist);
+    return cleanreturn(1, freelist);
 }
 
 
 static char *
 skipitem(const char **p_format, va_list *p_va, int flags)
 {
-	const char *format = *p_format;
-	char c = *format++;
-	
-	switch (c) {
+    const char *format = *p_format;
+    char c = *format++;
 
-	/* simple codes
-	 * The individual types (second arg of va_arg) are irrelevant */
+    switch (c) {
 
-	case 'b': /* byte -- very short int */
-	case 'B': /* byte as bitfield */
-	case 'h': /* short int */
-	case 'H': /* short int as bitfield */
-	case 'i': /* int */
-	case 'I': /* int sized bitfield */
-	case 'l': /* long int */
-	case 'k': /* long int sized bitfield */
+    /* simple codes
+     * The individual types (second arg of va_arg) are irrelevant */
+
+    case 'b': /* byte -- very short int */
+    case 'B': /* byte as bitfield */
+    case 'h': /* short int */
+    case 'H': /* short int as bitfield */
+    case 'i': /* int */
+    case 'I': /* int sized bitfield */
+    case 'l': /* long int */
+    case 'k': /* long int sized bitfield */
 #ifdef HAVE_LONG_LONG
-	case 'L': /* PY_LONG_LONG */
-	case 'K': /* PY_LONG_LONG sized bitfield */
+    case 'L': /* PY_LONG_LONG */
+    case 'K': /* PY_LONG_LONG sized bitfield */
 #endif
-	case 'f': /* float */
-	case 'd': /* double */
+    case 'f': /* float */
+    case 'd': /* double */
 #ifndef WITHOUT_COMPLEX
-	case 'D': /* complex double */
+    case 'D': /* complex double */
 #endif
-	case 'c': /* char */
-		{
-			(void) va_arg(*p_va, void *);
-			break;
-		}
+    case 'c': /* char */
+        {
+            (void) va_arg(*p_va, void *);
+            break;
+        }
 
-	case 'n': /* Py_ssize_t */
-		{
-			(void) va_arg(*p_va, Py_ssize_t *);
-			break;
-		}
-	
-	/* string codes */
-		
-	case 'e': /* string with encoding */
-		{
-			(void) va_arg(*p_va, const char *);
-			if (!(*format == 's' || *format == 't'))
-				/* after 'e', only 's' and 't' is allowed */
-				goto err;
-			format++;
-			/* explicit fallthrough to string cases */
-		}
-	
-	case 's': /* string */
-	case 'z': /* string or None */
+    case 'n': /* Py_ssize_t */
+        {
+            (void) va_arg(*p_va, Py_ssize_t *);
+            break;
+        }
+
+    /* string codes */
+
+    case 'e': /* string with encoding */
+        {
+            (void) va_arg(*p_va, const char *);
+            if (!(*format == 's' || *format == 't'))
+                /* after 'e', only 's' and 't' is allowed */
+                goto err;
+            format++;
+            /* explicit fallthrough to string cases */
+        }
+
+    case 's': /* string */
+    case 'z': /* string or None */
 #ifdef Py_USING_UNICODE
-	case 'u': /* unicode string */
+    case 'u': /* unicode string */
 #endif
-	case 't': /* buffer, read-only */
-	case 'w': /* buffer, read-write */
-		{
-			(void) va_arg(*p_va, char **);
-			if (*format == '#') {
-				if (flags & FLAG_SIZE_T)
-					(void) va_arg(*p_va, Py_ssize_t *);
-				else
-					(void) va_arg(*p_va, int *);
-				format++;
-			} else if ((c == 's' || c == 'z') && *format == '*') {
-				format++;
-			}
-			break;
-		}
+    case 't': /* buffer, read-only */
+    case 'w': /* buffer, read-write */
+        {
+            (void) va_arg(*p_va, char **);
+            if (*format == '#') {
+                if (flags & FLAG_SIZE_T)
+                    (void) va_arg(*p_va, Py_ssize_t *);
+                else
+                    (void) va_arg(*p_va, int *);
+                format++;
+            } else if ((c == 's' || c == 'z') && *format == '*') {
+                format++;
+            }
+            break;
+        }
 
-	/* object codes */
+    /* object codes */
 
-	case 'S': /* string object */
+    case 'S': /* string object */
 #ifdef Py_USING_UNICODE
-	case 'U': /* unicode string object */
+    case 'U': /* unicode string object */
 #endif
-		{
-			(void) va_arg(*p_va, PyObject **);
-			break;
-		}
-	
-	case 'O': /* object */
-		{
-			if (*format == '!') {
-				format++;
-				(void) va_arg(*p_va, PyTypeObject*);
-				(void) va_arg(*p_va, PyObject **);
-			}
-#if 0
-/* I don't know what this is for */
-			else if (*format == '?') {
-				inquiry pred = va_arg(*p_va, inquiry);
-				format++;
-				if ((*pred)(arg)) {
-					(void) va_arg(*p_va, PyObject **);
-				}
-			}
-#endif
-			else if (*format == '&') {
-				typedef int (*converter)(PyObject *, void *);
-				(void) va_arg(*p_va, converter);
-				(void) va_arg(*p_va, void *);
-				format++;
-			}
-			else {
-				(void) va_arg(*p_va, PyObject **);
-			}
-			break;
-		}
+        {
+            (void) va_arg(*p_va, PyObject **);
+            break;
+        }
 
-	case '(':	/* bypass tuple, not handled at all previously */
-		{
-			char *msg;
-			for (;;) {
-				if (*format==')')
-					break;
-				if (IS_END_OF_FORMAT(*format))
-					return "Unmatched left paren in format "
-					       "string";
-				msg = skipitem(&format, p_va, flags);
-				if (msg)
-					return msg;
-			}
-			format++;
-			break;
-		}
+    case 'O': /* object */
+        {
+            if (*format == '!') {
+                format++;
+                (void) va_arg(*p_va, PyTypeObject*);
+                (void) va_arg(*p_va, PyObject **);
+            }
+            else if (*format == '&') {
+                typedef int (*converter)(PyObject *, void *);
+                (void) va_arg(*p_va, converter);
+                (void) va_arg(*p_va, void *);
+                format++;
+            }
+            else {
+                (void) va_arg(*p_va, PyObject **);
+            }
+            break;
+        }
 
-	case ')':
-		return "Unmatched right paren in format string";
+    case '(':           /* bypass tuple, not handled at all previously */
+        {
+            char *msg;
+            for (;;) {
+                if (*format==')')
+                    break;
+                if (IS_END_OF_FORMAT(*format))
+                    return "Unmatched left paren in format "
+                           "string";
+                msg = skipitem(&format, p_va, flags);
+                if (msg)
+                    return msg;
+            }
+            format++;
+            break;
+        }
 
-	default:
+    case ')':
+        return "Unmatched right paren in format string";
+
+    default:
 err:
-		return "impossible<bad format char>";
-	
-	}
+        return "impossible<bad format char>";
 
-	*p_format = format;
-	return NULL;
+    }
+
+    *p_format = format;
+    return NULL;
 }
 
 
 int
 PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
 {
-	Py_ssize_t i, l;
-	PyObject **o;
-	va_list vargs;
+    Py_ssize_t i, l;
+    PyObject **o;
+    va_list vargs;
 
 #ifdef HAVE_STDARG_PROTOTYPES
-	va_start(vargs, max);
+    va_start(vargs, max);
 #else
-	va_start(vargs);
+    va_start(vargs);
 #endif
 
-	assert(min >= 0);
-	assert(min <= max);
-	if (!PyTuple_Check(args)) {
-		PyErr_SetString(PyExc_SystemError,
-		    "PyArg_UnpackTuple() argument list is not a tuple");
-		return 0;
-	}	
-	l = PyTuple_GET_SIZE(args);
-	if (l < min) {
-		if (name != NULL)
-			PyErr_Format(
-			    PyExc_TypeError,
-			    "%s expected %s%zd arguments, got %zd", 
-			    name, (min == max ? "" : "at least "), min, l);
-		else
-			PyErr_Format(
-			    PyExc_TypeError,
-			    "unpacked tuple should have %s%zd elements,"
-			    " but has %zd", 
-			    (min == max ? "" : "at least "), min, l);
-		va_end(vargs);
-		return 0;
-	}
-	if (l > max) {
-		if (name != NULL)
-			PyErr_Format(
-			    PyExc_TypeError,
-			    "%s expected %s%zd arguments, got %zd", 
-			    name, (min == max ? "" : "at most "), max, l);
-		else
-			PyErr_Format(
-			    PyExc_TypeError,
-			    "unpacked tuple should have %s%zd elements,"
-			    " but has %zd", 
-			    (min == max ? "" : "at most "), max, l);
-		va_end(vargs);
-		return 0;
-	}
-	for (i = 0; i < l; i++) {
-		o = va_arg(vargs, PyObject **);
-		*o = PyTuple_GET_ITEM(args, i);
-	}
-	va_end(vargs);
-	return 1;
+    assert(min >= 0);
+    assert(min <= max);
+    if (!PyTuple_Check(args)) {
+        PyErr_SetString(PyExc_SystemError,
+            "PyArg_UnpackTuple() argument list is not a tuple");
+        return 0;
+    }
+    l = PyTuple_GET_SIZE(args);
+    if (l < min) {
+        if (name != NULL)
+            PyErr_Format(
+                PyExc_TypeError,
+                "%s expected %s%zd arguments, got %zd",
+                name, (min == max ? "" : "at least "), min, l);
+        else
+            PyErr_Format(
+                PyExc_TypeError,
+                "unpacked tuple should have %s%zd elements,"
+                " but has %zd",
+                (min == max ? "" : "at least "), min, l);
+        va_end(vargs);
+        return 0;
+    }
+    if (l > max) {
+        if (name != NULL)
+            PyErr_Format(
+                PyExc_TypeError,
+                "%s expected %s%zd arguments, got %zd",
+                name, (min == max ? "" : "at most "), max, l);
+        else
+            PyErr_Format(
+                PyExc_TypeError,
+                "unpacked tuple should have %s%zd elements,"
+                " but has %zd",
+                (min == max ? "" : "at most "), max, l);
+        va_end(vargs);
+        return 0;
+    }
+    for (i = 0; i < l; i++) {
+        o = va_arg(vargs, PyObject **);
+        *o = PyTuple_GET_ITEM(args, i);
+    }
+    va_end(vargs);
+    return 1;
 }
 
 
 /* For type constructors that don't take keyword args
  *
- * Sets a TypeError and returns 0 if the kwds dict is 
+ * Sets a TypeError and returns 0 if the kwds dict is
  * not empty, returns 1 otherwise
  */
 int
 _PyArg_NoKeywords(const char *funcname, PyObject *kw)
 {
-	if (kw == NULL)
-		return 1;
-	if (!PyDict_CheckExact(kw)) {
-		PyErr_BadInternalCall();
-		return 0;
-	}
-	if (PyDict_Size(kw) == 0)
-		return 1;
-	
-	PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments", 
-			funcname);
-	return 0;
+    if (kw == NULL)
+        return 1;
+    if (!PyDict_CheckExact(kw)) {
+        PyErr_BadInternalCall();
+        return 0;
+    }
+    if (PyDict_Size(kw) == 0)
+        return 1;
+
+    PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments",
+                    funcname);
+    return 0;
 }
 #ifdef __cplusplus
 };
diff --git a/pypy/module/cpyext/src/modsupport.c b/pypy/module/cpyext/src/modsupport.c
--- a/pypy/module/cpyext/src/modsupport.c
+++ b/pypy/module/cpyext/src/modsupport.c
@@ -33,41 +33,41 @@
 static int
 countformat(const char *format, int endchar)
 {
-	int count = 0;
-	int level = 0;
-	while (level > 0 || *format != endchar) {
-		switch (*format) {
-		case '\0':
-			/* Premature end */
-			PyErr_SetString(PyExc_SystemError,
-					"unmatched paren in format");
-			return -1;
-		case '(':
-		case '[':
-		case '{':
-			if (level == 0)
-				count++;
-			level++;
-			break;
-		case ')':
-		case ']':
-		case '}':
-			level--;
-			break;
-		case '#':
-		case '&':
-		case ',':
-		case ':':
-		case ' ':
-		case '\t':
-			break;
-		default:
-			if (level == 0)
-				count++;
-		}
-		format++;
-	}
-	return count;
+    int count = 0;
+    int level = 0;
+    while (level > 0 || *format != endchar) {
+        switch (*format) {
+        case '\0':
+            /* Premature end */
+            PyErr_SetString(PyExc_SystemError,
+                            "unmatched paren in format");
+            return -1;
+        case '(':
+        case '[':
+        case '{':
+            if (level == 0)
+                count++;
+            level++;
+            break;
+        case ')':
+        case ']':
+        case '}':
+            level--;
+            break;
+        case '#':
+        case '&':
+        case ',':
+        case ':':
+        case ' ':
+        case '\t':
+            break;
+        default:
+            if (level == 0)
+                count++;
+        }
+        format++;
+    }
+    return count;
 }
 
 
@@ -83,582 +83,435 @@
 static PyObject *
 do_mkdict(const char **p_format, va_list *p_va, int endchar, int n, int flags)
 {
-	PyObject *d;
-	int i;
-	int itemfailed = 0;
-	if (n < 0)
-		return NULL;
-	if ((d = PyDict_New()) == NULL)
-		return NULL;
-	/* Note that we can't bail immediately on error as this will leak
-	   refcounts on any 'N' arguments. */
-	for (i = 0; i < n; i+= 2) {
-		PyObject *k, *v;
-		int err;
-		k = do_mkvalue(p_format, p_va, flags);
-		if (k == NULL) {
-			itemfailed = 1;
-			Py_INCREF(Py_None);
-			k = Py_None;
-		}
-		v = do_mkvalue(p_format, p_va, flags);
-		if (v == NULL) {
-			itemfailed = 1;
-			Py_INCREF(Py_None);
-			v = Py_None;
-		}
-		err = PyDict_SetItem(d, k, v);
-		Py_DECREF(k);
-		Py_DECREF(v);
-		if (err < 0 || itemfailed) {
-			Py_DECREF(d);
-			return NULL;
-		}
-	}
-	if (d != NULL && **p_format != endchar) {
-		Py_DECREF(d);
-		d = NULL;
-		PyErr_SetString(PyExc_SystemError,
-				"Unmatched paren in format");
-	}
-	else if (endchar)
-		++*p_format;
-	return d;
+    PyObject *d;
+    int i;
+    int itemfailed = 0;
+    if (n < 0)
+        return NULL;
+    if ((d = PyDict_New()) == NULL)
+        return NULL;
+    /* Note that we can't bail immediately on error as this will leak
+       refcounts on any 'N' arguments. */
+    for (i = 0; i < n; i+= 2) {
+        PyObject *k, *v;
+        int err;
+        k = do_mkvalue(p_format, p_va, flags);
+        if (k == NULL) {
+            itemfailed = 1;
+            Py_INCREF(Py_None);
+            k = Py_None;
+        }
+        v = do_mkvalue(p_format, p_va, flags);
+        if (v == NULL) {
+            itemfailed = 1;
+            Py_INCREF(Py_None);
+            v = Py_None;
+        }
+        err = PyDict_SetItem(d, k, v);
+        Py_DECREF(k);
+        Py_DECREF(v);
+        if (err < 0 || itemfailed) {
+            Py_DECREF(d);
+            return NULL;
+        }
+    }
+    if (d != NULL && **p_format != endchar) {
+        Py_DECREF(d);
+        d = NULL;
+        PyErr_SetString(PyExc_SystemError,
+                        "Unmatched paren in format");
+    }
+    else if (endchar)
+        ++*p_format;
+    return d;
 }
 
 static PyObject *
 do_mklist(const char **p_format, va_list *p_va, int endchar, int n, int flags)
 {
-	PyObject *v;
-	int i;
-	int itemfailed = 0;
-	if (n < 0)
-		return NULL;
-	v = PyList_New(n);
-	if (v == NULL)
-		return NULL;
-	/* Note that we can't bail immediately on error as this will leak
-	   refcounts on any 'N' arguments. */
-	for (i = 0; i < n; i++) {
-		PyObject *w = do_mkvalue(p_format, p_va, flags);
-		if (w == NULL) {
-			itemfailed = 1;
-			Py_INCREF(Py_None);
-			w = Py_None;
-		}
-		PyList_SET_ITEM(v, i, w);
-	}
+    PyObject *v;
+    int i;
+    int itemfailed = 0;
+    if (n < 0)
+        return NULL;
+    v = PyList_New(n);
+    if (v == NULL)
+        return NULL;
+    /* Note that we can't bail immediately on error as this will leak
+       refcounts on any 'N' arguments. */
+    for (i = 0; i < n; i++) {
+        PyObject *w = do_mkvalue(p_format, p_va, flags);
+        if (w == NULL) {
+            itemfailed = 1;
+            Py_INCREF(Py_None);
+            w = Py_None;
+        }
+        PyList_SET_ITEM(v, i, w);
+    }
 
-	if (itemfailed) {
-		/* do_mkvalue() should have already set an error */
-		Py_DECREF(v);
-		return NULL;
-	}
-	if (**p_format != endchar) {
-		Py_DECREF(v);
-		PyErr_SetString(PyExc_SystemError,
-				"Unmatched paren in format");
-		return NULL;
-	}
-	if (endchar)
-		++*p_format;
-	return v;
+    if (itemfailed) {
+        /* do_mkvalue() should have already set an error */
+        Py_DECREF(v);
+        return NULL;
+    }
+    if (**p_format != endchar) {
+        Py_DECREF(v);
+        PyErr_SetString(PyExc_SystemError,
+                        "Unmatched paren in format");
+        return NULL;
+    }
+    if (endchar)
+        ++*p_format;
+    return v;
 }
 
 #ifdef Py_USING_UNICODE
 static int
 _ustrlen(Py_UNICODE *u)
 {
-	int i = 0;
-	Py_UNICODE *v = u;
-	while (*v != 0) { i++; v++; } 
-	return i;
+    int i = 0;
+    Py_UNICODE *v = u;
+    while (*v != 0) { i++; v++; }
+    return i;
 }
 #endif
 
 static PyObject *
 do_mktuple(const char **p_format, va_list *p_va, int endchar, int n, int flags)
 {
-	PyObject *v;
-	int i;
-	int itemfailed = 0;
-	if (n < 0)
-		return NULL;
-	if ((v = PyTuple_New(n)) == NULL)
-		return NULL;
-	/* Note that we can't bail immediately on error as this will leak
-	   refcounts on any 'N' arguments. */
-	for (i = 0; i < n; i++) {
-		PyObject *w = do_mkvalue(p_format, p_va, flags);
-		if (w == NULL) {
-			itemfailed = 1;
-			Py_INCREF(Py_None);
-			w = Py_None;
-		}
-		PyTuple_SET_ITEM(v, i, w);
-	}
-	if (itemfailed) {
-		/* do_mkvalue() should have already set an error */
-		Py_DECREF(v);
-		return NULL;
-	}
-	if (**p_format != endchar) {
-		Py_DECREF(v);
-		PyErr_SetString(PyExc_SystemError,
-				"Unmatched paren in format");
-		return NULL;
-	}
-	if (endchar)
-		++*p_format;
-	return v;
+    PyObject *v;
+    int i;
+    int itemfailed = 0;
+    if (n < 0)
+        return NULL;
+    if ((v = PyTuple_New(n)) == NULL)
+        return NULL;
+    /* Note that we can't bail immediately on error as this will leak
+       refcounts on any 'N' arguments. */
+    for (i = 0; i < n; i++) {
+        PyObject *w = do_mkvalue(p_format, p_va, flags);
+        if (w == NULL) {
+            itemfailed = 1;
+            Py_INCREF(Py_None);
+            w = Py_None;
+        }
+        PyTuple_SET_ITEM(v, i, w);
+    }
+    if (itemfailed) {
+        /* do_mkvalue() should have already set an error */
+        Py_DECREF(v);
+        return NULL;
+    }
+    if (**p_format != endchar) {
+        Py_DECREF(v);
+        PyErr_SetString(PyExc_SystemError,
+                        "Unmatched paren in format");
+        return NULL;
+    }
+    if (endchar)
+        ++*p_format;
+    return v;
 }
 
 static PyObject *
 do_mkvalue(const char **p_format, va_list *p_va, int flags)
 {
-	for (;;) {
-		switch (*(*p_format)++) {
-		case '(':
-			return do_mktuple(p_format, p_va, ')',
-					  countformat(*p_format, ')'), flags);
+    for (;;) {
+        switch (*(*p_format)++) {
+        case '(':
+            return do_mktuple(p_format, p_va, ')',
+                              countformat(*p_format, ')'), flags);
 
-		case '[':
-			return do_mklist(p_format, p_va, ']',
-					 countformat(*p_format, ']'), flags);
+        case '[':
+            return do_mklist(p_format, p_va, ']',
+                             countformat(*p_format, ']'), flags);
 
-		case '{':
-			return do_mkdict(p_format, p_va, '}',
-					 countformat(*p_format, '}'), flags);
+        case '{':
+            return do_mkdict(p_format, p_va, '}',
+                             countformat(*p_format, '}'), flags);
 
-		case 'b':
-		case 'B':
-		case 'h':
-		case 'i':
-			return PyInt_FromLong((long)va_arg(*p_va, int));
-			
-		case 'H':
-			return PyInt_FromLong((long)va_arg(*p_va, unsigned int));
+        case 'b':
+        case 'B':
+        case 'h':
+        case 'i':
+            return PyInt_FromLong((long)va_arg(*p_va, int));
 
-		case 'I':
-		{
-			unsigned int n;
-			n = va_arg(*p_va, unsigned int);
-			if (n > (unsigned long)PyInt_GetMax())
-				return PyLong_FromUnsignedLong((unsigned long)n);
-			else
-				return PyInt_FromLong(n);
-		}
-		
-		case 'n':
+        case 'H':
+            return PyInt_FromLong((long)va_arg(*p_va, unsigned int));
+
+        case 'I':
+        {
+            unsigned int n;
+            n = va_arg(*p_va, unsigned int);
+            if (n > (unsigned long)PyInt_GetMax())
+                return PyLong_FromUnsignedLong((unsigned long)n);
+            else
+                return PyInt_FromLong(n);
+        }
+
+        case 'n':
 #if SIZEOF_SIZE_T!=SIZEOF_LONG
-			return PyInt_FromSsize_t(va_arg(*p_va, Py_ssize_t));
+            return PyInt_FromSsize_t(va_arg(*p_va, Py_ssize_t));
 #endif
-			/* Fall through from 'n' to 'l' if Py_ssize_t is long */
-		case 'l':
-			return PyInt_FromLong(va_arg(*p_va, long));
+            /* Fall through from 'n' to 'l' if Py_ssize_t is long */
+        case 'l':
+            return PyInt_FromLong(va_arg(*p_va, long));
 
-		case 'k':
-		{
-			unsigned long n;
-			n = va_arg(*p_va, unsigned long);
-			if (n > (unsigned long)PyInt_GetMax())
-				return PyLong_FromUnsignedLong(n);
-			else
-				return PyInt_FromLong(n);
-		}
+        case 'k':
+        {
+            unsigned long n;
+            n = va_arg(*p_va, unsigned long);
+            if (n > (unsigned long)PyInt_GetMax())
+                return PyLong_FromUnsignedLong(n);
+            else
+                return PyInt_FromLong(n);
+        }
 
 #ifdef HAVE_LONG_LONG
-		case 'L':
-			return PyLong_FromLongLong((PY_LONG_LONG)va_arg(*p_va, PY_LONG_LONG));
+        case 'L':
+            return PyLong_FromLongLong((PY_LONG_LONG)va_arg(*p_va, PY_LONG_LONG));
 
-		case 'K':
-			return PyLong_FromUnsignedLongLong((PY_LONG_LONG)va_arg(*p_va, unsigned PY_LONG_LONG));
+        case 'K':
+            return PyLong_FromUnsignedLongLong((PY_LONG_LONG)va_arg(*p_va, unsigned PY_LONG_LONG));
 #endif
 #ifdef Py_USING_UNICODE
-		case 'u':
-		{
-			PyObject *v;
-			Py_UNICODE *u = va_arg(*p_va, Py_UNICODE *);
-			Py_ssize_t n;	
-			if (**p_format == '#') {
-				++*p_format;
-				if (flags & FLAG_SIZE_T)
-					n = va_arg(*p_va, Py_ssize_t);
-				else
-					n = va_arg(*p_va, int);
-			}
-			else
-				n = -1;
-			if (u == NULL) {
-				v = Py_None;
-				Py_INCREF(v);
-			}
-			else {
-				if (n < 0)
-					n = _ustrlen(u);
-				v = PyUnicode_FromUnicode(u, n);
-			}
-			return v;
-		}
+        case 'u':
+        {
+            PyObject *v;
+            Py_UNICODE *u = va_arg(*p_va, Py_UNICODE *);
+            Py_ssize_t n;
+            if (**p_format == '#') {
+                ++*p_format;
+                if (flags & FLAG_SIZE_T)
+                    n = va_arg(*p_va, Py_ssize_t);
+                else
+                    n = va_arg(*p_va, int);
+            }
+            else
+                n = -1;
+            if (u == NULL) {
+                v = Py_None;
+                Py_INCREF(v);
+            }
+            else {
+                if (n < 0)
+                    n = _ustrlen(u);
+                v = PyUnicode_FromUnicode(u, n);
+            }
+            return v;
+        }
 #endif
-		case 'f':
-		case 'd':
-			return PyFloat_FromDouble(
-				(double)va_arg(*p_va, va_double));
+        case 'f':
+        case 'd':
+            return PyFloat_FromDouble(
+                (double)va_arg(*p_va, va_double));
 
 #ifndef WITHOUT_COMPLEX
-		case 'D':
-			return PyComplex_FromCComplex(
-				*((Py_complex *)va_arg(*p_va, Py_complex *)));
+        case 'D':
+            return PyComplex_FromCComplex(
+                *((Py_complex *)va_arg(*p_va, Py_complex *)));
 #endif /* WITHOUT_COMPLEX */
 
-		case 'c':
-		{
-			char p[1];
-			p[0] = (char)va_arg(*p_va, int);
-			return PyString_FromStringAndSize(p, 1);
-		}
+        case 'c':
+        {
+            char p[1];
+            p[0] = (char)va_arg(*p_va, int);
+            return PyString_FromStringAndSize(p, 1);
+        }
 
-		case 's':
-		case 'z':
-		{
-			PyObject *v;
-			char *str = va_arg(*p_va, char *);
-			Py_ssize_t n;
-			if (**p_format == '#') {
-				++*p_format;
-				if (flags & FLAG_SIZE_T)
-					n = va_arg(*p_va, Py_ssize_t);
-				else
-					n = va_arg(*p_va, int);
-			}
-			else
-				n = -1;
-			if (str == NULL) {
-				v = Py_None;
-				Py_INCREF(v);
-			}
-			else {
-				if (n < 0) {
-					size_t m = strlen(str);
-					if (m > PY_SSIZE_T_MAX) {
-						PyErr_SetString(PyExc_OverflowError,
-							"string too long for Python string");
-						return NULL;
-					}
-					n = (Py_ssize_t)m;
-				}
-				v = PyString_FromStringAndSize(str, n);
-			}
-			return v;
-		}
+        case 's':
+        case 'z':
+        {
+            PyObject *v;
+            char *str = va_arg(*p_va, char *);
+            Py_ssize_t n;
+            if (**p_format == '#') {
+                ++*p_format;
+                if (flags & FLAG_SIZE_T)
+                    n = va_arg(*p_va, Py_ssize_t);
+                else
+                    n = va_arg(*p_va, int);
+            }
+            else
+                n = -1;
+            if (str == NULL) {
+                v = Py_None;
+                Py_INCREF(v);
+            }
+            else {
+                if (n < 0) {
+                    size_t m = strlen(str);
+                    if (m > PY_SSIZE_T_MAX) {
+                        PyErr_SetString(PyExc_OverflowError,
+                            "string too long for Python string");
+                        return NULL;
+                    }
+                    n = (Py_ssize_t)m;
+                }
+                v = PyString_FromStringAndSize(str, n);
+            }
+            return v;
+        }
 
-		case 'N':
-		case 'S':
-		case 'O':
-		if (**p_format == '&') {
-			typedef PyObject *(*converter)(void *);
-			converter func = va_arg(*p_va, converter);
-			void *arg = va_arg(*p_va, void *);
-			++*p_format;
-			return (*func)(arg);
-		}
-		else {
-			PyObject *v;
-			v = va_arg(*p_va, PyObject *);
-			if (v != NULL) {
-				if (*(*p_format - 1) != 'N')
-					Py_INCREF(v);
-			}
-			else if (!PyErr_Occurred())
-				/* If a NULL was passed
-				 * because a call that should
-				 * have constructed a value
-				 * failed, that's OK, and we
-				 * pass the error on; but if
-				 * no error occurred it's not
-				 * clear that the caller knew
-				 * what she was doing. */
-				PyErr_SetString(PyExc_SystemError,
-					"NULL object passed to Py_BuildValue");
-			return v;
-		}
+        case 'N':
+        case 'S':
+        case 'O':
+        if (**p_format == '&') {
+            typedef PyObject *(*converter)(void *);
+            converter func = va_arg(*p_va, converter);
+            void *arg = va_arg(*p_va, void *);
+            ++*p_format;
+            return (*func)(arg);
+        }
+        else {
+            PyObject *v;
+            v = va_arg(*p_va, PyObject *);
+            if (v != NULL) {
+                if (*(*p_format - 1) != 'N')
+                    Py_INCREF(v);
+            }
+            else if (!PyErr_Occurred())
+                /* If a NULL was passed
+                 * because a call that should
+                 * have constructed a value
+                 * failed, that's OK, and we
+                 * pass the error on; but if
+                 * no error occurred it's not
+                 * clear that the caller knew
+                 * what she was doing. */
+                PyErr_SetString(PyExc_SystemError,
+                    "NULL object passed to Py_BuildValue");
+            return v;
+        }
 
-		case ':':
-		case ',':
-		case ' ':
-		case '\t':
-			break;
+        case ':':
+        case ',':
+        case ' ':
+        case '\t':
+            break;
 
-		default:
-			PyErr_SetString(PyExc_SystemError,
-				"bad format char passed to Py_BuildValue");
-			return NULL;
+        default:
+            PyErr_SetString(PyExc_SystemError,
+                "bad format char passed to Py_BuildValue");
+            return NULL;
 
-		}
-	}
+        }
+    }
 }
 
 
 PyObject *
 Py_BuildValue(const char *format, ...)
 {
-	va_list va;
-	PyObject* retval;
-	va_start(va, format);
-	retval = va_build_value(format, va, 0);
-	va_end(va);
-	return retval;
+    va_list va;
+    PyObject* retval;
+    va_start(va, format);
+    retval = va_build_value(format, va, 0);
+    va_end(va);
+    return retval;
 }
 
 PyObject *
 _Py_BuildValue_SizeT(const char *format, ...)
 {
-	va_list va;
-	PyObject* retval;
-	va_start(va, format);
-	retval = va_build_value(format, va, FLAG_SIZE_T);
-	va_end(va);
-	return retval;
+    va_list va;
+    PyObject* retval;
+    va_start(va, format);
+    retval = va_build_value(format, va, FLAG_SIZE_T);
+    va_end(va);
+    return retval;
 }
 
 PyObject *
 Py_VaBuildValue(const char *format, va_list va)
 {
-	return va_build_value(format, va, 0);
+    return va_build_value(format, va, 0);
 }
 
 PyObject *
 _Py_VaBuildValue_SizeT(const char *format, va_list va)
 {
-	return va_build_value(format, va, FLAG_SIZE_T);
+    return va_build_value(format, va, FLAG_SIZE_T);
 }
 
 static PyObject *
 va_build_value(const char *format, va_list va, int flags)
 {
-	const char *f = format;
-	int n = countformat(f, '\0');
-	va_list lva;
+    const char *f = format;
+    int n = countformat(f, '\0');
+    va_list lva;
 
 #ifdef VA_LIST_IS_ARRAY
-	memcpy(lva, va, sizeof(va_list));
+    memcpy(lva, va, sizeof(va_list));
 #else
 #ifdef __va_copy
-	__va_copy(lva, va);
+    __va_copy(lva, va);
 #else
-	lva = va;
+    lva = va;
 #endif
 #endif
 
-	if (n < 0)
-		return NULL;
-	if (n == 0) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	if (n == 1)
-		return do_mkvalue(&f, &lva, flags);
-	return do_mktuple(&f, &lva, '\0', n, flags);
+    if (n < 0)
+        return NULL;
+    if (n == 0) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+    if (n == 1)
+        return do_mkvalue(&f, &lva, flags);
+    return do_mktuple(&f, &lva, '\0', n, flags);
 }
 
 
 PyObject *
 PyEval_CallFunction(PyObject *obj, const char *format, ...)
 {
-	va_list vargs;
-	PyObject *args;
-	PyObject *res;
+    va_list vargs;
+    PyObject *args;
+    PyObject *res;
 
-	va_start(vargs, format);
+    va_start(vargs, format);
 
-	args = Py_VaBuildValue(format, vargs);
-	va_end(vargs);
+    args = Py_VaBuildValue(format, vargs);
+    va_end(vargs);
 
-	if (args == NULL)
-		return NULL;
+    if (args == NULL)
+        return NULL;
 
-	res = PyEval_CallObject(obj, args);
-	Py_DECREF(args);
+    res = PyEval_CallObject(obj, args);
+    Py_DECREF(args);
 
-	return res;
+    return res;
 }
 
 
 PyObject *
 PyEval_CallMethod(PyObject *obj, const char *methodname, const char *format, ...)
 {
-	va_list vargs;
-	PyObject *meth;
-	PyObject *args;
-	PyObject *res;
+    va_list vargs;
+    PyObject *meth;
+    PyObject *args;
+    PyObject *res;
 
-	meth = PyObject_GetAttrString(obj, methodname);
-	if (meth == NULL)
-		return NULL;
+    meth = PyObject_GetAttrString(obj, methodname);
+    if (meth == NULL)
+        return NULL;
 
-	va_start(vargs, format);
+    va_start(vargs, format);
 
-	args = Py_VaBuildValue(format, vargs);
-	va_end(vargs);
+    args = Py_VaBuildValue(format, vargs);
+    va_end(vargs);
 
-	if (args == NULL) {
-		Py_DECREF(meth);
-		return NULL;
-	}
+    if (args == NULL) {
+        Py_DECREF(meth);
+        return NULL;
+    }
 
-	res = PyEval_CallObject(meth, args);
-	Py_DECREF(meth);
-	Py_DECREF(args);
+    res = PyEval_CallObject(meth, args);
+    Py_DECREF(meth);
+    Py_DECREF(args);
 
-	return res;
-}
-
-static PyObject*
-call_function_tail(PyObject *callable, PyObject *args)
-{
-	PyObject *retval;
-
-	if (args == NULL)
-		return NULL;
-
-	if (!PyTuple_Check(args)) {
-		PyObject *a;
-
-		a = PyTuple_New(1);
-		if (a == NULL) {
-			Py_DECREF(args);
-			return NULL;
-		}
-		PyTuple_SET_ITEM(a, 0, args);
-		args = a;
-	}
-	retval = PyObject_Call(callable, args, NULL);
-
-	Py_DECREF(args);
-
-	return retval;
-}
-
-PyObject *
-PyObject_CallFunction(PyObject *callable, const char *format, ...)
-{
-	va_list va;
-	PyObject *args;
-
-	if (format && *format) {
-		va_start(va, format);
-		args = Py_VaBuildValue(format, va);
-		va_end(va);
-	}
-	else
-		args = PyTuple_New(0);
-
-	return call_function_tail(callable, args);
-}
-
-PyObject *
-PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
-{
-	va_list va;
-	PyObject *args;
-	PyObject *func = NULL;
-	PyObject *retval = NULL;
-
-	func = PyObject_GetAttrString(o, name);
-	if (func == NULL) {
-		PyErr_SetString(PyExc_AttributeError, name);
-		return 0;
-	}
-
-	if (format && *format) {
-		va_start(va, format);
-		args = Py_VaBuildValue(format, va);
-		va_end(va);
-	}
-	else
-		args = PyTuple_New(0);
-
-	retval = call_function_tail(func, args);
-
-  exit:
-	/* args gets consumed in call_function_tail */
-	Py_XDECREF(func);
-
-	return retval;
-}
-
-static PyObject *
-objargs_mktuple(va_list va)
-{
-	int i, n = 0;
-	va_list countva;
-	PyObject *result, *tmp;
-
-#ifdef VA_LIST_IS_ARRAY
-	memcpy(countva, va, sizeof(va_list));
-#else
-#ifdef __va_copy
-	__va_copy(countva, va);
-#else
-	countva = va;
-#endif
-#endif
-
-	while (((PyObject *)va_arg(countva, PyObject *)) != NULL)
-		++n;
-	result = PyTuple_New(n);
-	if (result != NULL && n > 0) {
-		for (i = 0; i < n; ++i) {
-			tmp = (PyObject *)va_arg(va, PyObject *);
-			Py_INCREF(tmp);
-			PyTuple_SET_ITEM(result, i, tmp);
-		}
-	}
-	return result;
-}
-
-PyObject *
-PyObject_CallFunctionObjArgs(PyObject *callable, ...)
-{
-	PyObject *args, *tmp;
-	va_list vargs;
-
-	/* count the args */
-	va_start(vargs, callable);
-	args = objargs_mktuple(vargs);
-	va_end(vargs);
-	if (args == NULL)
-		return NULL;
-	tmp = PyObject_Call(callable, args, NULL);
-	Py_DECREF(args);
-
-	return tmp;
-}
-
-PyObject *
-PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
-{
-	PyObject *args, *tmp;
-	va_list vargs;
-
-	callable = PyObject_GetAttr(callable, name);
-	if (callable == NULL)
-		return NULL;
-
-	/* count the args */
-	va_start(vargs, name);
-	args = objargs_mktuple(vargs);
-	va_end(vargs);
-	if (args == NULL) {
-		Py_DECREF(callable);
-		return NULL;
-	}
-	tmp = PyObject_Call(callable, args, NULL);
-	Py_DECREF(args);
-	Py_DECREF(callable);
-
-	return tmp;
+    return res;
 }
 
 /* returns -1 in case of error, 0 if a new key was added, 1 if the key
@@ -666,67 +519,67 @@
 static int
 _PyModule_AddObject_NoConsumeRef(PyObject *m, const char *name, PyObject *o)
 {
-	PyObject *dict, *prev;
-	if (!PyModule_Check(m)) {
-		PyErr_SetString(PyExc_TypeError,
-			    "PyModule_AddObject() needs module as first arg");
-		return -1;
-	}
-	if (!o) {
-		if (!PyErr_Occurred())
-			PyErr_SetString(PyExc_TypeError,
-					"PyModule_AddObject() needs non-NULL value");
-		return -1;
-	}
+    PyObject *dict, *prev;
+    if (!PyModule_Check(m)) {
+        PyErr_SetString(PyExc_TypeError,
+                    "PyModule_AddObject() needs module as first arg");
+        return -1;
+    }
+    if (!o) {
+        if (!PyErr_Occurred())
+            PyErr_SetString(PyExc_TypeError,
+                            "PyModule_AddObject() needs non-NULL value");
+        return -1;
+    }
 
-	dict = PyModule_GetDict(m);
-	if (dict == NULL) {
-		/* Internal error -- modules must have a dict! */
-		PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
-			     PyModule_GetName(m));
-		return -1;
-	}
-	prev = PyDict_GetItemString(dict, name);
-	if (PyDict_SetItemString(dict, name, o))
-		return -1;
-	return prev != NULL;
+    dict = PyModule_GetDict(m);
+    if (dict == NULL) {
+        /* Internal error -- modules must have a dict! */
+        PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
+                     PyModule_GetName(m));
+        return -1;
+    }
+    prev = PyDict_GetItemString(dict, name);
+    if (PyDict_SetItemString(dict, name, o))
+        return -1;
+    return prev != NULL;
 }
 
 int
 PyModule_AddObject(PyObject *m, const char *name, PyObject *o)
 {
-	int result = _PyModule_AddObject_NoConsumeRef(m, name, o);
-	/* XXX WORKAROUND for a common misusage of PyModule_AddObject:
-	   for the common case of adding a new key, we don't consume a
-	   reference, but instead just leak it away.  The issue is that
-	   people generally don't realize that this function consumes a
-	   reference, because on CPython the reference is still stored
-	   on the dictionary. */
-	if (result != 0)
-		Py_DECREF(o);
-	return result < 0 ? -1 : 0;
+    int result = _PyModule_AddObject_NoConsumeRef(m, name, o);
+    /* XXX WORKAROUND for a common misusage of PyModule_AddObject:
+       for the common case of adding a new key, we don't consume a
+       reference, but instead just leak it away.  The issue is that
+       people generally don't realize that this function consumes a
+       reference, because on CPython the reference is still stored
+       on the dictionary. */
+    if (result != 0)
+        Py_DECREF(o);
+    return result < 0 ? -1 : 0;
 }
 
-int 
+int
 PyModule_AddIntConstant(PyObject *m, const char *name, long value)
 {
-	int result;
-	PyObject *o = PyInt_FromLong(value);
-	if (!o)
-		return -1;
-	result = _PyModule_AddObject_NoConsumeRef(m, name, o);
-	Py_DECREF(o);
-	return result < 0 ? -1 : 0;
+    int result;
+    PyObject *o = PyInt_FromLong(value);
+    if (!o)
+        return -1;
+    result = _PyModule_AddObject_NoConsumeRef(m, name, o);
+    Py_DECREF(o);
+    return result < 0 ? -1 : 0;
 }
 
-int 
+int
 PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
 {
-	int result;
-	PyObject *o = PyString_FromString(value);
-	if (!o)
-		return -1;
-	result = _PyModule_AddObject_NoConsumeRef(m, name, o);
-	Py_DECREF(o);
-	return result < 0 ? -1 : 0;
+    int result;
+    PyObject *o = PyString_FromString(value);
+    if (!o)
+        return -1;
+    result = _PyModule_AddObject_NoConsumeRef(m, name, o);
+    Py_DECREF(o);
+    return result < 0 ? -1 : 0;
 }
diff --git a/pypy/module/cpyext/src/mysnprintf.c b/pypy/module/cpyext/src/mysnprintf.c
--- a/pypy/module/cpyext/src/mysnprintf.c
+++ b/pypy/module/cpyext/src/mysnprintf.c
@@ -20,86 +20,86 @@
 
    Return value (rv):
 
-	When 0 <= rv < size, the output conversion was unexceptional, and
-	rv characters were written to str (excluding a trailing \0 byte at
-	str[rv]).
+    When 0 <= rv < size, the output conversion was unexceptional, and
+    rv characters were written to str (excluding a trailing \0 byte at
+    str[rv]).
 
-	When rv >= size, output conversion was truncated, and a buffer of
-	size rv+1 would have been needed to avoid truncation.  str[size-1]
-	is \0 in this case.
+    When rv >= size, output conversion was truncated, and a buffer of
+    size rv+1 would have been needed to avoid truncation.  str[size-1]
+    is \0 in this case.
 
-	When rv < 0, "something bad happened".  str[size-1] is \0 in this
-	case too, but the rest of str is unreliable.  It could be that
-	an error in format codes was detected by libc, or on platforms
-	with a non-C99 vsnprintf simply that the buffer wasn't big enough
-	to avoid truncation, or on platforms without any vsnprintf that
-	PyMem_Malloc couldn't obtain space for a temp buffer.
+    When rv < 0, "something bad happened".  str[size-1] is \0 in this
+    case too, but the rest of str is unreliable.  It could be that
+    an error in format codes was detected by libc, or on platforms
+    with a non-C99 vsnprintf simply that the buffer wasn't big enough
+    to avoid truncation, or on platforms without any vsnprintf that
+    PyMem_Malloc couldn't obtain space for a temp buffer.
 
    CAUTION:  Unlike C99, str != NULL and size > 0 are required.
 */
 
 int
+PyOS_snprintf(char *str, size_t size, const  char  *format, ...)
+{
+    int rc;
+    va_list va;
+
+    va_start(va, format);
+    rc = PyOS_vsnprintf(str, size, format, va);
+    va_end(va);
+    return rc;
+}
+
+int
 PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
 {
-	int len;  /* # bytes written, excluding \0 */
+    int len;  /* # bytes written, excluding \0 */
 #ifdef HAVE_SNPRINTF
 #define _PyOS_vsnprintf_EXTRA_SPACE 1
 #else
 #define _PyOS_vsnprintf_EXTRA_SPACE 512
-	char *buffer;
+    char *buffer;
 #endif
-	assert(str != NULL);
-	assert(size > 0);
-	assert(format != NULL);
-	/* We take a size_t as input but return an int.  Sanity check
-	 * our input so that it won't cause an overflow in the
-         * vsnprintf return value or the buffer malloc size.  */
-	if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
-		len = -666;
-		goto Done;
-	}
+    assert(str != NULL);
+    assert(size > 0);
+    assert(format != NULL);
+    /* We take a size_t as input but return an int.  Sanity check
+     * our input so that it won't cause an overflow in the
+     * vsnprintf return value or the buffer malloc size.  */
+    if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
+        len = -666;
+        goto Done;
+    }
 
 #ifdef HAVE_SNPRINTF
-	len = vsnprintf(str, size, format, va);
+    len = vsnprintf(str, size, format, va);
 #else
-	/* Emulate it. */
-	buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
-	if (buffer == NULL) {
-		len = -666;
-		goto Done;
-	}
+    /* Emulate it. */
+    buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
+    if (buffer == NULL) {
+        len = -666;
+        goto Done;
+    }
 
-	len = vsprintf(buffer, format, va);
-	if (len < 0)
-		/* ignore the error */;
+    len = vsprintf(buffer, format, va);
+    if (len < 0)
+        /* ignore the error */;
 
-	else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
-		Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
+    else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
+        Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
 
-	else {
-		const size_t to_copy = (size_t)len < size ?
-					(size_t)len : size - 1;
-		assert(to_copy < size);
-		memcpy(str, buffer, to_copy);
-		str[to_copy] = '\0';
-	}
-	PyMem_FREE(buffer);
+    else {
+        const size_t to_copy = (size_t)len < size ?
+                                (size_t)len : size - 1;
+        assert(to_copy < size);
+        memcpy(str, buffer, to_copy);
+        str[to_copy] = '\0';
+    }
+    PyMem_FREE(buffer);
 #endif
 Done:
-	if (size > 0)
-		str[size-1] = '\0';
-	return len;
+    if (size > 0)
+        str[size-1] = '\0';
+    return len;
 #undef _PyOS_vsnprintf_EXTRA_SPACE
 }
-
-int
-PyOS_snprintf(char *str, size_t size, const  char  *format, ...)
-{
-	int rc;
-	va_list va;
-
-	va_start(va, format);
-	rc = PyOS_vsnprintf(str, size, format, va);
-	va_end(va);
-	return rc;
-}
diff --git a/pypy/module/cpyext/src/object.c b/pypy/module/cpyext/src/object.c
deleted file mode 100644
--- a/pypy/module/cpyext/src/object.c
+++ /dev/null
@@ -1,91 +0,0 @@
-// contains code from abstract.c
-#include <Python.h>
-
-
-static PyObject *
-null_error(void)
-{
-	if (!PyErr_Occurred())
-		PyErr_SetString(PyExc_SystemError,
-				"null argument to internal routine");
-	return NULL;
-}
-
-int PyObject_AsReadBuffer(PyObject *obj,
-			  const void **buffer,
-			  Py_ssize_t *buffer_len)
-{
-	PyBufferProcs *pb;
-	void *pp;
-	Py_ssize_t len;
-
-	if (obj == NULL || buffer == NULL || buffer_len == NULL) {
-		null_error();
-		return -1;
-	}
-	pb = obj->ob_type->tp_as_buffer;
-	if (pb == NULL ||
-	     pb->bf_getreadbuffer == NULL ||
-	     pb->bf_getsegcount == NULL) {
-		PyErr_SetString(PyExc_TypeError,
-				"expected a readable buffer object");
-		return -1;
-	}
-	if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
-		PyErr_SetString(PyExc_TypeError,
-				"expected a single-segment buffer object");
-		return -1;
-	}
-	len = (*pb->bf_getreadbuffer)(obj, 0, &pp);
-	if (len < 0)
-		return -1;
-	*buffer = pp;
-	*buffer_len = len;
-	return 0;
-}
-
-int PyObject_AsWriteBuffer(PyObject *obj,
-			   void **buffer,
-			   Py_ssize_t *buffer_len)
-{
-	PyBufferProcs *pb;
-	void*pp;
-	Py_ssize_t len;
-
-	if (obj == NULL || buffer == NULL || buffer_len == NULL) {
-		null_error();
-		return -1;
-	}
-	pb = obj->ob_type->tp_as_buffer;
-	if (pb == NULL ||
-	     pb->bf_getwritebuffer == NULL ||
-	     pb->bf_getsegcount == NULL) {
-		PyErr_SetString(PyExc_TypeError,
-				"expected a writeable buffer object");
-		return -1;
-	}
-	if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
-		PyErr_SetString(PyExc_TypeError,
-				"expected a single-segment buffer object");
-		return -1;
-	}
-	len = (*pb->bf_getwritebuffer)(obj,0,&pp);
-	if (len < 0)
-		return -1;
-	*buffer = pp;
-	*buffer_len = len;
-	return 0;
-}
-
-int
-PyObject_CheckReadBuffer(PyObject *obj)
-{
-	PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
-
-	if (pb == NULL ||
-	    pb->bf_getreadbuffer == NULL ||
-	    pb->bf_getsegcount == NULL ||
-	    (*pb->bf_getsegcount)(obj, NULL) != 1)
-		return 0;
-	return 1;
-}
diff --git a/pypy/module/cpyext/src/pyerrors.c b/pypy/module/cpyext/src/pyerrors.c
--- a/pypy/module/cpyext/src/pyerrors.c
+++ b/pypy/module/cpyext/src/pyerrors.c
@@ -25,7 +25,7 @@
 PyObject *
 PyErr_NewException(const char *name, PyObject *base, PyObject *dict)
 {
-    const char *dot;
+    char *dot;
     PyObject *modulename = NULL;
     PyObject *classname = NULL;
     PyObject *mydict = NULL;
diff --git a/pypy/module/cpyext/src/pysignals.c b/pypy/module/cpyext/src/pysignals.c
--- a/pypy/module/cpyext/src/pysignals.c
+++ b/pypy/module/cpyext/src/pysignals.c
@@ -17,17 +17,34 @@
 PyOS_getsig(int sig)
 {
 #ifdef SA_RESTART
-        /* assume sigaction exists */
-        struct sigaction context;
-        if (sigaction(sig, NULL, &context) == -1)
-                return SIG_ERR;
-        return context.sa_handler;
+    /* assume sigaction exists */
+    struct sigaction context;
+    if (sigaction(sig, NULL, &context) == -1)
+        return SIG_ERR;
+    return context.sa_handler;
 #else
-        PyOS_sighandler_t handler;
-        handler = signal(sig, SIG_IGN);
-        if (handler != SIG_ERR)
-                signal(sig, handler);
-        return handler;
+    PyOS_sighandler_t handler;
+/* Special signal handling for the secure CRT in Visual Studio 2005 */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+    switch (sig) {
+    /* Only these signals are valid */
+    case SIGINT:
+    case SIGILL:
+    case SIGFPE:
+    case SIGSEGV:
+    case SIGTERM:
+    case SIGBREAK:
+    case SIGABRT:
+        break;
+    /* Don't call signal() with other values or it will assert */
+    default:
+        return SIG_ERR;
+    }
+#endif /* _MSC_VER && _MSC_VER >= 1400 */
+    handler = signal(sig, SIG_IGN);
+    if (handler != SIG_ERR)
+        signal(sig, handler);
+    return handler;
 #endif
 }
 
@@ -35,21 +52,21 @@
 PyOS_setsig(int sig, PyOS_sighandler_t handler)
 {
 #ifdef SA_RESTART
-        /* assume sigaction exists */
-        struct sigaction context, ocontext;
-        context.sa_handler = handler;
-        sigemptyset(&context.sa_mask);
-        context.sa_flags = 0;
-        if (sigaction(sig, &context, &ocontext) == -1)
-                return SIG_ERR;
-        return ocontext.sa_handler;
+    /* assume sigaction exists */
+    struct sigaction context, ocontext;
+    context.sa_handler = handler;
+    sigemptyset(&context.sa_mask);
+    context.sa_flags = 0;
+    if (sigaction(sig, &context, &ocontext) == -1)
+        return SIG_ERR;
+    return ocontext.sa_handler;
 #else
-        PyOS_sighandler_t oldhandler;
-        oldhandler = signal(sig, handler);
+    PyOS_sighandler_t oldhandler;
+    oldhandler = signal(sig, handler);
 #ifndef MS_WINDOWS
-        /* should check if this exists */
-        siginterrupt(sig, 1);
+    /* should check if this exists */
+    siginterrupt(sig, 1);
 #endif
-        return oldhandler;
+    return oldhandler;
 #endif
 }
diff --git a/pypy/module/cpyext/src/pythonrun.c b/pypy/module/cpyext/src/pythonrun.c
--- a/pypy/module/cpyext/src/pythonrun.c
+++ b/pypy/module/cpyext/src/pythonrun.c
@@ -9,28 +9,28 @@
 void
 Py_FatalError(const char *msg)
 {
-	fprintf(stderr, "Fatal Python error: %s\n", msg);
-	fflush(stderr); /* it helps in Windows debug build */
+    fprintf(stderr, "Fatal Python error: %s\n", msg);
+    fflush(stderr); /* it helps in Windows debug build */
 
 #ifdef MS_WINDOWS
-	{
-		size_t len = strlen(msg);
-		WCHAR* buffer;
-		size_t i;
+    {
+        size_t len = strlen(msg);
+        WCHAR* buffer;
+        size_t i;
 
-		/* Convert the message to wchar_t. This uses a simple one-to-one
-		conversion, assuming that the this error message actually uses ASCII
-		only. If this ceases to be true, we will have to convert. */
-		buffer = alloca( (len+1) * (sizeof *buffer));
-		for( i=0; i<=len; ++i)
-			buffer[i] = msg[i];
-		OutputDebugStringW(L"Fatal Python error: ");
-		OutputDebugStringW(buffer);
-		OutputDebugStringW(L"\n");
-	}
+        /* Convert the message to wchar_t. This uses a simple one-to-one
+        conversion, assuming that the this error message actually uses ASCII
+        only. If this ceases to be true, we will have to convert. */
+        buffer = alloca( (len+1) * (sizeof *buffer));
+        for( i=0; i<=len; ++i)
+            buffer[i] = msg[i];
+        OutputDebugStringW(L"Fatal Python error: ");
+        OutputDebugStringW(buffer);
+        OutputDebugStringW(L"\n");
+    }
 #ifdef _DEBUG
-	DebugBreak();
+    DebugBreak();
 #endif
 #endif /* MS_WINDOWS */
-	abort();
+    abort();
 }
diff --git a/pypy/module/cpyext/src/structseq.c b/pypy/module/cpyext/src/structseq.c
--- a/pypy/module/cpyext/src/structseq.c
+++ b/pypy/module/cpyext/src/structseq.c
@@ -175,32 +175,33 @@
     if (min_len != max_len) {
         if (len < min_len) {
             PyErr_Format(PyExc_TypeError,
-           "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
-                                 type->tp_name, min_len, len);
-                    Py_DECREF(arg);
-                    return NULL;
+                "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
+                type->tp_name, min_len, len);
+            Py_DECREF(arg);
+            return NULL;
         }
 
         if (len > max_len) {
             PyErr_Format(PyExc_TypeError,
-           "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
-                                 type->tp_name, max_len, len);
-                    Py_DECREF(arg);
-                    return NULL;
+                         "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
+                         type->tp_name, max_len, len);
+            Py_DECREF(arg);
+            return NULL;
         }
     }
     else {
         if (len != min_len) {
             PyErr_Format(PyExc_TypeError,
-           "%.500s() takes a %zd-sequence (%zd-sequence given)",
-                                 type->tp_name, min_len, len);
-                    Py_DECREF(arg);
-                    return NULL;
+                         "%.500s() takes a %zd-sequence (%zd-sequence given)",
+                         type->tp_name, min_len, len);
+            Py_DECREF(arg);
+            return NULL;
         }
     }
 
     res = (PyStructSequence*) PyStructSequence_New(type);
     if (res == NULL) {
+        Py_DECREF(arg);
         return NULL;
     }
     for (i = 0; i < len; ++i) {
diff --git a/pypy/module/cpyext/src/sysmodule.c b/pypy/module/cpyext/src/sysmodule.c
--- a/pypy/module/cpyext/src/sysmodule.c
+++ b/pypy/module/cpyext/src/sysmodule.c
@@ -100,4 +100,3 @@
     sys_write("stderr", stderr, format, va);
     va_end(va);
 }
-
diff --git a/pypy/module/cpyext/src/varargwrapper.c b/pypy/module/cpyext/src/varargwrapper.c
--- a/pypy/module/cpyext/src/varargwrapper.c
+++ b/pypy/module/cpyext/src/varargwrapper.c
@@ -1,21 +1,25 @@
 #include <Python.h>
 #include <stdarg.h>
 
-PyObject * PyTuple_Pack(Py_ssize_t size, ...)
+PyObject *
+PyTuple_Pack(Py_ssize_t n, ...)
 {
-    va_list ap;
-    PyObject *cur, *tuple;
-    int i;
+    Py_ssize_t i;
+    PyObject *o;
+    PyObject *result;
+    va_list vargs;
 
-    tuple = PyTuple_New(size);
-    va_start(ap, size);
-    for (i = 0; i < size; i++) {
-        cur = va_arg(ap, PyObject*);
-        Py_INCREF(cur);
-        if (PyTuple_SetItem(tuple, i, cur) < 0)
+    va_start(vargs, n);
+    result = PyTuple_New(n);
+    if (result == NULL)
+        return NULL;
+    for (i = 0; i < n; i++) {
+        o = va_arg(vargs, PyObject *);
+        Py_INCREF(o);
+        if (PyTuple_SetItem(result, i, o) < 0)
             return NULL;
     }
-    va_end(ap);
-    return tuple;
+    va_end(vargs);
+    return result;
 }
 
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -288,6 +288,26 @@
         w_errors = space.wrap(rffi.charp2str(errors))
     return space.call_method(w_str, 'encode', w_encoding, w_errors)
 
+ at cpython_api([PyObject, rffi.CCHARP, rffi.CCHARP], PyObject)
+def PyString_AsDecodedObject(space, w_str, encoding, errors):
+    """Decode a string object by passing it to the codec registered
+    for encoding and return the result as Python object. encoding and
+    errors have the same meaning as the parameters of the same name in
+    the string encode() method.  The codec to be used is looked up
+    using the Python codec registry. Return NULL if an exception was
+    raised by the codec.
+
+    This function is not available in 3.x and does not have a PyBytes alias."""
+    if not PyString_Check(space, w_str):
+        PyErr_BadArgument(space)
+
+    w_encoding = w_errors = space.w_None
+    if encoding:
+        w_encoding = space.wrap(rffi.charp2str(encoding))
+    if errors:
+        w_errors = space.wrap(rffi.charp2str(errors))
+    return space.call_method(w_str, "decode", w_encoding, w_errors)
+
 @cpython_api([PyObject, PyObject], PyObject)
 def _PyString_Join(space, w_sep, w_seq):
     return space.call_method(w_sep, 'join', w_seq)
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -1405,17 +1405,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
-def PyList_GetSlice(space, list, low, high):
-    """Return a list of the objects in list containing the objects between low
-    and high.  Return NULL and set an exception if unsuccessful.  Analogous
-    to list[low:high].  Negative indices, as when slicing from Python, are not
-    supported.
-
-    This function used an int for low and high. This might
-    require changes in your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
 @cpython_api([Py_ssize_t], PyObject)
 def PyLong_FromSsize_t(space, v):
     """Return a new PyLongObject object from a C Py_ssize_t, or
@@ -1588,15 +1577,6 @@
     for PyObject_Str()."""
     raise NotImplementedError
 
- at cpython_api([PyObject], lltype.Signed, error=-1)
-def PyObject_HashNotImplemented(space, o):
-    """Set a TypeError indicating that type(o) is not hashable and return -1.
-    This function receives special treatment when stored in a tp_hash slot,
-    allowing a type to explicitly indicate to the interpreter that it is not
-    hashable.
-    """
-    raise NotImplementedError
-
 @cpython_api([], PyFrameObject)
 def PyEval_GetFrame(space):
     """Return the current thread state's frame, which is NULL if no frame is
@@ -1719,17 +1699,6 @@
     changes in your code for properly supporting 64-bit systems."""
     raise NotImplementedError
 
- at cpython_api([PyObject, rffi.CCHARP, rffi.CCHARP], PyObject)
-def PyString_AsDecodedObject(space, str, encoding, errors):
-    """Decode a string object by passing it to the codec registered for encoding and
-    return the result as Python object. encoding and errors have the same
-    meaning as the parameters of the same name in the string encode() method.
-    The codec to be used is looked up using the Python codec registry. Return NULL
-    if an exception was raised by the codec.
-
-    This function is not available in 3.x and does not have a PyBytes alias."""
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP, rffi.CCHARP], PyObject)
 def PyString_Encode(space, s, size, encoding, errors):
     """Encode the char buffer of the given size by passing it to the codec
diff --git a/pypy/module/cpyext/test/test_iterator.py b/pypy/module/cpyext/test/test_iterator.py
--- a/pypy/module/cpyext/test/test_iterator.py
+++ b/pypy/module/cpyext/test/test_iterator.py
@@ -15,3 +15,8 @@
         assert space.unwrap(api.PyIter_Next(w_iter)) == 3
         assert api.PyIter_Next(w_iter) is None
         assert not api.PyErr_Occurred()
+
+    def test_iternext_error(self,space, api):
+        assert api.PyIter_Next(space.w_None) is None
+        assert api.PyErr_Occurred() is space.w_TypeError
+        api.PyErr_Clear()
diff --git a/pypy/module/cpyext/test/test_listobject.py b/pypy/module/cpyext/test/test_listobject.py
--- a/pypy/module/cpyext/test/test_listobject.py
+++ b/pypy/module/cpyext/test/test_listobject.py
@@ -58,6 +58,11 @@
         w_t = api.PyList_AsTuple(w_l)
         assert space.unwrap(w_t) == (3, 2, 1)
 
+    def test_list_getslice(self, space, api):
+        w_l = space.newlist([space.wrap(3), space.wrap(2), space.wrap(1)])
+        w_s = api.PyList_GetSlice(w_l, 1, 5)
+        assert space.unwrap(w_s) == [2, 1]
+
 class AppTestListObject(AppTestCpythonExtensionBase):
     def test_listobject(self):
         import sys
diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -273,6 +273,43 @@
         rffi.free_charp(buf)
         assert w_s1 is w_s2
 
+    def test_AsEncodedObject(self, space, api):
+        ptr = space.wrap('abc')
+
+        errors = rffi.str2charp("strict")
+
+        encoding = rffi.str2charp("hex")
+        res = api.PyString_AsEncodedObject(
+            ptr, encoding, errors)
+        assert space.unwrap(res) == "616263"
+
+        res = api.PyString_AsEncodedObject(
+            ptr, encoding, lltype.nullptr(rffi.CCHARP.TO))
+        assert space.unwrap(res) == "616263"
+        rffi.free_charp(encoding)
+
+        encoding = rffi.str2charp("unknown_encoding")
+        self.raises(space, api, LookupError, api.PyString_AsEncodedObject,
+                    ptr, encoding, errors)
+        rffi.free_charp(encoding)
+
+        rffi.free_charp(errors)
+
+        res = api.PyString_AsEncodedObject(
+            ptr, lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO))
+        assert space.unwrap(res) == "abc"
+
+        self.raises(space, api, TypeError, api.PyString_AsEncodedObject,
+            space.wrap(2), lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO)
+        )
+
+    def test_AsDecodedObject(self, space, api):
+        w_str = space.wrap('caf\xe9')
+        encoding = rffi.str2charp("latin-1")
+        w_res = api.PyString_AsDecodedObject(w_str, encoding, None)
+        rffi.free_charp(encoding)
+        assert space.unwrap(w_res) == u"caf\xe9"
+
     def test_eq(self, space, api):
         assert 1 == api._PyString_Eq(space.wrapbytes("hello"), space.wrapbytes("hello"))
         assert 0 == api._PyString_Eq(space.wrapbytes("hello"), space.wrapbytes("world"))
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -488,3 +488,55 @@
         assert type(it) is type(iter([]))
         assert module.tp_iternext(it) == 1
         raises(StopIteration, module.tp_iternext, it)
+        
+    def test_bool(self):
+        module = self.import_extension('foo', [
+            ("newInt", "METH_VARARGS",
+             """
+                IntLikeObject *intObj;
+                long intval;
+                PyObject *name;
+
+                if (!PyArg_ParseTuple(args, "i", &intval))
+                    return NULL;
+
+                IntLike_Type.tp_as_number = &intlike_as_number;
+                intlike_as_number.nb_nonzero = intlike_nb_nonzero;
+                if (PyType_Ready(&IntLike_Type) < 0) return NULL;
+                intObj = PyObject_New(IntLikeObject, &IntLike_Type);
+                if (!intObj) {
+                    return NULL;
+                }
+
+                intObj->value = intval;
+                return (PyObject *)intObj;
+             """)],
+            """
+            typedef struct
+            {
+                PyObject_HEAD
+                int value;
+            } IntLikeObject;
+
+            static int
+            intlike_nb_nonzero(IntLikeObject *v)
+            {
+                if (v->value == -42) {
+                    PyErr_SetNone(PyExc_ValueError);
+                    return -1;
+                }
+                return v->value;
+            }
+
+            PyTypeObject IntLike_Type = {
+                PyObject_HEAD_INIT(0)
+                /*ob_size*/             0,
+                /*tp_name*/             "IntLike",
+                /*tp_basicsize*/        sizeof(IntLikeObject),
+            };
+            static PyNumberMethods intlike_as_number;
+            """)
+        assert not bool(module.newInt(0))
+        assert bool(module.newInt(1))
+        assert bool(module.newInt(-1))
+        raises(ValueError, bool, module.newInt(-42))
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -488,10 +488,22 @@
 
     def test_tailmatch(self, space, api):
         w_str = space.wrap(u"abcdef")
-        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 2, 10, 1) == 1
-        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 1, 5, -1) == 1
+        # prefix match
+        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 2, 9, -1) == 1
+        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 2, 4, -1) == 0 # ends at 'd'
+        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 1, 6, -1) == 0 # starts at 'b'
+        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cdf"), 2, 6, -1) == 0
+        # suffix match
+        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 1, 5,  1) == 1
+        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 3, 5,  1) == 0 # starts at 'd'
+        assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 1, 6,  1) == 0 # ends at 'f'
+        assert api.PyUnicode_Tailmatch(w_str, space.wrap("bde"), 1, 5,  1) == 0
+        # type checks
         self.raises(space, api, TypeError,
                     api.PyUnicode_Tailmatch, w_str, space.wrap(3), 2, 10, 1)
+        self.raises(space, api, TypeError,
+                    api.PyUnicode_Tailmatch, space.wrap(3), space.wrap("abc"),
+                    2, 10, 1)
 
     def test_count(self, space, api):
         w_str = space.wrap(u"abcabdab")
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -597,7 +597,7 @@
     suffix match), 0 otherwise. Return -1 if an error occurred."""
     str = space.unicode_w(w_str)
     substr = space.unicode_w(w_substr)
-    if rffi.cast(lltype.Signed, direction) >= 0:
+    if rffi.cast(lltype.Signed, direction) <= 0:
         return stringtype.stringstartswith(str, substr, start, end)
     else:
         return stringtype.stringendswith(str, substr, start, end)
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -5,6 +5,7 @@
     interpleveldefs = {
         'debug_repr': 'interp_extras.debug_repr',
         'remove_invalidates': 'interp_extras.remove_invalidates',
+        'set_invalidation': 'interp_extras.set_invalidation',
     }
     appleveldefs = {}
 
@@ -30,6 +31,7 @@
         'isna': 'interp_numarray.isna',
         'concatenate': 'interp_numarray.concatenate',
         'repeat': 'interp_numarray.repeat',
+        'where': 'interp_arrayops.where',
 
         'set_string_function': 'appbridge.set_string_function',
 
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -10,6 +10,7 @@
 from pypy.module.micronumpy.interp_dtype import get_dtype_cache
 from pypy.module.micronumpy.interp_numarray import (Scalar, BaseArray,
      scalar_w, W_NDimArray, array)
+from pypy.module.micronumpy.interp_arrayops import where
 from pypy.module.micronumpy import interp_ufuncs
 from pypy.rlib.objectmodel import specialize, instantiate
 
@@ -35,6 +36,7 @@
 SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any",
                         "unegative", "flat", "tostring"]
 TWO_ARG_FUNCTIONS = ["dot", 'take']
+THREE_ARG_FUNCTIONS = ['where']
 
 class FakeSpace(object):
     w_ValueError = None
@@ -445,14 +447,25 @@
             arg = self.args[1].execute(interp)
             if not isinstance(arg, BaseArray):
                 raise ArgumentNotAnArray
-            if not isinstance(arg, BaseArray):
-                raise ArgumentNotAnArray
             if self.name == "dot":
                 w_res = arr.descr_dot(interp.space, arg)
             elif self.name == 'take':
                 w_res = arr.descr_take(interp.space, arg)
             else:
                 assert False # unreachable code
+        elif self.name in THREE_ARG_FUNCTIONS:
+            if len(self.args) != 3:
+                raise ArgumentMismatch
+            arg1 = self.args[1].execute(interp)
+            arg2 = self.args[2].execute(interp)
+            if not isinstance(arg1, BaseArray):
+                raise ArgumentNotAnArray
+            if not isinstance(arg2, BaseArray):
+                raise ArgumentNotAnArray
+            if self.name == "where":
+                w_res = where(interp.space, arr, arg1, arg2)
+            else:
+                assert False
         else:
             raise WrongFunctionName
         if isinstance(w_res, BaseArray):
diff --git a/pypy/module/micronumpy/interp_arrayops.py b/pypy/module/micronumpy/interp_arrayops.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_arrayops.py
@@ -0,0 +1,90 @@
+
+from pypy.module.micronumpy.interp_numarray import convert_to_array,\
+     VirtualArray
+from pypy.module.micronumpy import signature
+
+class WhereArray(VirtualArray):
+    def __init__(self, space, arr, x, y):
+        self.arr = arr
+        self.x = x
+        self.y = y
+        VirtualArray.__init__(self, 'where', arr.shape[:],
+                              x.find_dtype())
+
+    def create_sig(self):
+        if self.forced_result is not None:
+            return self.forced_result.create_sig()
+        return signature.WhereSignature(self.res_dtype, self.arr.find_dtype(),
+                                        self.arr.create_sig(),
+                                        self.x.create_sig(),
+                                        self.y.create_sig())
+
+    def _del_sources(self):
+        self.arr = None
+        self.x = None
+        self.y = None
+
+def where(space, w_arr, w_x, w_y):
+    """where(condition, [x, y])
+
+    Return elements, either from `x` or `y`, depending on `condition`.
+
+    If only `condition` is given, return ``condition.nonzero()``.
+
+    Parameters
+    ----------
+    condition : array_like, bool
+        When True, yield `x`, otherwise yield `y`.
+    x, y : array_like, optional
+        Values from which to choose. `x` and `y` need to have the same
+        shape as `condition`.
+
+    Returns
+    -------
+    out : ndarray or tuple of ndarrays
+        If both `x` and `y` are specified, the output array contains
+        elements of `x` where `condition` is True, and elements from
+        `y` elsewhere.
+
+        If only `condition` is given, return the tuple
+        ``condition.nonzero()``, the indices where `condition` is True.
+
+    See Also
+    --------
+    nonzero, choose
+
+    Notes
+    -----
+    If `x` and `y` are given and input arrays are 1-D, `where` is
+    equivalent to::
+
+        [xv if c else yv for (c,xv,yv) in zip(condition,x,y)]
+
+    Examples
+    --------
+    >>> np.where([[True, False], [True, True]],
+    ...          [[1, 2], [3, 4]],
+    ...          [[9, 8], [7, 6]])
+    array([[1, 8],
+           [3, 4]])
+
+    >>> np.where([[0, 1], [1, 0]])
+    (array([0, 1]), array([1, 0]))
+
+    >>> x = np.arange(9.).reshape(3, 3)
+    >>> np.where( x > 5 )
+    (array([2, 2, 2]), array([0, 1, 2]))
+    >>> x[np.where( x > 3.0 )]               # Note: result is 1D.
+    array([ 4.,  5.,  6.,  7.,  8.])
+    >>> np.where(x < 5, x, -1)               # Note: broadcasting.
+    array([[ 0.,  1.,  2.],
+           [ 3.,  4., -1.],
+           [-1., -1., -1.]])
+
+    
+    NOTE: support for not passing x and y is unsupported
+    """
+    arr = convert_to_array(space, w_arr)
+    x = convert_to_array(space, w_x)
+    y = convert_to_array(space, w_y)
+    return WhereArray(space, arr, x, y)
diff --git a/pypy/module/micronumpy/interp_extras.py b/pypy/module/micronumpy/interp_extras.py
--- a/pypy/module/micronumpy/interp_extras.py
+++ b/pypy/module/micronumpy/interp_extras.py
@@ -1,5 +1,5 @@
 from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_numarray import BaseArray
+from pypy.module.micronumpy.interp_numarray import BaseArray, get_numarray_cache
 
 
 @unwrap_spec(array=BaseArray)
@@ -13,3 +13,7 @@
     """
     del array.invalidates[:]
     return space.w_None
+
+ at unwrap_spec(arg=bool)
+def set_invalidation(space, arg):
+    get_numarray_cache(space).enable_invalidation = arg
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -72,9 +72,10 @@
             arr.force_if_needed()
         del self.invalidates[:]
 
-    def add_invalidates(self, other):
-        self.invalidates.append(other)
-
+    def add_invalidates(self, space, other):
+        if get_numarray_cache(space).enable_invalidation:
+            self.invalidates.append(other)
+        
     def descr__new__(space, w_subtype, w_size, w_dtype=None):
         dtype = space.interp_w(interp_dtype.W_Dtype,
             space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
@@ -1583,3 +1584,10 @@
         arr.fill(space, space.wrap(False))
         return arr
     return space.wrap(False)
+
+class NumArrayCache(object):
+    def __init__(self, space):
+        self.enable_invalidation = True
+
+def get_numarray_cache(space):
+    return space.fromcache(NumArrayCache)
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -278,7 +278,7 @@
         else:
             w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype,
                                          res_dtype, w_obj)
-        w_obj.add_invalidates(w_res)
+        w_obj.add_invalidates(space, w_res)
         return w_res
 
 
@@ -347,8 +347,8 @@
         w_res = Call2(self.func, self.name,
                       new_shape, calc_dtype,
                       res_dtype, w_lhs, w_rhs, out)
-        w_lhs.add_invalidates(w_res)
-        w_rhs.add_invalidates(w_res)
+        w_lhs.add_invalidates(space, w_res)
+        w_rhs.add_invalidates(space, w_res)
         if out:
             w_res.get_concrete()
         return w_res
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -498,3 +498,63 @@
         arr.left.setitem(iterator.offset, value)
     def debug_repr(self):
         return 'AxisReduceSig(%s, %s)' % (self.name, self.right.debug_repr())
+
+class WhereSignature(Signature):
+    _immutable_fields_ = ['dtype', 'arrdtype', 'arrsig', 'xsig', 'ysig']
+    
+    def __init__(self, dtype, arrdtype, arrsig, xsig, ysig):
+        self.dtype = dtype
+        self.arrdtype = arrdtype
+        self.arrsig = arrsig
+        self.xsig = xsig
+        self.ysig = ysig
+
+    def hash(self):
+        return (intmask(self.arrsig.hash() << 1) ^
+                intmask(self.xsig.hash() << 2) ^
+                intmask(self.ysig.hash() << 3))
+
+    def eq(self, other, compare_array_no=True):
+        if type(self) is not type(other):
+            return False
+        assert isinstance(other, WhereSignature)
+        return (self.arrsig.eq(other.arrsig, compare_array_no) and
+                self.xsig.eq(other.xsig, compare_array_no) and
+                self.ysig.eq(other.ysig, compare_array_no))
+
+    def _invent_array_numbering(self, arr, cache):
+        from pypy.module.micronumpy.interp_arrayops import WhereArray
+        assert isinstance(arr, WhereArray)
+        self.arrsig._invent_array_numbering(arr.arr, cache)
+        self.xsig._invent_array_numbering(arr.x, cache)
+        self.ysig._invent_array_numbering(arr.y, cache)
+
+    def _invent_numbering(self, cache, allnumbers):
+        self.arrsig._invent_numbering(cache, allnumbers)
+        self.xsig._invent_numbering(cache, allnumbers)
+        self.ysig._invent_numbering(cache, allnumbers)
+
+    def _create_iter(self, iterlist, arraylist, arr, transforms):
+        from pypy.module.micronumpy.interp_arrayops import WhereArray
+
+        assert isinstance(arr, WhereArray)
+        # XXX this does not support broadcasting correctly
+        self.arrsig._create_iter(iterlist, arraylist, arr.arr, transforms)
+        self.xsig._create_iter(iterlist, arraylist, arr.x, transforms)
+        self.ysig._create_iter(iterlist, arraylist, arr.y, transforms)
+ 
+    def eval(self, frame, arr):
+        from pypy.module.micronumpy.interp_arrayops import WhereArray
+        assert isinstance(arr, WhereArray)
+        lhs = self.xsig.eval(frame, arr.x).convert_to(self.dtype)
+        rhs = self.ysig.eval(frame, arr.y).convert_to(self.dtype)
+        w_val = self.arrsig.eval(frame, arr.arr)
+        if self.arrdtype.itemtype.bool(w_val):
+            return lhs
+        else:
+            return rhs
+
+    def debug_repr(self):
+        return 'Where(%s, %s, %s)' % (self.arrsig.debug_repr(),
+                                      self.xsig.debug_repr(),
+                                      self.ysig.debug_repr())
diff --git a/pypy/module/micronumpy/test/test_arrayops.py b/pypy/module/micronumpy/test/test_arrayops.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_arrayops.py
@@ -0,0 +1,16 @@
+
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+class AppTestNumSupport(BaseNumpyAppTest):
+    def test_where(self):
+        from _numpypy import where, ones, zeros, array
+        a = [1, 2, 3, 0, -3]
+        a = where(array(a) > 0, ones(5), zeros(5))
+        assert (a == [1, 1, 1, 0, 0]).all()
+
+    def test_where_invalidates(self):
+        from _numpypy import where, ones, zeros, array
+        a = array([1, 2, 3, 0, -3])
+        b = where(a > 0, ones(5), zeros(5))
+        a[0] = 0
+        assert (b == [1, 1, 1, 0, 0]).all()
diff --git a/pypy/module/micronumpy/test/test_compile.py b/pypy/module/micronumpy/test/test_compile.py
--- a/pypy/module/micronumpy/test/test_compile.py
+++ b/pypy/module/micronumpy/test/test_compile.py
@@ -270,3 +270,13 @@
         b -> 2
         """)
         assert interp.results[0].value == 3
+
+    def test_where(self):
+        interp = self.run('''
+        a = [1, 0, 3, 0]
+        b = [1, 1, 1, 1]
+        c = [0, 0, 0, 0]
+        d = where(a, b, c)
+        d -> 1
+        ''')
+        assert interp.results[0].value == 0
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -184,6 +184,33 @@
 
         assert dtype("float") is dtype(float)
 
+    def test_index_int8(self):
+        from _numpypy import array, int8
+
+        a = array(range(10), dtype=int8)
+        b = array([0] * 10, dtype=int8)
+        for idx in b: a[idx] += 1
+
+    def test_index_int16(self):
+        from _numpypy import array, int16
+
+        a = array(range(10), dtype=int16)
+        b = array([0] * 10, dtype=int16)
+        for idx in b: a[idx] += 1
+
+    def test_index_int32(self):
+        from _numpypy import array, int32
+
+        a = array(range(10), dtype=int32)
+        b = array([0] * 10, dtype=int32)
+        for idx in b: a[idx] += 1
+
+    def test_index_int64(self):
+        from _numpypy import array, int64
+
+        a = array(range(10), dtype=int64)
+        b = array([0] * 10, dtype=int64)
+        for idx in b: a[idx] += 1
 
 class AppTestTypes(BaseNumpyAppTest):    
     def test_abstract_types(self):
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1,9 +1,8 @@
 
 import py
 
-from pypy.conftest import gettestobjspace, option
+from pypy.conftest import option
 from pypy.interpreter.error import OperationError
-from pypy.module.micronumpy import signature
 from pypy.module.micronumpy.appbridge import get_appbridge_cache
 from pypy.module.micronumpy.interp_iter import Chunk, Chunks
 from pypy.module.micronumpy.interp_numarray import W_NDimArray, shape_agreement
@@ -1831,6 +1830,19 @@
         a[a & 1 == 1] = array([8, 9, 10])
         assert (a == [[0, 8], [2, 9], [4, 10]]).all()
 
+    def test_array_indexing_bool_setitem_multidim(self):
+        from _numpypy import arange
+        a = arange(10).reshape(5, 2)
+        a[a & 1 == 0] = 15
+        assert (a == [[15, 1], [15, 3], [15, 5], [15, 7], [15, 9]]).all()
+
+    def test_array_indexing_bool_setitem_2(self):
+        from _numpypy import arange
+        a = arange(10).reshape(5, 2)
+        a = a[::2]
+        a[a & 1 == 0] = 15
+        assert (a == [[15, 1], [15, 5], [15, 9]]).all()
+
     def test_copy_kwarg(self):
         from _numpypy import array
         x = array([1, 2, 3])
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -1,7 +1,6 @@
 
 from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
 
-
 class AppTestUfuncs(BaseNumpyAppTest):
     def test_ufunc_instance(self):
         from _numpypy import add, ufunc
@@ -149,7 +148,11 @@
         assert math.isnan(fmax(0, nan))
         assert math.isnan(fmax(nan, nan))
         # The numpy docs specify that the FIRST NaN should be used if both are NaN
-        assert math.copysign(1.0, fmax(nnan, nan)) == -1.0
+        # Since comparisons with nnan and nan all return false,
+        # use copysign on both sides to sidestep bug in nan representaion
+        # on Microsoft win32
+        assert math.copysign(1., fmax(nnan, nan)) == math.copysign(1., nnan)
+
 
     def test_fmin(self):
         from _numpypy import fmin
@@ -165,7 +168,9 @@
         assert math.isnan(fmin(0, nan))
         assert math.isnan(fmin(nan, nan))
         # The numpy docs specify that the FIRST NaN should be used if both are NaN
-        assert math.copysign(1.0, fmin(nnan, nan)) == -1.0
+        # use copysign on both sides to sidestep bug in nan representaion
+        # on Microsoft win32
+        assert math.copysign(1., fmin(nnan, nan)) == math.copysign(1., nnan)
 
     def test_fmod(self):
         from _numpypy import fmod
@@ -762,6 +767,8 @@
 
     def test_logaddexp(self):
         import math
+        import sys
+        float_max, float_min = sys.float_info.max, sys.float_info.min
         from _numpypy import logaddexp
 
         # From the numpy documentation
@@ -772,7 +779,8 @@
 
         assert logaddexp(0, 0) == math.log(2)
         assert logaddexp(float('-inf'), 0) == 0
-        assert logaddexp(12345678, 12345678) == float('inf')
+        assert logaddexp(float_max, float_max) == float_max
+        assert logaddexp(float_min, float_min) == math.log(2)
 
         assert math.isnan(logaddexp(float('nan'), 1))
         assert math.isnan(logaddexp(1, float('nan')))
@@ -785,6 +793,8 @@
 
     def test_logaddexp2(self):
         import math
+        import sys
+        float_max, float_min = sys.float_info.max, sys.float_info.min
         from _numpypy import logaddexp2
         log2 = math.log(2)
 
@@ -796,7 +806,8 @@
 
         assert logaddexp2(0, 0) == 1
         assert logaddexp2(float('-inf'), 0) == 0
-        assert logaddexp2(12345678, 12345678) == float('inf')
+        assert logaddexp2(float_max, float_max) == float_max
+        assert logaddexp2(float_min, float_min) == 1.0
 
         assert math.isnan(logaddexp2(float('nan'), 1))
         assert math.isnan(logaddexp2(1, float('nan')))
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -17,6 +17,7 @@
                                                 'render_as_void': True})
 degToRad = math.pi / 180.0
 log2 = math.log(2)
+log2e = 1./log2
 
 def simple_unary_op(func):
     specialize.argtype(1)(func)
@@ -841,45 +842,26 @@
 
     @simple_binary_op
     def logaddexp(self, v1, v2):
-        try:
-            v1e = math.exp(v1)
-        except OverflowError:
-            v1e = rfloat.INFINITY
-        try:
-            v2e = math.exp(v2)
-        except OverflowError:
-            v2e = rfloat.INFINITY
+        tmp = v1 - v2
+        if tmp > 0:
+            return v1 + rfloat.log1p(math.exp(-tmp))
+        elif tmp <= 0:
+            return v2 + rfloat.log1p(math.exp(tmp))
+        else:
+            return v1 + v2
 
-        v12e = v1e + v2e
-        try:
-            return math.log(v12e)
-        except ValueError:
-            if v12e == 0.0:
-                # CPython raises ValueError here, so we have to check
-                # the value to find the correct numpy return value
-                return -rfloat.INFINITY
-            return rfloat.NAN
+    def npy_log2_1p(self, v):
+        return log2e * rfloat.log1p(v)
 
     @simple_binary_op
     def logaddexp2(self, v1, v2):
-        try:
-            v1e = math.pow(2, v1)
-        except OverflowError:
-            v1e = rfloat.INFINITY
-        try:
-            v2e = math.pow(2, v2)
-        except OverflowError:
-            v2e = rfloat.INFINITY
-
-        v12e = v1e + v2e
-        try:
-            return math.log(v12e) / log2
-        except ValueError:
-            if v12e == 0.0:
-                # CPython raises ValueError here, so we have to check
-                # the value to find the correct numpy return value
-                return -rfloat.INFINITY
-            return rfloat.NAN
+        tmp = v1 - v2
+        if tmp > 0:
+            return v1 + self.npy_log2_1p(math.pow(2, -tmp))
+        if tmp <= 0:
+            return v2 + self.npy_log2_1p(math.pow(2, tmp))
+        else:
+            return v1 + v2
 
 class NonNativeFloat(NonNativePrimitive, Float):
     _mixin_ = True
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -54,7 +54,8 @@
             cmdline += ['--jit', ','.join(jitcmdline)]
         cmdline.append(str(self.filepath))
         #
-        env={'PYPYLOG': self.log_string + ':' + str(logfile)}
+        env = os.environ.copy()
+        env['PYPYLOG'] = self.log_string + ':' + str(logfile)
         pipe = subprocess.Popen(cmdline,
                                 env=env,
                                 stdout=subprocess.PIPE,
diff --git a/pypy/module/pypyjit/test_pypy_c/test_exception.py b/pypy/module/pypyjit/test_pypy_c/test_exception.py
--- a/pypy/module/pypyjit/test_pypy_c/test_exception.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_exception.py
@@ -91,3 +91,29 @@
             --TICK--
             jump(..., descr=...)
         """)
+
+    def test_continue_in_finally(self):
+        # check that 'continue' inside a try:finally: block is correctly
+        # detected as closing a loop
+        py.test.skip("is this case important?")
+        def f(n):
+            i = 0
+            while 1:
+                try:
+                    if i < n:
+                        continue
+                finally:
+                    i += 1
+                return i
+
+        log = self.run(f, [2000])
+        assert log.result == 2001
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i40 = int_add_ovf(i31, 1)
+            guard_no_overflow(descr=...)
+            i41 = int_lt(i40, i33)
+            guard_true(i41, descr=...)
+            --TICK--
+            jump(..., descr=...)
+        """)
diff --git a/pypy/module/rctime/interp_time.py b/pypy/module/rctime/interp_time.py
--- a/pypy/module/rctime/interp_time.py
+++ b/pypy/module/rctime/interp_time.py
@@ -24,10 +24,9 @@
     from pypy.module.thread import ll_thread as thread
 
     eci = ExternalCompilationInfo(
+        includes = ['windows.h'],
         post_include_bits = ["BOOL pypy_timemodule_setCtrlHandler(HANDLE event);"],
         separate_module_sources=['''
-            #include <windows.h>
-
             static HANDLE interrupt_event;
 
             static BOOL WINAPI CtrlHandlerRoutine(
@@ -573,7 +572,7 @@
                 if i < length and format[i] == '#':
                     # not documented by python
                     i += 1
-                if i >= length or format[i] not in "aAbBcdfHIjmMpSUwWxXyYzZ%":
+                if i >= length or format[i] not in "aAbBcdHIjmMpSUwWxXyYzZ%":
                     raise OperationError(space.w_ValueError,
                                          space.wrap("invalid format string"))
             i += 1
diff --git a/pypy/module/zipimport/interp_zipimport.py b/pypy/module/zipimport/interp_zipimport.py
--- a/pypy/module/zipimport/interp_zipimport.py
+++ b/pypy/module/zipimport/interp_zipimport.py
@@ -229,7 +229,11 @@
         startpos = fullname.rfind('.') + 1 # 0 when not found
         assert startpos >= 0
         subname = fullname[startpos:]
-        return self.prefix + subname.replace('.', '/')
+        if ZIPSEP == os.path.sep:
+            return self.prefix + subname.replace('.', '/')
+        else:
+            return self.prefix.replace(os.path.sep, ZIPSEP) + \
+                    subname.replace('.', '/')
 
     def make_co_filename(self, filename):
         """
diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py
--- a/pypy/module/zipimport/test/test_zipimport.py
+++ b/pypy/module/zipimport/test/test_zipimport.py
@@ -314,13 +314,11 @@
         assert z.get_filename("package") == mod.__file__
 
     def test_subdirectory_twice(self):
-        import os, zipimport
+        #import os, zipimport
  
         self.writefile("package/__init__.py", "")
         self.writefile("package/subpackage/__init__.py", "")
         self.writefile("package/subpackage/foo.py", "")
-        import sys
-        print(sys.path)
         mod = __import__('package.subpackage.foo', None, None, [])
         assert mod
 
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -391,7 +391,8 @@
     def contains(space, w_container, w_item):
         w_descr = space.lookup(w_container, '__contains__')
         if w_descr is not None:
-            return space.get_and_call_function(w_descr, w_container, w_item)
+            w_result = space.get_and_call_function(w_descr, w_container, w_item)
+            return space.nonzero(w_result)
         return space.sequence_contains(w_container, w_item)
 
     def sequence_contains(space, w_container, w_item):
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -358,8 +358,8 @@
                     result = op(*args)
                 except Exception, e:
                     etype = e.__class__
-                    msg = "generated by a constant operation:  %s" % (
-                        name)
+                    msg = "generated by a constant operation:\n\t%s%r" % (
+                        name, tuple(args))
                     raise OperationThatShouldNotBePropagatedError(
                         self.wrap(etype), self.wrap(msg))
                 else:
diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py
--- a/pypy/objspace/std/model.py
+++ b/pypy/objspace/std/model.py
@@ -355,7 +355,10 @@
     __slots__ = ()
 
     def __repr__(self):
-        s = '%s(%s)' % (self.__class__.__name__, getattr(self, 'name', ''))
+        name = getattr(self, 'name', '')
+        if not isinstance(name, str):
+            name = ''
+        s = '%s(%s)' % (self.__class__.__name__, name)
         w_cls = getattr(self, 'w__class__', None)
         if w_cls is not None and w_cls is not self:
             s += ' instance of %s' % self.w__class__
diff --git a/pypy/objspace/std/test/test_methodcache.py b/pypy/objspace/std/test/test_methodcache.py
--- a/pypy/objspace/std/test/test_methodcache.py
+++ b/pypy/objspace/std/test/test_methodcache.py
@@ -70,8 +70,31 @@
             assert a.f() == 42 + i
             A.f = eval("lambda self: %s" % (42 + i + 1, ))
         cache_counter = __pypy__.method_cache_counter("f")
-        # the cache hits come from A.f = ..., which first does a lookup on A as
-        # well
+        #
+        # a bit of explanation about what's going on.  (1) is the line "a.f()"
+        # and (2) is "A.f = ...".
+        #
+        # at line (1) we do the lookup on type(a).f
+        #
+        # at line (2) we do a setattr on A. However, descr_setattr does also a
+        # lookup of type(A).f i.e. type.f, to check if by chance 'f' is a data
+        # descriptor.
+        #
+        # At the first iteration:
+        # (1) is a miss because it's the first lookup of A.f. The result is cached
+        #
+        # (2) is a miss because it is the first lookup of type.f. The
+        # (non-existant) result is cached. The version of A changes, and 'f'
+        # is changed to be a cell object, so that subsequest assignments won't
+        # change the version of A
+        #
+        # At the second iteration:
+        # (1) is a miss because the version of A changed just before
+        # (2) is a hit, because type.f is cached. The version of A no longer changes
+        #
+        # At the third and subsequent iterations:
+        # (1) is a hit, because the version of A did not change
+        # (2) is a hit, see above
         assert cache_counter == (17, 3)
 
     def test_subclasses(self):
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -640,5 +640,30 @@
                 except (Exception) as e_len:
                     assert str(e_bool) == str(e_len)
 
+    def test_bool___contains__(self):
+        class X(object):
+            def __contains__(self, item):
+                if item == 'foo':
+                    return 42
+                else:
+                    return 'hello world'
+        x = X()
+        res = 'foo' in x
+        assert res is True
+        res = 'bar' in x
+        assert res is True
+        #
+        class MyError(Exception):
+            pass
+        class CannotConvertToBool(object):
+            def __nonzero__(self):
+                raise MyError
+        class X(object):
+            def __contains__(self, item):
+                return CannotConvertToBool()
+        x = X()
+        raises(MyError, "'foo' in x")
+        
+            
 class AppTestWithBuiltinShortcut(AppTest_Descroperation):
     OPTIONS = {'objspace.std.builtinshortcut': True}
diff --git a/pypy/pytest.ini b/pypy/pytest.ini
--- a/pypy/pytest.ini
+++ b/pypy/pytest.ini
@@ -1,2 +1,2 @@
 [pytest]
-addopts = --assert=plain -rf
+addopts = --assert=reinterp -rf
diff --git a/pypy/rlib/parsing/test/test_ebnfparse.py b/pypy/rlib/parsing/test/test_ebnfparse.py
--- a/pypy/rlib/parsing/test/test_ebnfparse.py
+++ b/pypy/rlib/parsing/test/test_ebnfparse.py
@@ -103,6 +103,7 @@
 """)
     parse = make_parse_function(regexs, rules)
     tree = parse("prefix(\n\tlonger(and_nested(term(X))), Xya, _, X0, _).")
+    assert tree.children[0].children[0].children[2].children[0].getsourcepos().lineno == 1
     assert tree is not None
     tree = parse("""
 foo(X, Y) :- bar(Y, X), bar(Y, X) ; foobar(X, Y, 1234, atom).""")
diff --git a/pypy/rlib/parsing/tree.py b/pypy/rlib/parsing/tree.py
--- a/pypy/rlib/parsing/tree.py
+++ b/pypy/rlib/parsing/tree.py
@@ -23,6 +23,9 @@
         self.symbol = symbol
         self.additional_info = additional_info
         self.token = token
+
+    def getsourcepos(self):
+        return self.token.source_pos
     
     def __repr__(self):
         return "Symbol(%r, %r)" % (self.symbol, self.additional_info)
@@ -49,6 +52,9 @@
         self.children = children
         self.symbol = symbol
 
+    def getsourcepos(self):
+        return self.children[0].getsourcepos()
+
     def __str__(self):
         return "%s(%s)" % (self.symbol, ", ".join([str(c) for c in self.children]))
 
diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -40,7 +40,7 @@
 # In that case, do 5 bits at a time.  The potential drawback is that
 # a table of 2**5 intermediate results is computed.
 
-## FIVEARY_CUTOFF = 8   disabled for now
+FIVEARY_CUTOFF = 8
 
 
 def _mask_digit(x):
@@ -474,7 +474,7 @@
 
         # python adaptation: moved macros REDUCE(X) and MULT(X, Y, result)
         # into helper function result = _help_mult(x, y, c)
-        if 1:   ## b.numdigits() <= FIVEARY_CUTOFF:
+        if b.numdigits() <= FIVEARY_CUTOFF:
             # Left-to-right binary exponentiation (HAC Algorithm 14.79)
             # http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
             i = b.numdigits() - 1
@@ -487,30 +487,51 @@
                         z = _help_mult(z, a, c)
                     j >>= 1
                 i -= 1
-##        else:
-##            This code is disabled for now, because it assumes that
-##            SHIFT is a multiple of 5.  It could be fixed but it looks
-##            like it's more troubles than benefits...
-##
-##            # Left-to-right 5-ary exponentiation (HAC Algorithm 14.82)
-##            # This is only useful in the case where c != None.
-##            # z still holds 1L
-##            table = [z] * 32
-##            table[0] = z
-##            for i in range(1, 32):
-##                table[i] = _help_mult(table[i-1], a, c)
-##            i = b.numdigits() - 1
-##            while i >= 0:
-##                bi = b.digit(i)
-##                j = SHIFT - 5
-##                while j >= 0:
-##                    index = (bi >> j) & 0x1f
-##                    for k in range(5):
-##                        z = _help_mult(z, z, c)
-##                    if index:
-##                        z = _help_mult(z, table[index], c)
-##                    j -= 5
-##                i -= 1
+        else:
+            # Left-to-right 5-ary exponentiation (HAC Algorithm 14.82)
+            # This is only useful in the case where c != None.
+            # z still holds 1L
+            table = [z] * 32
+            table[0] = z
+            for i in range(1, 32):
+                table[i] = _help_mult(table[i-1], a, c)
+            i = b.numdigits()
+            # Note that here SHIFT is not a multiple of 5.  The difficulty
+            # is to extract 5 bits at a time from 'b', starting from the
+            # most significant digits, so that at the end of the algorithm
+            # it falls exactly to zero.
+            # m  = max number of bits = i * SHIFT
+            # m+ = m rounded up to the next multiple of 5
+            # j  = (m+) % SHIFT = (m+) - (i * SHIFT)
+            # (computed without doing "i * SHIFT", which might overflow)
+            j = i % 5
+            if j != 0:
+                j = 5 - j
+            if not we_are_translated():
+                assert j == (i*SHIFT+4)//5*5 - i*SHIFT
+            #
+            accum = r_uint(0)
+            while True:
+                j -= 5
+                if j >= 0:
+                    index = (accum >> j) & 0x1f
+                else:
+                    # 'accum' does not have enough digit.
+                    # must get the next digit from 'b' in order to complete
+                    i -= 1
+                    if i < 0:
+                        break    # done
+                    bi = b.udigit(i)
+                    index = ((accum << (-j)) | (bi >> (j+SHIFT))) & 0x1f
+                    accum = bi
+                    j += SHIFT
+                #
+                for k in range(5):
+                    z = _help_mult(z, z, c)
+                if index:
+                    z = _help_mult(z, table[index], c)
+            #
+            assert j == -5
 
         if negativeOutput and z.sign != 0:
             z = z.sub(c)
diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py
--- a/pypy/rlib/ropenssl.py
+++ b/pypy/rlib/ropenssl.py
@@ -4,8 +4,10 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib.unroll import unrolling_iterable
 
-import sys
+import sys, os
 
+link_files = []
+testonly_libraries = []
 if sys.platform == 'win32' and platform.name != 'mingw32':
     libraries = ['libeay32', 'ssleay32',
                  'user32', 'advapi32', 'gdi32', 'msvcrt', 'ws2_32']
@@ -18,8 +20,18 @@
         # so that openssl/ssl.h can repair this nonsense.
         'wincrypt.h']
 else:
-    libraries = ['ssl', 'crypto']
+    libraries = ['z']
     includes = []
+    if (sys.platform.startswith('linux') and
+        os.path.exists('/usr/lib/libssl.a') and
+        os.path.exists('/usr/lib/libcrypto.a')):
+        # use static linking to avoid the infinite
+        # amount of troubles due to symbol versions
+        # and 0.9.8/1.0.0
+        link_files += ['/usr/lib/libssl.a', '/usr/lib/libcrypto.a']
+        testonly_libraries += ['ssl', 'crypto']
+    else:
+        libraries += ['ssl', 'crypto']
 
 includes += [
     'openssl/ssl.h', 
@@ -31,6 +43,8 @@
 
 eci = ExternalCompilationInfo(
     libraries = libraries,
+    link_files = link_files,
+    testonly_libraries = testonly_libraries,
     includes = includes,
     export_symbols = [],
     post_include_bits = [
diff --git a/pypy/rlib/rposix.py b/pypy/rlib/rposix.py
--- a/pypy/rlib/rposix.py
+++ b/pypy/rlib/rposix.py
@@ -1,9 +1,11 @@
 import os
-from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable, INT
+from pypy.rpython.lltypesystem.rffi import (CConstant, CExternVariable,
+        INT, CCHARPP)
 from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import specialize
+from pypy.rlib import jit
 
 class CConstantErrno(CConstant):
     # these accessors are used when calling get_errno() or set_errno()
@@ -18,9 +20,69 @@
     def __setitem__(self, index, value):
         assert index == 0
         ll2ctypes.TLS.errno = value
+if os.name == 'nt':
+    separate_module_sources =['''
+        /* Lifted completely from CPython 3.3 Modules/posix_module.c */
+        #include <malloc.h> /* for _msize */
+        typedef struct {
+            intptr_t osfhnd;
+            char osfile;
+        } my_ioinfo;
+        extern __declspec(dllimport) char * __pioinfo[];
+        #define IOINFO_L2E 5
+        #define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
+        #define IOINFO_ARRAYS 64
+        #define _NHANDLE_           (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
+        #define FOPEN 0x01
+        #define _NO_CONSOLE_FILENO (intptr_t)-2
 
+        /* This function emulates what the windows CRT
+            does to validate file handles */
+        int
+        _PyVerify_fd(int fd)
+        {
+            const int i1 = fd >> IOINFO_L2E;
+            const int i2 = fd & ((1 << IOINFO_L2E) - 1);
+
+            static size_t sizeof_ioinfo = 0;
+
+            /* Determine the actual size of the ioinfo structure,
+             * as used by the CRT loaded in memory
+             */
+            if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
+                sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
+            }
+            if (sizeof_ioinfo == 0) {
+                /* This should not happen... */
+                goto fail;
+            }
+
+            /* See that it isn't a special CLEAR fileno */
+                if (fd != _NO_CONSOLE_FILENO) {
+                /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that.  Instead
+                 * we check pointer validity and other info
+                 */
+                if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
+                    /* finally, check that the file is open */
+                    my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
+                    if (info->osfile & FOPEN) {
+                        return 1;
+                    }
+                }
+            }
+          fail:
+            errno = EBADF;
+            return 0;
+        }
+    ''',]
+    export_symbols = ['_PyVerify_fd']
+else:
+    separate_module_sources = []
+    export_symbols = []
 errno_eci = ExternalCompilationInfo(
-    includes=['errno.h']
+    includes=['errno.h','stdio.h'],
+    separate_module_sources = separate_module_sources,
+    export_symbols = export_symbols,
 )
 
 _get_errno, _set_errno = CExternVariable(INT, 'errno', errno_eci,
@@ -35,6 +97,21 @@
 def set_errno(errno):
     _set_errno(rffi.cast(INT, errno))
 
+if os.name == 'nt':
+    _validate_fd = rffi.llexternal(
+        "_PyVerify_fd", [rffi.INT], rffi.INT,
+        compilation_info=errno_eci,
+        )
+    @jit.dont_look_inside
+    def validate_fd(fd):
+        if not _validate_fd(fd):
+            raise OSError(get_errno(), 'Bad file descriptor')
+else:
+    def _validate_fd(fd):
+        return 1
+
+    def validate_fd(fd):
+        return 1
 
 def closerange(fd_low, fd_high):
     # this behaves like os.closerange() from Python 2.6.
diff --git a/pypy/rlib/runicode.py b/pypy/rlib/runicode.py
--- a/pypy/rlib/runicode.py
+++ b/pypy/rlib/runicode.py
@@ -1239,7 +1239,7 @@
             pos += 1
             continue
 
-        if 0xD800 <= oc < 0xDC00 and pos + 1 < size:
+        if MAXUNICODE < 65536 and 0xD800 <= oc < 0xDC00 and pos + 1 < size:
             # Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes
             pos += 1
             oc2 = ord(s[pos])
@@ -1355,6 +1355,20 @@
     pos = 0
     while pos < size:
         oc = ord(s[pos])
+
+        if MAXUNICODE < 65536 and 0xD800 <= oc < 0xDC00 and pos + 1 < size:
+            # Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes
+            pos += 1
+            oc2 = ord(s[pos])
+
+            if 0xDC00 <= oc2 <= 0xDFFF:
+                ucs = (((oc & 0x03FF) << 10) | (oc2 & 0x03FF)) + 0x00010000
+                raw_unicode_escape_helper(result, ucs)
+                pos += 1
+                continue
+            # Fall through: isolated surrogates are copied as-is
+            pos -= 1
+
         if oc < 0x100:
             result.append(chr(oc))
         else:
diff --git a/pypy/rlib/rweakref.py b/pypy/rlib/rweakref.py
--- a/pypy/rlib/rweakref.py
+++ b/pypy/rlib/rweakref.py
@@ -9,6 +9,9 @@
 
 ref = weakref.ref    # basic regular weakrefs are supported in RPython
 
+def has_weakref_support():
+    return True      # returns False if --no-translation-rweakref
+
 
 class RWeakValueDictionary(object):
     """A dictionary containing weak values."""
@@ -68,6 +71,20 @@
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.tool.pairtype import pairtype
 
+class Entry(extregistry.ExtRegistryEntry):
+    _about_ = has_weakref_support
+
+    def compute_result_annotation(self):
+        translator = self.bookkeeper.annotator.translator
+        res = translator.config.translation.rweakref
+        return self.bookkeeper.immutablevalue(res)
+
+    def specialize_call(self, hop):
+        from pypy.rpython.lltypesystem import lltype
+        hop.exception_cannot_occur()
+        return hop.inputconst(lltype.Bool, hop.s_result.const)
+
+
 class SomeWeakValueDict(annmodel.SomeObject):
     knowntype = RWeakValueDictionary
 
diff --git a/pypy/rlib/test/test_rbigint.py b/pypy/rlib/test/test_rbigint.py
--- a/pypy/rlib/test/test_rbigint.py
+++ b/pypy/rlib/test/test_rbigint.py
@@ -379,6 +379,18 @@
         for n, expected in [(37, 9), (1291, 931), (67889, 39464)]:
             v = two.pow(t, rbigint.fromint(n))
             assert v.toint() == expected
+        #
+        # more tests, comparing against CPython's answer
+        enabled = sample(range(5*32), 10)
+        for i in range(5*32):
+            t = t.mul(two)      # add one random bit
+            if random() >= 0.5:
+                t = t.add(rbigint.fromint(1))
+            if i not in enabled:
+                continue    # don't take forever
+            n = randint(1, sys.maxint)
+            v = two.pow(t, rbigint.fromint(n))
+            assert v.toint() == pow(2, t.tolong(), n)
 
     def test_pow_lln(self):
         x = 10L
diff --git a/pypy/rlib/test/test_rposix.py b/pypy/rlib/test/test_rposix.py
--- a/pypy/rlib/test/test_rposix.py
+++ b/pypy/rlib/test/test_rposix.py
@@ -131,3 +131,15 @@
                 os.rmdir(self.ufilename)
             except Exception:
                 pass
+
+    def test_validate_fd(self):
+        if os.name != 'nt':
+            skip('relevant for windows only')
+        assert rposix._validate_fd(0) == 1
+        fid = open(str(udir.join('validate_test.txt')), 'w')
+        fd = fid.fileno()
+        assert rposix._validate_fd(fd) == 1
+        fid.close()
+        assert rposix._validate_fd(fd) == 0
+
+
diff --git a/pypy/rlib/test/test_runicode.py b/pypy/rlib/test/test_runicode.py
--- a/pypy/rlib/test/test_runicode.py
+++ b/pypy/rlib/test/test_runicode.py
@@ -731,3 +731,18 @@
 
         res = interpret(f, [0x10140])
         assert res == 0x10140
+
+    def test_encode_surrogate_pair(self):
+        u = runicode.UNICHR(0xD800) + runicode.UNICHR(0xDC00)
+        if runicode.MAXUNICODE < 65536:
+            # Narrow unicode build, consider utf16 surrogate pairs
+            assert runicode.unicode_encode_unicode_escape(
+                u, len(u), True) == r'\U00010000'
+            assert runicode.unicode_encode_raw_unicode_escape(
+                u, len(u), True) == r'\U00010000'
+        else:
+            # Wide unicode build, don't merge utf16 surrogate pairs
+            assert runicode.unicode_encode_unicode_escape(
+                u, len(u), True) == r'\ud800\udc00'
+            assert runicode.unicode_encode_raw_unicode_escape(
+                u, len(u), True) == r'\ud800\udc00'
diff --git a/pypy/rlib/test/test_rweakref.py b/pypy/rlib/test/test_rweakref.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/test/test_rweakref.py
@@ -0,0 +1,14 @@
+from pypy.rlib.rweakref import has_weakref_support
+from pypy.rpython.test.test_llinterp import interpret
+
+
+def test_has_weakref_support():
+    assert has_weakref_support()
+
+    res = interpret(lambda: has_weakref_support(), [],
+                    **{'translation.rweakref': True})
+    assert res == True
+
+    res = interpret(lambda: has_weakref_support(), [],
+                    **{'translation.rweakref': False})
+    assert res == False
diff --git a/pypy/rpython/annlowlevel.py b/pypy/rpython/annlowlevel.py
--- a/pypy/rpython/annlowlevel.py
+++ b/pypy/rpython/annlowlevel.py
@@ -488,6 +488,8 @@
     else:
         TO = PTR
     if not hasattr(object, '_carry_around_for_tests'):
+        if object is None:
+            return lltype.nullptr(PTR.TO)
         assert not hasattr(object, '_TYPE')
         object._carry_around_for_tests = True
         object._TYPE = TO
@@ -557,6 +559,8 @@
     """NOT_RPYTHON: hack. Reverse the hacking done in cast_object_to_ptr()."""
     if isinstance(lltype.typeOf(ptr), lltype.Ptr):
         ptr = ptr._as_obj()
+        if ptr is None:
+            return None
     if not isinstance(ptr, Class):
         raise NotImplementedError("cast_base_ptr_to_instance: casting %r to %r"
                                   % (ptr, Class))
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -1072,7 +1072,7 @@
     try:
         eci = _eci_cache[old_eci]
     except KeyError:
-        eci = old_eci.compile_shared_lib()
+        eci = old_eci.compile_shared_lib(ignore_a_files=True)
         _eci_cache[old_eci] = eci
 
     libraries = eci.testonly_libraries + eci.libraries + eci.frameworks
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -1167,7 +1167,7 @@
         try:
             return self._lookup_adtmeth(field_name)
         except AttributeError:
-            raise AttributeError("%r instance has no field %r" % (self._T._name,
+            raise AttributeError("%r instance has no field %r" % (self._T,
                                                                   field_name))
 
     def __setattr__(self, field_name, val):
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -1168,8 +1168,11 @@
             DIRENTP = lltype.Ptr(DIRENT)
             os_opendir = self.llexternal('opendir', [rffi.CCHARP], DIRP,
                                          compilation_info=compilation_info)
+            # XXX macro=True is hack to make sure we get the correct kind of
+            # dirent struct (which depends on defines)
             os_readdir = self.llexternal('readdir', [DIRP], DIRENTP,
-                                         compilation_info=compilation_info)
+                                         compilation_info=compilation_info,
+                                         macro=True)
             os_closedir = self.llexternal('closedir', [DIRP], rffi.INT,
                                           compilation_info=compilation_info)
 
diff --git a/pypy/rpython/module/test/test_ll_os.py b/pypy/rpython/module/test/test_ll_os.py
--- a/pypy/rpython/module/test/test_ll_os.py
+++ b/pypy/rpython/module/test/test_ll_os.py
@@ -4,6 +4,7 @@
 import pypy
 from pypy.tool.udir import udir
 from pypy.translator.c.test.test_genc import compile
+from pypy.rpython.module import ll_os #has side effect of registering functions
 
 from pypy.rpython import extregistry
 import errno
diff --git a/pypy/rpython/test/test_llann.py b/pypy/rpython/test/test_llann.py
--- a/pypy/rpython/test/test_llann.py
+++ b/pypy/rpython/test/test_llann.py
@@ -9,6 +9,7 @@
 from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
 from pypy.rpython.annlowlevel import PseudoHighLevelCallable
 from pypy.rpython.annlowlevel import llhelper, cast_instance_to_base_ptr
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
 from pypy.rpython.annlowlevel import base_ptr_lltype
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.test.test_llinterp import interpret
@@ -502,7 +503,10 @@
             self.y = y
 
     def f(x, y):
-        a = A(x, y)
+        if x > 20:
+            a = None
+        else:
+            a = A(x, y)
         a1 = cast_instance_to_base_ptr(a)
         return a1
 
@@ -510,3 +514,30 @@
     assert typeOf(res) == base_ptr_lltype()
     assert fishllattr(res, 'x') == 5
     assert fishllattr(res, 'y') == 10
+
+    res = interpret(f, [25, 10])
+    assert res == nullptr(base_ptr_lltype().TO)
+
+
+def test_cast_base_ptr_to_instance():
+    class A:
+        def __init__(self, x, y):
+            self.x = x
+            self.y = y
+
+    def f(x, y):
+        if x > 20:
+            a = None
+        else:
+            a = A(x, y)
+        a1 = cast_instance_to_base_ptr(a)
+        b = cast_base_ptr_to_instance(A, a1)
+        return a is b
+
+    assert f(5, 10) is True
+    assert f(25, 10) is True
+
+    res = interpret(f, [5, 10])
+    assert res is True
+    res = interpret(f, [25, 10])
+    assert res is True
diff --git a/pypy/rpython/tool/rffi_platform.py b/pypy/rpython/tool/rffi_platform.py
--- a/pypy/rpython/tool/rffi_platform.py
+++ b/pypy/rpython/tool/rffi_platform.py
@@ -379,7 +379,7 @@
         self.name = name
 
     def prepare_code(self):
-        yield 'if ((%s) < 0) {' % (self.name,)
+        yield 'if ((%s) <= 0) {' % (self.name,)
         yield '    long long x = (long long)(%s);' % (self.name,)
         yield '    printf("value: %lld\\n", x);'
         yield '} else {'
@@ -401,7 +401,7 @@
     def prepare_code(self):
         yield '#ifdef %s' % self.macro
         yield 'dump("defined", 1);'
-        yield 'if ((%s) < 0) {' % (self.macro,)
+        yield 'if ((%s) <= 0) {' % (self.macro,)
         yield '    long long x = (long long)(%s);' % (self.macro,)
         yield '    printf("value: %lld\\n", x);'
         yield '} else {'
diff --git a/pypy/tool/compare_last_builds.py b/pypy/tool/compare_last_builds.py
new file mode 100644
--- /dev/null
+++ b/pypy/tool/compare_last_builds.py
@@ -0,0 +1,122 @@
+import os
+import urllib2
+import json
+import sys
+import md5
+
+wanted = sys.argv[1:]
+if not wanted:
+    wanted = ['default']
+base = "http://buildbot.pypy.org/json/builders/"
+
+cachedir = os.environ.get('PYPY_BUILDS_CACHE')
+if cachedir and not os.path.exists(cachedir):
+    os.makedirs(cachedir)
+
+
+
+def get_json(url, cache=cachedir):
+    return json.loads(get_data(url, cache))
+
+
+def get_data(url, cache=cachedir):
+    url = str(url)
+    if cache:
+        digest = md5.md5()
+        digest.update(url)
+        digest = digest.hexdigest()
+        cachepath = os.path.join(cachedir, digest)
+        if os.path.exists(cachepath):
+            with open(cachepath) as fp:
+                return fp.read()
+
+    print 'GET', url
+    fp = urllib2.urlopen(url)
+    try:
+        data = fp.read()
+        if cache:
+            with open(cachepath, 'wb') as cp:
+                cp.write(data)
+        return data
+    finally:
+        fp.close()
+
+def parse_log(log):
+    items = []
+    for v in log.splitlines(1):
+        if not v[0].isspace() and v[1].isspace():
+            items.append(v)
+    return sorted(items) #sort cause testrunner order is non-deterministic
+
+def gather_logdata(build):
+    logdata = get_data(str(build['log']) + '?as_text=1')
+    logdata = logdata.replace('</span><span class="stdout">', '')
+    logdata = logdata.replace('</span></pre>', '')
+    del build['log']
+    build['log'] = parse_log(logdata)
+
+
+def branch_mapping(l):
+    keep = 3 - len(wanted)
+    d = {}
+    for x in reversed(l):
+        gather_logdata(x)
+        if not x['log']:
+            continue
+        b = x['branch']
+        if b not in d:
+            d[b] = []
+        d[b].insert(0, x)
+        if len(d[b]) > keep:
+            d[b].pop()
+    return d
+
+def cleanup_build(d):
+    for a in 'times eta steps slave reason sourceStamp blame currentStep text'.split():
+        del d[a]
+
+    props = d.pop(u'logs')
+    for name, val in props:
+        if name == u'pytestLog':
+            d['log'] = val
+    props = d.pop(u'properties')
+    for name, val, _ in props:
+        if name == u'branch':
+            d['branch'] = val or 'default'
+    return d
+
+def collect_builds(d):
+    name = str(d['basedir'])
+    builds = d['cachedBuilds']
+    l = []
+    for build in builds:
+        d = get_json(base + '%s/builds/%s' % (name, build))
+        cleanup_build(d)
+        l.append(d)
+
+    l = [x for x in l if x['branch'] in wanted and 'log' in x]
+    d = branch_mapping(l)
+    return [x for lst in d.values() for x in lst]
+
+
+def only_linux32(d):
+    return d['own-linux-x86-32']
+
+
+own_builds = get_json(base, cache=False)['own-linux-x86-32']
+
+builds = collect_builds(own_builds)
+
+
+builds.sort(key=lambda x: (wanted.index(x['branch']), x['number']))
+logs = [x.pop('log') for x in builds]
+for b, s in zip(builds, logs):
+    b['resultset'] = len(s)
+import pprint
+pprint.pprint(builds)
+
+from difflib import Differ
+
+for x in Differ().compare(*logs):
+    if x[0]!=' ':
+        sys.stdout.write(x)
diff --git a/pypy/tool/pytest/pypy_test_failure_demo.py b/pypy/tool/pytest/pypy_test_failure_demo.py
--- a/pypy/tool/pytest/pypy_test_failure_demo.py
+++ b/pypy/tool/pytest/pypy_test_failure_demo.py
@@ -8,6 +8,10 @@
 def test_interp_func(space): 
     assert space.is_true(space.w_None) 
 
+def test_interp_reinterpret(space):
+    a = 1
+    assert a == 2
+
 class TestInterpTest: 
     def test_interp_method(self): 
         assert self.space.is_true(self.space.w_False) 
diff --git a/pypy/translator/c/extfunc.py b/pypy/translator/c/extfunc.py
--- a/pypy/translator/c/extfunc.py
+++ b/pypy/translator/c/extfunc.py
@@ -5,7 +5,6 @@
 from pypy.rpython.lltypesystem.rstr import STR, mallocstr
 from pypy.rpython.lltypesystem import rstr
 from pypy.rpython.lltypesystem import rlist
-from pypy.rpython.module import ll_time, ll_os
 
 # table of functions hand-written in src/ll_*.h
 # Note about *.im_func: The annotator and the rtyper expect direct
diff --git a/pypy/translator/c/src/cjkcodecs/cjkcodecs.h b/pypy/translator/c/src/cjkcodecs/cjkcodecs.h
--- a/pypy/translator/c/src/cjkcodecs/cjkcodecs.h
+++ b/pypy/translator/c/src/cjkcodecs/cjkcodecs.h
@@ -210,15 +210,15 @@
 
 #define BEGIN_CODECS_LIST /* empty */
 #define _CODEC(name)                                                    \
-  static const MultibyteCodec _pypy_cjkcodec_##name;                    \
-  const MultibyteCodec *pypy_cjkcodec_##name(void) {                    \
+  static MultibyteCodec _pypy_cjkcodec_##name;                          \
+  MultibyteCodec *pypy_cjkcodec_##name(void) {                          \
     if (_pypy_cjkcodec_##name.codecinit != NULL) {                      \
       int r = _pypy_cjkcodec_##name.codecinit(_pypy_cjkcodec_##name.config); \
       assert(r == 0);                                                   \
     }                                                                   \
     return &_pypy_cjkcodec_##name;                                      \
   }                                                                     \
-  static const MultibyteCodec _pypy_cjkcodec_##name
+  static MultibyteCodec _pypy_cjkcodec_##name
 #define _STATEFUL_METHODS(enc)          \
     enc##_encode,                       \
     enc##_encode_init,                  \
diff --git a/pypy/translator/c/src/cjkcodecs/multibytecodec.h b/pypy/translator/c/src/cjkcodecs/multibytecodec.h
--- a/pypy/translator/c/src/cjkcodecs/multibytecodec.h
+++ b/pypy/translator/c/src/cjkcodecs/multibytecodec.h
@@ -131,7 +131,7 @@
 /* list of codecs defined in the .c files */
 
 #define DEFINE_CODEC(name)                              \
-    const MultibyteCodec *pypy_cjkcodec_##name(void);
+    MultibyteCodec *pypy_cjkcodec_##name(void);
 
 // _codecs_cn
 DEFINE_CODEC(gb2312)
diff --git a/pypy/translator/c/src/exception.h b/pypy/translator/c/src/exception.h
--- a/pypy/translator/c/src/exception.h
+++ b/pypy/translator/c/src/exception.h
@@ -43,6 +43,16 @@
           filename, lineno, functionname);
 }
 #endif
+#else   /* !DO_LOG_EXC: define the function anyway, so that we can shut
+           off the prints of a debug_exc by remaking only testing_1.o */
+void RPyDebugReturnShowException(const char *msg, const char *filename,
+                                 long lineno, const char *functionname);
+#ifndef PYPY_NOT_MAIN_FILE
+void RPyDebugReturnShowException(const char *msg, const char *filename,
+                                 long lineno, const char *functionname)
+{
+}
+#endif
 #endif  /* DO_LOG_EXC */
 
 /* Hint: functions and macros not defined here, like RPyRaiseException,
diff --git a/pypy/translator/tool/cbuild.py b/pypy/translator/tool/cbuild.py
--- a/pypy/translator/tool/cbuild.py
+++ b/pypy/translator/tool/cbuild.py
@@ -267,9 +267,12 @@
         d['separate_module_files'] = ()
         return files, ExternalCompilationInfo(**d)
 
-    def compile_shared_lib(self, outputfilename=None):
+    def compile_shared_lib(self, outputfilename=None, ignore_a_files=False):
         self = self.convert_sources_to_files()
-        if not self.separate_module_files:
+        if ignore_a_files:
+            if not [fn for fn in self.link_files if fn.endswith('.a')]:
+                ignore_a_files = False    # there are none
+        if not self.separate_module_files and not ignore_a_files:
             if sys.platform != 'win32':
                 return self
             if not self.export_symbols:
@@ -288,6 +291,13 @@
                 num += 1
             basepath.ensure(dir=1)
             outputfilename = str(pth.dirpath().join(pth.purebasename))
+
+        if ignore_a_files:
+            d = self._copy_attributes()
+            d['link_files'] = [fn for fn in d['link_files']
+                                  if not fn.endswith('.a')]
+            self = ExternalCompilationInfo(**d)
+
         lib = str(host.compile([], self, outputfilename=outputfilename,
                                standalone=False))
         d = self._copy_attributes()


More information about the pypy-commit mailing list