[pypy-svn] r74324 - in pypy/branch/py12: . lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/command pypy pypy/_interfaces pypy/annotation pypy/annotation/test pypy/config pypy/doc pypy/doc/config pypy/interpreter pypy/interpreter/test pypy/jit/backend/test pypy/jit/backend/x86/test pypy/jit/metainterp pypy/lib pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/src pypy/module/cpyext/test pypy/module/imp pypy/module/thread pypy/module/thread/test pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/test pypy/tool pypy/translator pypy/translator/c pypy/translator/c/gcc pypy/translator/c/gcc/test pypy/translator/c/src pypy/translator/c/test pypy/translator/goal pypy/translator/platform pypy/translator/test pypy/translator/tool pypy/translator/tool/test

hpk at codespeak.net hpk at codespeak.net
Sun May 2 18:05:14 CEST 2010


Author: hpk
Date: Sun May  2 18:05:10 2010
New Revision: 74324

Added:
   pypy/branch/py12/pypy/_interfaces/   (props changed)
      - copied from r74323, pypy/trunk/pypy/_interfaces/
   pypy/branch/py12/pypy/doc/config/objspace.usemodules.cpyext.txt
      - copied unchanged from r74323, pypy/trunk/pypy/doc/config/objspace.usemodules.cpyext.txt
   pypy/branch/py12/pypy/doc/config/translation.secondaryentrypoints.txt
      - copied unchanged from r74323, pypy/trunk/pypy/doc/config/translation.secondaryentrypoints.txt
   pypy/branch/py12/pypy/doc/config/translation.shared.txt
      - copied unchanged from r74323, pypy/trunk/pypy/doc/config/translation.shared.txt
   pypy/branch/py12/pypy/module/cpyext/   (props changed)
      - copied from r74323, pypy/trunk/pypy/module/cpyext/
   pypy/branch/py12/pypy/rlib/_rweakkeydict.py
      - copied unchanged from r74323, pypy/trunk/pypy/rlib/_rweakkeydict.py
   pypy/branch/py12/pypy/rlib/_rweakvaldict.py
      - copied unchanged from r74323, pypy/trunk/pypy/rlib/_rweakvaldict.py
   pypy/branch/py12/pypy/rlib/entrypoint.py
      - copied unchanged from r74323, pypy/trunk/pypy/rlib/entrypoint.py
   pypy/branch/py12/pypy/rlib/exports.py
      - copied unchanged from r74323, pypy/trunk/pypy/rlib/exports.py
   pypy/branch/py12/pypy/rlib/test/test_rweakkeydict.py
      - copied unchanged from r74323, pypy/trunk/pypy/rlib/test/test_rweakkeydict.py
   pypy/branch/py12/pypy/rlib/test/test_rweakvaldict.py
      - copied unchanged from r74323, pypy/trunk/pypy/rlib/test/test_rweakvaldict.py
Removed:
   pypy/branch/py12/pypy/doc/README.Debian
   pypy/branch/py12/pypy/doc/README.compiling
   pypy/branch/py12/pypy/rlib/rweakrefimpl.py
   pypy/branch/py12/pypy/rlib/test/test_rweakref.py
Modified:
   pypy/branch/py12/   (props changed)
   pypy/branch/py12/lib-python/modified-2.5.2/distutils/command/build_ext.py
   pypy/branch/py12/lib-python/modified-2.5.2/distutils/msvccompiler.py
   pypy/branch/py12/lib-python/modified-2.5.2/distutils/spawn.py
   pypy/branch/py12/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py
   pypy/branch/py12/pypy/annotation/annrpython.py
   pypy/branch/py12/pypy/annotation/description.py
   pypy/branch/py12/pypy/annotation/test/test_annrpython.py
   pypy/branch/py12/pypy/config/pypyoption.py
   pypy/branch/py12/pypy/config/translationoption.py
   pypy/branch/py12/pypy/conftest.py
   pypy/branch/py12/pypy/doc/project-ideas.txt
   pypy/branch/py12/pypy/interpreter/argument.py
   pypy/branch/py12/pypy/interpreter/baseobjspace.py
   pypy/branch/py12/pypy/interpreter/executioncontext.py
   pypy/branch/py12/pypy/interpreter/main.py
   pypy/branch/py12/pypy/interpreter/pycompiler.py
   pypy/branch/py12/pypy/interpreter/pyopcode.py
   pypy/branch/py12/pypy/interpreter/test/test_argument.py
   pypy/branch/py12/pypy/interpreter/test/test_typedef.py
   pypy/branch/py12/pypy/interpreter/typedef.py
   pypy/branch/py12/pypy/jit/backend/test/support.py
   pypy/branch/py12/pypy/jit/backend/x86/test/test_zrpy_gc.py
   pypy/branch/py12/pypy/jit/metainterp/support.py
   pypy/branch/py12/pypy/jit/metainterp/warmspot.py
   pypy/branch/py12/pypy/lib/identity_dict.py
   pypy/branch/py12/pypy/module/cpyext/include/   (props changed)
   pypy/branch/py12/pypy/module/cpyext/src/   (props changed)
   pypy/branch/py12/pypy/module/cpyext/test/   (props changed)
   pypy/branch/py12/pypy/module/imp/importing.py
   pypy/branch/py12/pypy/module/thread/ll_thread.py
   pypy/branch/py12/pypy/module/thread/test/test_ll_thread.py
   pypy/branch/py12/pypy/objspace/std/fake.py
   pypy/branch/py12/pypy/objspace/std/objspace.py
   pypy/branch/py12/pypy/objspace/std/test/test_setobject.py
   pypy/branch/py12/pypy/objspace/std/typeobject.py
   pypy/branch/py12/pypy/rlib/rarithmetic.py
   pypy/branch/py12/pypy/rlib/rstring.py
   pypy/branch/py12/pypy/rlib/rweakref.py
   pypy/branch/py12/pypy/rlib/test/test_rarithmetic.py
   pypy/branch/py12/pypy/rlib/test/test_rbigint.py
   pypy/branch/py12/pypy/rlib/test/test_rstring.py
   pypy/branch/py12/pypy/rpython/annlowlevel.py
   pypy/branch/py12/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/py12/pypy/rpython/lltypesystem/lltype.py
   pypy/branch/py12/pypy/rpython/lltypesystem/rdict.py
   pypy/branch/py12/pypy/rpython/lltypesystem/rffi.py
   pypy/branch/py12/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
   pypy/branch/py12/pypy/rpython/lltypesystem/test/test_lltype.py
   pypy/branch/py12/pypy/rpython/test/test_llinterp.py
   pypy/branch/py12/pypy/tool/fixeol
   pypy/branch/py12/pypy/translator/c/gcc/test/test_asmgcroot.py
   pypy/branch/py12/pypy/translator/c/gcc/trackgcroot.py
   pypy/branch/py12/pypy/translator/c/genc.py
   pypy/branch/py12/pypy/translator/c/node.py
   pypy/branch/py12/pypy/translator/c/src/commondefs.h
   pypy/branch/py12/pypy/translator/c/src/main.h
   pypy/branch/py12/pypy/translator/c/src/obmalloc.c
   pypy/branch/py12/pypy/translator/c/test/test_genc.py
   pypy/branch/py12/pypy/translator/c/test/test_newgc.py
   pypy/branch/py12/pypy/translator/c/test/test_standalone.py
   pypy/branch/py12/pypy/translator/driver.py
   pypy/branch/py12/pypy/translator/goal/ann_override.py
   pypy/branch/py12/pypy/translator/platform/__init__.py
   pypy/branch/py12/pypy/translator/platform/darwin.py
   pypy/branch/py12/pypy/translator/platform/linux.py
   pypy/branch/py12/pypy/translator/platform/posix.py
   pypy/branch/py12/pypy/translator/platform/windows.py
   pypy/branch/py12/pypy/translator/test/test_unsimplify.py
   pypy/branch/py12/pypy/translator/tool/cbuild.py
   pypy/branch/py12/pypy/translator/tool/test/test_cbuild.py
   pypy/branch/py12/pypy/translator/unsimplify.py
Log:
merge trunk 


Modified: pypy/branch/py12/lib-python/modified-2.5.2/distutils/command/build_ext.py
==============================================================================
--- pypy/branch/py12/lib-python/modified-2.5.2/distutils/command/build_ext.py	(original)
+++ pypy/branch/py12/lib-python/modified-2.5.2/distutils/command/build_ext.py	Sun May  2 18:05:10 2010
@@ -167,7 +167,7 @@
         # for Release and Debug builds.
         # also Python's library directory must be appended to library_dirs
         if os.name == 'nt':
-            self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
+            self.library_dirs.append(os.path.join(sys.pypy_prefix, 'pypy', '_interfaces'))
             if self.debug:
                 self.build_temp = os.path.join(self.build_temp, "Debug")
             else:
@@ -175,8 +175,8 @@
 
             # Append the source distribution include and library directories,
             # this allows distutils on windows to work in the source tree
-            self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
-            self.library_dirs.append(os.path.join(sys.exec_prefix, 'PCBuild'))
+            #self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
+            #self.library_dirs.append(os.path.join(sys.exec_prefix, 'PCBuild'))
 
         # OS/2 (EMX) doesn't support Debug vs Release builds, but has the
         # import libraries in its "Config" subdirectory
@@ -645,24 +645,12 @@
         shared extension.  On most platforms, this is just 'ext.libraries';
         on Windows and OS/2, we add the Python library (eg. python20.dll).
         """
-        # The python library is always needed on Windows.  For MSVC, this
-        # is redundant, since the library is mentioned in a pragma in
-        # pyconfig.h that MSVC groks.  The other Windows compilers all seem
-        # to need it mentioned explicitly, though, so that's what we do.
-        # Append '_d' to the python import library on debug builds.
+        # The python library is always needed on Windows.
         if sys.platform == "win32":
-            from distutils.msvccompiler import MSVCCompiler
-            if not isinstance(self.compiler, MSVCCompiler):
-                template = "python%d%d"
-                if self.debug:
-                    template = template + '_d'
-                pythonlib = (template %
-                       (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
-                # don't extend ext.libraries, it may be shared with other
-                # extensions, it is a reference to the original list
-                return ext.libraries + [pythonlib]
-            else:
-                return ext.libraries
+            pythonlib = 'libpypy-c.exe'
+            # don't extend ext.libraries, it may be shared with other
+            # extensions, it is a reference to the original list
+            return ext.libraries + [pythonlib]
         elif sys.platform == "os2emx":
             # EMX/GCC requires the python library explicitly, and I
             # believe VACPP does as well (though not confirmed) - AIM Apr01

Modified: pypy/branch/py12/lib-python/modified-2.5.2/distutils/msvccompiler.py
==============================================================================
--- pypy/branch/py12/lib-python/modified-2.5.2/distutils/msvccompiler.py	(original)
+++ pypy/branch/py12/lib-python/modified-2.5.2/distutils/msvccompiler.py	Sun May  2 18:05:10 2010
@@ -1,154 +1,162 @@
-"""distutils.msvccompiler
+"""distutils.msvc9compiler
 
 Contains MSVCCompiler, an implementation of the abstract CCompiler class
-for the Microsoft Visual Studio.
+for the Microsoft Visual Studio 2008.
+
+The module is compatible with VS 2005 and VS 2008. You can find legacy support
+for older versions of VS in distutils.msvccompiler.
 """
 
 # Written by Perry Stoll
 # hacked by Robin Becker and Thomas Heller to do a better job of
 #   finding DevStudio (through the registry)
+# ported to VS2005 and VS 2008 by Christian Heimes
 
-# This module should be kept compatible with Python 2.1.
-
-__revision__ = "$Id: msvccompiler.py 54645 2007-04-01 18:29:47Z neal.norwitz $"
+__revision__ = "$Id: msvc9compiler.py 78713 2010-03-06 02:17:28Z tarek.ziade $"
 
-import sys, os, string
-from distutils.errors import \
-     DistutilsExecError, DistutilsPlatformError, \
-     CompileError, LibError, LinkError
-from distutils.ccompiler import \
-     CCompiler, gen_preprocess_options, gen_lib_options
+import os
+import subprocess
+import sys
+import re
+
+from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
+                              CompileError, LibError, LinkError)
+from distutils.ccompiler import CCompiler, gen_lib_options
 from distutils import log
+from distutils.util import get_platform
 
-_can_read_reg = 0
-try:
-    import _winreg
-
-    _can_read_reg = 1
-    hkey_mod = _winreg
-
-    RegOpenKeyEx = _winreg.OpenKeyEx
-    RegEnumKey = _winreg.EnumKey
-    RegEnumValue = _winreg.EnumValue
-    RegError = _winreg.error
+import _winreg
 
-except ImportError:
-    try:
-        import win32api
-        import win32con
-        _can_read_reg = 1
-        hkey_mod = win32con
-
-        RegOpenKeyEx = win32api.RegOpenKeyEx
-        RegEnumKey = win32api.RegEnumKey
-        RegEnumValue = win32api.RegEnumValue
-        RegError = win32api.error
-
-    except ImportError:
-        log.info("Warning: Can't read registry to find the "
-                 "necessary compiler setting\n"
-                 "Make sure that Python modules _winreg, "
-                 "win32api or win32con are installed.")
-        pass
-
-if _can_read_reg:
-    HKEYS = (hkey_mod.HKEY_USERS,
-             hkey_mod.HKEY_CURRENT_USER,
-             hkey_mod.HKEY_LOCAL_MACHINE,
-             hkey_mod.HKEY_CLASSES_ROOT)
+RegOpenKeyEx = _winreg.OpenKeyEx
+RegEnumKey = _winreg.EnumKey
+RegEnumValue = _winreg.EnumValue
+RegError = _winreg.error
+
+HKEYS = (_winreg.HKEY_USERS,
+         _winreg.HKEY_CURRENT_USER,
+         _winreg.HKEY_LOCAL_MACHINE,
+         _winreg.HKEY_CLASSES_ROOT)
+
+VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
+VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f"
+WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
+NET_BASE = r"Software\Microsoft\.NETFramework"
+
+# A map keyed by get_platform() return values to values accepted by
+# 'vcvarsall.bat'.  Note a cross-compile may combine these (eg, 'x86_amd64' is
+# the param to cross-compile on x86 targetting amd64.)
+PLAT_TO_VCVARS = {
+    'win32' : 'x86',
+    'win-amd64' : 'amd64',
+    'win-ia64' : 'ia64',
+}
 
-def read_keys(base, key):
-    """Return list of registry keys."""
+class Reg:
+    """Helper class to read values from the registry
+    """
 
-    try:
-        handle = RegOpenKeyEx(base, key)
-    except RegError:
-        return None
-    L = []
-    i = 0
-    while 1:
+    def get_value(cls, path, key):
+        for base in HKEYS:
+            d = cls.read_values(base, path)
+            if d and key in d:
+                return d[key]
+        raise KeyError(key)
+    get_value = classmethod(get_value)
+
+    def read_keys(cls, base, key):
+        """Return list of registry keys."""
         try:
-            k = RegEnumKey(handle, i)
+            handle = RegOpenKeyEx(base, key)
         except RegError:
-            break
-        L.append(k)
-        i = i + 1
-    return L
+            return None
+        L = []
+        i = 0
+        while True:
+            try:
+                k = RegEnumKey(handle, i)
+            except RegError:
+                break
+            L.append(k)
+            i += 1
+        return L
+    read_keys = classmethod(read_keys)
 
-def read_values(base, key):
-    """Return dict of registry keys and values.
+    def read_values(cls, base, key):
+        """Return dict of registry keys and values.
 
-    All names are converted to lowercase.
-    """
-    try:
-        handle = RegOpenKeyEx(base, key)
-    except RegError:
-        return None
-    d = {}
-    i = 0
-    while 1:
+        All names are converted to lowercase.
+        """
         try:
-            name, value, type = RegEnumValue(handle, i)
+            handle = RegOpenKeyEx(base, key)
         except RegError:
-            break
-        name = name.lower()
-        d[convert_mbcs(name)] = convert_mbcs(value)
-        i = i + 1
-    return d
-
-def convert_mbcs(s):
-    enc = getattr(s, "encode", None)
-    if enc is not None:
-        try:
-            s = enc("mbcs")
-        except UnicodeError:
-            pass
-    return s
+            return None
+        d = {}
+        i = 0
+        while True:
+            try:
+                name, value, type = RegEnumValue(handle, i)
+            except RegError:
+                break
+            name = name.lower()
+            d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
+            i += 1
+        return d
+    read_values = classmethod(read_values)
+
+    def convert_mbcs(s):
+        dec = getattr(s, "decode", None)
+        if dec is not None:
+            try:
+                s = dec("mbcs")
+            except UnicodeError:
+                pass
+        return s
+    convert_mbcs = staticmethod(convert_mbcs)
 
 class MacroExpander:
 
     def __init__(self, version):
         self.macros = {}
+        self.vsbase = VS_BASE % version
         self.load_macros(version)
 
     def set_macro(self, macro, path, key):
-        for base in HKEYS:
-            d = read_values(base, path)
-            if d:
-                self.macros["$(%s)" % macro] = d[key]
-                break
+        self.macros["$(%s)" % macro] = Reg.get_value(path, key)
 
     def load_macros(self, version):
-        vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
-        self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
-        self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
-        net = r"Software\Microsoft\.NETFramework"
-        self.set_macro("FrameworkDir", net, "installroot")
+        self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir")
+        self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir")
+        self.set_macro("FrameworkDir", NET_BASE, "installroot")
         try:
-            if version > 7.0:
-                self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
+            if version >= 8.0:
+                self.set_macro("FrameworkSDKDir", NET_BASE,
+                               "sdkinstallrootv2.0")
             else:
-                self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
-        except KeyError, exc: #
-            raise DistutilsPlatformError, \
-                  ("""Python was built with Visual Studio 2003;
+                raise KeyError("sdkinstallrootv2.0")
+        except KeyError:
+            raise DistutilsPlatformError(
+            """Python was built with Visual Studio 2008;
 extensions must be built with a compiler than can generate compatible binaries.
-Visual Studio 2003 was not found on this system. If you have Cygwin installed,
+Visual Studio 2008 was not found on this system. If you have Cygwin installed,
 you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
 
-        p = r"Software\Microsoft\NET Framework Setup\Product"
-        for base in HKEYS:
-            try:
-                h = RegOpenKeyEx(base, p)
-            except RegError:
-                continue
-            key = RegEnumKey(h, 0)
-            d = read_values(base, r"%s\%s" % (p, key))
-            self.macros["$(FrameworkVersion)"] = d["version"]
+        if version >= 9.0:
+            self.set_macro("FrameworkVersion", self.vsbase, "clr version")
+            self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder")
+        else:
+            p = r"Software\Microsoft\NET Framework Setup\Product"
+            for base in HKEYS:
+                try:
+                    h = RegOpenKeyEx(base, p)
+                except RegError:
+                    continue
+                key = RegEnumKey(h, 0)
+                d = Reg.get_value(base, r"%s\%s" % (p, key))
+                self.macros["$(FrameworkVersion)"] = d["version"]
 
     def sub(self, s):
         for k, v in self.macros.items():
-            s = string.replace(s, k, v)
+            s = s.replace(k, v)
         return s
 
 def get_build_version():
@@ -157,35 +165,7 @@
     For Python 2.3 and up, the version number is included in
     sys.version.  For earlier versions, assume the compiler is MSVC 6.
     """
-
-    prefix = "MSC v."
-    i = string.find(sys.version, prefix)
-    if i == -1:
-        return 6
-    i = i + len(prefix)
-    s, rest = sys.version[i:].split(" ", 1)
-    majorVersion = int(s[:-2]) - 6
-    minorVersion = int(s[2:3]) / 10.0
-    # I don't think paths are affected by minor version in version 6
-    if majorVersion == 6:
-        minorVersion = 0
-    if majorVersion >= 6:
-        return majorVersion + minorVersion
-    # else we don't know what version of the compiler this is
-    return None
-
-def get_build_architecture():
-    """Return the processor architecture.
-
-    Possible results are "Intel", "Itanium", or "AMD64".
-    """
-
-    prefix = " bit ("
-    i = string.find(sys.version, prefix)
-    if i == -1:
-        return "Intel"
-    j = string.find(sys.version, ")", i)
-    return sys.version[i+len(prefix):j]
+    return 8.0
 
 def normalize_and_reduce_paths(paths):
     """Return a list of normalized paths with duplicates removed.
@@ -201,8 +181,104 @@
             reduced_paths.append(np)
     return reduced_paths
 
+def removeDuplicates(variable):
+    """Remove duplicate values of an environment variable.
+    """
+    oldList = variable.split(os.pathsep)
+    newList = []
+    for i in oldList:
+        if i not in newList:
+            newList.append(i)
+    newVariable = os.pathsep.join(newList)
+    return newVariable
+
+def find_vcvarsall(version):
+    """Find the vcvarsall.bat file
+
+    At first it tries to find the productdir of VS 2008 in the registry. If
+    that fails it falls back to the VS90COMNTOOLS env var.
+    """
+    vsbase = VS_BASE % version
+    try:
+        productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
+                                   "productdir")
+    except KeyError:
+        productdir = None
+
+    # trying Express edition
+    if productdir is None:
+        vsbase = VSEXPRESS_BASE % version
+        try:
+            productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
+                                       "productdir")
+        except KeyError:
+            productdir = None
+            log.debug("Unable to find productdir in registry")
+
+    if not productdir or not os.path.isdir(productdir):
+        toolskey = "VS%0.f0COMNTOOLS" % version
+        toolsdir = os.environ.get(toolskey, None)
+
+        if toolsdir and os.path.isdir(toolsdir):
+            productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
+            productdir = os.path.abspath(productdir)
+            if not os.path.isdir(productdir):
+                log.debug("%s is not a valid directory" % productdir)
+                return None
+        else:
+            log.debug("Env var %s is not set or invalid" % toolskey)
+    if not productdir:
+        log.debug("No productdir found")
+        return None
+    vcvarsall = os.path.join(productdir, "vcvarsall.bat")
+    if os.path.isfile(vcvarsall):
+        return vcvarsall
+    log.debug("Unable to find vcvarsall.bat")
+    return None
+
+def query_vcvarsall(version, arch="x86"):
+    """Launch vcvarsall.bat and read the settings from its environment
+    """
+    vcvarsall = find_vcvarsall(version)
+    interesting = set(("include", "lib", "libpath", "path"))
+    result = {}
+
+    if vcvarsall is None:
+        raise DistutilsPlatformError("Unable to find vcvarsall.bat")
+    log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
+    popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+
+    stdout, stderr = popen.communicate()
+    if popen.wait() != 0:
+        raise DistutilsPlatformError(stderr.decode("mbcs"))
+
+    stdout = stdout.decode("mbcs")
+    for line in stdout.split("\n"):
+        line = Reg.convert_mbcs(line)
+        if '=' not in line:
+            continue
+        line = line.strip()
+        key, value = line.split('=', 1)
+        key = key.lower()
+        if key in interesting:
+            if value.endswith(os.pathsep):
+                value = value[:-1]
+            result[key] = removeDuplicates(value)
+
+    if len(result) != len(interesting):
+        raise ValueError(str(list(result.keys())))
+
+    return result
+
+# More globals
+VERSION = get_build_version()
+if VERSION < 8.0:
+    raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
+# MACROS = MacroExpander(VERSION)
 
-class MSVCCompiler (CCompiler) :
+class MSVCCompiler(CCompiler) :
     """Concrete class that implements an interface to Microsoft Visual C++,
        as defined by the CCompiler abstract class."""
 
@@ -232,27 +308,29 @@
     static_lib_format = shared_lib_format = '%s%s'
     exe_extension = '.exe'
 
-    def __init__ (self, verbose=0, dry_run=0, force=0):
+    def __init__(self, verbose=0, dry_run=0, force=0):
         CCompiler.__init__ (self, verbose, dry_run, force)
-        self.__version = get_build_version()
-        self.__arch = get_build_architecture()
-        if self.__arch == "Intel":
-            # x86
-            if self.__version >= 7:
-                self.__root = r"Software\Microsoft\VisualStudio"
-                self.__macros = MacroExpander(self.__version)
-            else:
-                self.__root = r"Software\Microsoft\Devstudio"
-            self.__product = "Visual Studio version %s" % self.__version
-        else:
-            # Win64. Assume this was built with the platform SDK
-            self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
-
+        self.__version = VERSION
+        self.__root = r"Software\Microsoft\VisualStudio"
+        # self.__macros = MACROS
+        self.__paths = []
+        # target platform (.plat_name is consistent with 'bdist')
+        self.plat_name = None
+        self.__arch = None # deprecated name
         self.initialized = False
 
-    def initialize(self):
-        self.__paths = []
-        if os.environ.has_key("DISTUTILS_USE_SDK") and os.environ.has_key("MSSdk") and self.find_exe("cl.exe"):
+    def initialize(self, plat_name=None):
+        # multi-init means we would need to check platform same each time...
+        assert not self.initialized, "don't init multiple times"
+        if plat_name is None:
+            plat_name = get_platform()
+        # sanity check for platforms to prevent obscure errors later.
+        ok_plats = 'win32', 'win-amd64', 'win-ia64'
+        if plat_name not in ok_plats:
+            raise DistutilsPlatformError("--plat-name must be one of %s" %
+                                         (ok_plats,))
+
+        if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
             # Assume that the SDK set up everything alright; don't try to be
             # smarter
             self.cc = "cl.exe"
@@ -261,36 +339,54 @@
             self.rc = "rc.exe"
             self.mc = "mc.exe"
         else:
-            self.__paths = self.get_msvc_paths("path")
+            # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
+            # to cross compile, you use 'x86_amd64'.
+            # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
+            # compile use 'x86' (ie, it runs the x86 compiler directly)
+            # No idea how itanium handles this, if at all.
+            if plat_name == get_platform() or plat_name == 'win32':
+                # native build or cross-compile to win32
+                plat_spec = PLAT_TO_VCVARS[plat_name]
+            else:
+                # cross compile from win32 -> some 64bit
+                plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \
+                            PLAT_TO_VCVARS[plat_name]
+
+            vc_env = query_vcvarsall(VERSION, plat_spec)
+
+            # take care to only use strings in the environment.
+            self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep)
+            os.environ['lib'] = vc_env['lib'].encode('mbcs')
+            os.environ['include'] = vc_env['include'].encode('mbcs')
 
-            if len (self.__paths) == 0:
-                raise DistutilsPlatformError, \
-                      ("Python was built with %s, "
+            if len(self.__paths) == 0:
+                raise DistutilsPlatformError("Python was built with %s, "
                        "and extensions need to be built with the same "
-                       "version of the compiler, but it isn't installed." % self.__product)
+                       "version of the compiler, but it isn't installed."
+                       % self.__product)
 
             self.cc = self.find_exe("cl.exe")
             self.linker = self.find_exe("link.exe")
             self.lib = self.find_exe("lib.exe")
             self.rc = self.find_exe("rc.exe")   # resource compiler
             self.mc = self.find_exe("mc.exe")   # message compiler
-            self.set_path_env_var('lib')
-            self.set_path_env_var('include')
+            #self.set_path_env_var('lib')
+            #self.set_path_env_var('include')
 
         # extend the MSVC path with the current path
         try:
-            for p in string.split(os.environ['path'], ';'):
+            for p in os.environ['path'].split(';'):
                 self.__paths.append(p)
         except KeyError:
             pass
         self.__paths = normalize_and_reduce_paths(self.__paths)
-        os.environ['path'] = string.join(self.__paths, ';')
+        os.environ['path'] = ";".join(self.__paths)
 
         self.preprocess_options = None
-        if self.__arch == "Intel":
-            self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
+        if self.__arch == "x86":
+            self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3',
                                      '/DNDEBUG']
-            self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
+            self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3',
                                           '/Z7', '/D_DEBUG']
         else:
             # Win64
@@ -304,20 +400,16 @@
             self.ldflags_shared_debug = [
                 '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
                 ]
-        else:
-            self.ldflags_shared_debug = [
-                '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
-                ]
         self.ldflags_static = [ '/nologo']
 
         self.initialized = True
 
     # -- Worker methods ------------------------------------------------
 
-    def object_filenames (self,
-                          source_filenames,
-                          strip_dir=0,
-                          output_dir=''):
+    def object_filenames(self,
+                         source_filenames,
+                         strip_dir=0,
+                         output_dir=''):
         # Copied from ccompiler.py, extended to return .res as 'object'-file
         # for .rc input file
         if output_dir is None: output_dir = ''
@@ -344,17 +436,16 @@
                                                 base + self.obj_extension))
         return obj_names
 
-    # object_filenames ()
-
 
     def compile(self, sources,
                 output_dir=None, macros=None, include_dirs=None, debug=0,
                 extra_preargs=None, extra_postargs=None, depends=None):
 
-        if not self.initialized: self.initialize()
-        macros, objects, extra_postargs, pp_opts, build = \
-                self._setup_compile(output_dir, macros, include_dirs, sources,
-                                    depends, extra_postargs)
+        if not self.initialized:
+            self.initialize()
+        compile_info = self._setup_compile(output_dir, macros, include_dirs,
+                                           sources, depends, extra_postargs)
+        macros, objects, extra_postargs, pp_opts, build = compile_info
 
         compile_opts = extra_preargs or []
         compile_opts.append ('/c')
@@ -383,13 +474,12 @@
                 input_opt = src
                 output_opt = "/fo" + obj
                 try:
-                    self.spawn ([self.rc] + pp_opts +
-                                [output_opt] + [input_opt])
+                    self.spawn([self.rc] + pp_opts +
+                               [output_opt] + [input_opt])
                 except DistutilsExecError, msg:
-                    raise CompileError, msg
+                    raise CompileError(msg)
                 continue
             elif ext in self._mc_extensions:
-
                 # Compile .MC to .RC file to .RES file.
                 #   * '-h dir' specifies the directory for the
                 #     generated include file
@@ -401,99 +491,95 @@
                 # we use the source-directory for the include file and
                 # the build directory for the RC file and message
                 # resources. This works at least for win32all.
-
-                h_dir = os.path.dirname (src)
-                rc_dir = os.path.dirname (obj)
+                h_dir = os.path.dirname(src)
+                rc_dir = os.path.dirname(obj)
                 try:
                     # first compile .MC to .RC and .H file
-                    self.spawn ([self.mc] +
-                                ['-h', h_dir, '-r', rc_dir] + [src])
+                    self.spawn([self.mc] +
+                               ['-h', h_dir, '-r', rc_dir] + [src])
                     base, _ = os.path.splitext (os.path.basename (src))
                     rc_file = os.path.join (rc_dir, base + '.rc')
                     # then compile .RC to .RES file
-                    self.spawn ([self.rc] +
-                                ["/fo" + obj] + [rc_file])
+                    self.spawn([self.rc] +
+                               ["/fo" + obj] + [rc_file])
 
                 except DistutilsExecError, msg:
-                    raise CompileError, msg
+                    raise CompileError(msg)
                 continue
             else:
                 # how to handle this file?
-                raise CompileError (
-                    "Don't know how to compile %s to %s" % \
-                    (src, obj))
+                raise CompileError("Don't know how to compile %s to %s"
+                                   % (src, obj))
 
             output_opt = "/Fo" + obj
             try:
-                self.spawn ([self.cc] + compile_opts + pp_opts +
-                            [input_opt, output_opt] +
-                            extra_postargs)
+                self.spawn([self.cc] + compile_opts + pp_opts +
+                           [input_opt, output_opt] +
+                           extra_postargs)
             except DistutilsExecError, msg:
-                raise CompileError, msg
+                raise CompileError(msg)
 
         return objects
 
-    # compile ()
-
 
-    def create_static_lib (self,
-                           objects,
-                           output_libname,
-                           output_dir=None,
-                           debug=0,
-                           target_lang=None):
-
-        if not self.initialized: self.initialize()
-        (objects, output_dir) = self._fix_object_args (objects, output_dir)
-        output_filename = \
-            self.library_filename (output_libname, output_dir=output_dir)
+    def create_static_lib(self,
+                          objects,
+                          output_libname,
+                          output_dir=None,
+                          debug=0,
+                          target_lang=None):
+
+        if not self.initialized:
+            self.initialize()
+        (objects, output_dir) = self._fix_object_args(objects, output_dir)
+        output_filename = self.library_filename(output_libname,
+                                                output_dir=output_dir)
 
-        if self._need_link (objects, output_filename):
+        if self._need_link(objects, output_filename):
             lib_args = objects + ['/OUT:' + output_filename]
             if debug:
-                pass                    # XXX what goes here?
+                pass # XXX what goes here?
             try:
-                self.spawn ([self.lib] + lib_args)
+                self.spawn([self.lib] + lib_args)
             except DistutilsExecError, msg:
-                raise LibError, msg
-
+                raise LibError(msg)
         else:
             log.debug("skipping %s (up-to-date)", output_filename)
 
-    # create_static_lib ()
 
-    def link (self,
-              target_desc,
-              objects,
-              output_filename,
-              output_dir=None,
-              libraries=None,
-              library_dirs=None,
-              runtime_library_dirs=None,
-              export_symbols=None,
-              debug=0,
-              extra_preargs=None,
-              extra_postargs=None,
-              build_temp=None,
-              target_lang=None):
-
-        if not self.initialized: self.initialize()
-        (objects, output_dir) = self._fix_object_args (objects, output_dir)
-        (libraries, library_dirs, runtime_library_dirs) = \
-            self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
+    def link(self,
+             target_desc,
+             objects,
+             output_filename,
+             output_dir=None,
+             libraries=None,
+             library_dirs=None,
+             runtime_library_dirs=None,
+             export_symbols=None,
+             debug=0,
+             extra_preargs=None,
+             extra_postargs=None,
+             build_temp=None,
+             target_lang=None):
+
+        if not self.initialized:
+            self.initialize()
+        (objects, output_dir) = self._fix_object_args(objects, output_dir)
+        fixed_args = self._fix_lib_args(libraries, library_dirs,
+                                        runtime_library_dirs)
+        (libraries, library_dirs, runtime_library_dirs) = fixed_args
 
         if runtime_library_dirs:
             self.warn ("I don't know what to do with 'runtime_library_dirs': "
                        + str (runtime_library_dirs))
 
-        lib_opts = gen_lib_options (self,
-                                    library_dirs, runtime_library_dirs,
-                                    libraries)
+        lib_opts = gen_lib_options(self,
+                                   library_dirs, runtime_library_dirs,
+                                   libraries)
         if output_dir is not None:
-            output_filename = os.path.join (output_dir, output_filename)
-
-        if self._need_link (objects, output_filename):
+            output_filename = os.path.join(output_dir, output_filename)
 
+        if self._need_link(objects, output_filename):
             if target_desc == CCompiler.EXECUTABLE:
                 if debug:
                     ldflags = self.ldflags_shared_debug[1:]
@@ -517,47 +603,99 @@
             # needed! Make sure they are generated in the temporary build
             # directory. Since they have different names for debug and release
             # builds, they can go into the same directory.
+            build_temp = os.path.dirname(objects[0])
             if export_symbols is not None:
                 (dll_name, dll_ext) = os.path.splitext(
                     os.path.basename(output_filename))
                 implib_file = os.path.join(
-                    os.path.dirname(objects[0]),
+                    build_temp,
                     self.library_filename(dll_name))
                 ld_args.append ('/IMPLIB:' + implib_file)
 
+            # Embedded manifests are recommended - see MSDN article titled
+            # "How to: Embed a Manifest Inside a C/C++ Application"
+            # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
+            # Ask the linker to generate the manifest in the temp dir, so
+            # we can embed it later.
+            temp_manifest = os.path.join(
+                    build_temp,
+                    os.path.basename(output_filename) + ".manifest")
+            ld_args.append('/MANIFESTFILE:' + temp_manifest)
+
             if extra_preargs:
                 ld_args[:0] = extra_preargs
             if extra_postargs:
                 ld_args.extend(extra_postargs)
 
-            self.mkpath (os.path.dirname (output_filename))
+            self.mkpath(os.path.dirname(output_filename))
             try:
-                self.spawn ([self.linker] + ld_args)
+                self.spawn([self.linker] + ld_args)
             except DistutilsExecError, msg:
-                raise LinkError, msg
+                raise LinkError(msg)
 
+            # embed the manifest
+            # XXX - this is somewhat fragile - if mt.exe fails, distutils
+            # will still consider the DLL up-to-date, but it will not have a
+            # manifest.  Maybe we should link to a temp file?  OTOH, that
+            # implies a build environment error that shouldn't go undetected.
+            if target_desc == CCompiler.EXECUTABLE:
+                mfid = 1
+            else:
+                mfid = 2
+                self._remove_visual_c_ref(temp_manifest)
+            out_arg = '-outputresource:%s;%s' % (output_filename, mfid)
+            try:
+                self.spawn(['mt.exe', '-nologo', '-manifest',
+                            temp_manifest, out_arg])
+            except DistutilsExecError, msg:
+                raise LinkError(msg)
         else:
             log.debug("skipping %s (up-to-date)", output_filename)
 
-    # link ()
-
+    def _remove_visual_c_ref(self, manifest_file):
+        try:
+            # Remove references to the Visual C runtime, so they will
+            # fall through to the Visual C dependency of Python.exe.
+            # This way, when installed for a restricted user (e.g.
+            # runtimes are not in WinSxS folder, but in Python's own
+            # folder), the runtimes do not need to be in every folder
+            # with .pyd's.
+            manifest_f = open(manifest_file)
+            try:
+                manifest_buf = manifest_f.read()
+            finally:
+                manifest_f.close()
+            pattern = re.compile(
+                r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
+                r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
+                re.DOTALL)
+            manifest_buf = re.sub(pattern, "", manifest_buf)
+            pattern = "<dependentAssembly>\s*</dependentAssembly>"
+            manifest_buf = re.sub(pattern, "", manifest_buf)
+            manifest_f = open(manifest_file, 'w')
+            try:
+                manifest_f.write(manifest_buf)
+            finally:
+                manifest_f.close()
+        except IOError:
+            pass
 
     # -- Miscellaneous methods -----------------------------------------
     # These are all used by the 'gen_lib_options() function, in
     # ccompiler.py.
 
-    def library_dir_option (self, dir):
+    def library_dir_option(self, dir):
         return "/LIBPATH:" + dir
 
-    def runtime_library_dir_option (self, dir):
-        raise DistutilsPlatformError, \
-              "don't know how to set runtime library search path for MSVC++"
+    def runtime_library_dir_option(self, dir):
+        raise DistutilsPlatformError(
+              "don't know how to set runtime library search path for MSVC++")
 
-    def library_option (self, lib):
-        return self.library_filename (lib)
+    def library_option(self, lib):
+        return self.library_filename(lib)
 
 
-    def find_library_file (self, dirs, lib, debug=0):
+    def find_library_file(self, dirs, lib, debug=0):
         # Prefer a debugging library if found (and requested), but deal
         # with it if we don't have one.
         if debug:
@@ -573,8 +711,6 @@
             # Oops, didn't find it in *any* of 'dirs'
             return None
 
-    # find_library_file ()
-
     # Helper methods for using the MSVC registry settings
 
     def find_exe(self, exe):
@@ -586,67 +722,15 @@
         absolute path that is known to exist.  If none of them work, just
         return the original program name, 'exe'.
         """
-
         for p in self.__paths:
             fn = os.path.join(os.path.abspath(p), exe)
             if os.path.isfile(fn):
                 return fn
 
         # didn't find it; try existing path
-        for p in string.split(os.environ['Path'],';'):
+        for p in os.environ['Path'].split(';'):
             fn = os.path.join(os.path.abspath(p),exe)
             if os.path.isfile(fn):
                 return fn
 
         return exe
-
-    def get_msvc_paths(self, path, platform='x86'):
-        """Get a list of devstudio directories (include, lib or path).
-
-        Return a list of strings.  The list will be empty if unable to
-        access the registry or appropriate registry keys not found.
-        """
-
-        if not _can_read_reg:
-            return []
-
-        path = path + " dirs"
-        if self.__version >= 7:
-            key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
-                   % (self.__root, self.__version))
-        else:
-            key = (r"%s\6.0\Build System\Components\Platforms"
-                   r"\Win32 (%s)\Directories" % (self.__root, platform))
-
-        for base in HKEYS:
-            d = read_values(base, key)
-            if d:
-                if self.__version >= 7:
-                    return string.split(self.__macros.sub(d[path]), ";")
-                else:
-                    return string.split(d[path], ";")
-        # MSVC 6 seems to create the registry entries we need only when
-        # the GUI is run.
-        if self.__version == 6:
-            for base in HKEYS:
-                if read_values(base, r"%s\6.0" % self.__root) is not None:
-                    self.warn("It seems you have Visual Studio 6 installed, "
-                        "but the expected registry settings are not present.\n"
-                        "You must at least run the Visual Studio GUI once "
-                        "so that these entries are created.")
-                    break
-        return []
-
-    def set_path_env_var(self, name):
-        """Set environment variable 'name' to an MSVC path type value.
-
-        This is equivalent to a SET command prior to execution of spawned
-        commands.
-        """
-
-        if name == "lib":
-            p = self.get_msvc_paths("library")
-        else:
-            p = self.get_msvc_paths(name)
-        if p:
-            os.environ[name] = string.join(p, ';')

Modified: pypy/branch/py12/lib-python/modified-2.5.2/distutils/spawn.py
==============================================================================
--- pypy/branch/py12/lib-python/modified-2.5.2/distutils/spawn.py	(original)
+++ pypy/branch/py12/lib-python/modified-2.5.2/distutils/spawn.py	Sun May  2 18:05:10 2010
@@ -69,7 +69,6 @@
                dry_run=0):
 
     executable = cmd[0]
-    cmd = _nt_quote_args(cmd)
     if search_path:
         # either we find one or it stays the same
         executable = find_executable(executable) or executable
@@ -77,7 +76,8 @@
     if not dry_run:
         # spawn for NT requires a full path to the .exe
         try:
-            rc = os.spawnv(os.P_WAIT, executable, cmd)
+            import subprocess
+            rc = subprocess.call(cmd)
         except OSError, exc:
             # this seems to happen when the command isn't found
             raise DistutilsExecError, \

Modified: pypy/branch/py12/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py
==============================================================================
--- pypy/branch/py12/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py	(original)
+++ pypy/branch/py12/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py	Sun May  2 18:05:10 2010
@@ -11,6 +11,12 @@
 python_build = False
 
 
+def get_python_inc(plat_specific=0, prefix=None):
+    from os.path import join as j
+    if plat_specific:
+        return j(sys.pypy_prefix, "pypy", "_interfaces")
+    return j(sys.pypy_prefix, 'pypy', 'module', 'cpyext', 'include')
+
 def get_python_version():
     """Return a string containing the major and minor Python version,
     leaving off the patchlevel.  Sample return values could be '1.5'
@@ -47,6 +53,7 @@
     """Initialize the module as appropriate for POSIX systems."""
     g = {}
     g['EXE'] = ""
+    g['SO'] = ".so"
 
     global _config_vars
     _config_vars = g
@@ -56,6 +63,7 @@
     """Initialize the module as appropriate for NT"""
     g = {}
     g['EXE'] = ".exe"
+    g['SO'] = ".pyd"
 
     global _config_vars
     _config_vars = g

Modified: pypy/branch/py12/pypy/annotation/annrpython.py
==============================================================================
--- pypy/branch/py12/pypy/annotation/annrpython.py	(original)
+++ pypy/branch/py12/pypy/annotation/annrpython.py	Sun May  2 18:05:10 2010
@@ -83,20 +83,23 @@
 
     #___ convenience high-level interface __________________
 
-    def build_types(self, function, input_arg_types, complete_now=True):
+    def build_types(self, function, input_arg_types, complete_now=True,
+                    main_entry_point=False):
         """Recursively build annotations about the specific entry point."""
         assert isinstance(function, types.FunctionType), "fix that!"
 
+        from pypy.annotation.policy import AnnotatorPolicy
+        policy = AnnotatorPolicy()
         # make input arguments and set their type
-        inputcells = [self.typeannotation(t) for t in input_arg_types]
+        args_s = [self.typeannotation(t) for t in input_arg_types]
 
-        desc = self.bookkeeper.getdesc(function)
-        desc.getcallfamily()   # record this implicit call (hint for back-ends)
-        flowgraph = desc.specialize(inputcells)
+        flowgraph, inputcells = self.get_call_parameters(function, args_s, policy)
         if not isinstance(flowgraph, FunctionGraph):
             assert isinstance(flowgraph, annmodel.SomeObject)
             return flowgraph
 
+        if main_entry_point:
+            self.translator.entry_point_graph = flowgraph
         return self.build_graph_types(flowgraph, inputcells, complete_now=complete_now)
 
     def get_call_parameters(self, function, args_s, policy):

Modified: pypy/branch/py12/pypy/annotation/description.py
==============================================================================
--- pypy/branch/py12/pypy/annotation/description.py	(original)
+++ pypy/branch/py12/pypy/annotation/description.py	Sun May  2 18:05:10 2010
@@ -209,8 +209,9 @@
         if len(self._cache) != 1:
             raise NoStandardGraph(self)
         [graph] = self._cache.values()
+        relax_sig_check = getattr(self.pyobj, "relax_sig_check", False)
         if (graph.signature != self.signature or
-            graph.defaults  != self.defaults):
+            graph.defaults  != self.defaults) and not relax_sig_check:
             raise NoStandardGraph(self)
         return graph
 

Modified: pypy/branch/py12/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/py12/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/py12/pypy/annotation/test/test_annrpython.py	Sun May  2 18:05:10 2010
@@ -3185,6 +3185,13 @@
         assert isinstance(s, annmodel.SomeList)
         assert s.listdef.listitem.resized
 
+    def test_varargs(self):
+        def f(*args):
+            return args[0] + 42
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int, int])
+        assert isinstance(s, annmodel.SomeInteger)
+
     def test_listitem_no_mutating(self):
         from pypy.rlib.debug import check_annotation
         called = []
@@ -3304,6 +3311,15 @@
         s = a.build_types(f, [int])
         assert s.knowntype is int
 
+    def test_relax(self):
+        def f(*args):
+            return args[0] + args[1]
+        f.relax_sig_check = True
+        def g(x):
+            return f(x, x - x)
+        a = self.RPythonAnnotator()
+        s = a.build_types(g, [int])
+        assert a.bookkeeper.getdesc(f).getuniquegraph()
 
 def g(n):
     return [0,1,2,n]

Modified: pypy/branch/py12/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/py12/pypy/config/pypyoption.py	(original)
+++ pypy/branch/py12/pypy/config/pypyoption.py	Sun May  2 18:05:10 2010
@@ -29,7 +29,8 @@
       "rctime" , "select", "zipimport", "_lsprof",
      "crypt", "signal", "_rawffi", "termios", "zlib",
      "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO",
-     "thread", "itertools", "pyexpat", "_ssl"]
+     "thread", "itertools", "pyexpat", "_ssl"] # "cpyext"] commented out until
+     # it stops adding _pyolifeline on W_Root
 ))
 
 working_oo_modules = default_modules.copy()
@@ -62,11 +63,14 @@
 
 
 module_dependencies = {}
-module_suggests = {    # the reason you want _rawffi is for ctypes, which
-                       # itself needs the interp-level struct module
-                       # because 'P' is missing from the app-level one
-                       '_rawffi': [("objspace.usemodules.struct", True)],
-                       }
+module_suggests = {
+    # the reason you want _rawffi is for ctypes, which
+    # itself needs the interp-level struct module
+    # because 'P' is missing from the app-level one
+    "_rawffi": [("objspace.usemodules.struct", True)],
+    "cpyext": [("translation.secondaryentrypoints", "cpyext"),
+               ("translation.shared", sys.platform == "win32")],
+    }
 
 module_import_dependencies = {
     # no _rawffi if importing pypy.rlib.libffi raises ImportError

Modified: pypy/branch/py12/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/py12/pypy/config/translationoption.py	(original)
+++ pypy/branch/py12/pypy/config/translationoption.py	Sun May  2 18:05:10 2010
@@ -42,6 +42,9 @@
                      },
                  cmdline="-b --backend"),
 
+    BoolOption("shared", "Build as a shared library",
+               default=False, cmdline="--shared"),
+
     BoolOption("log", "Include debug prints in the translation (PYPYLOG=...)",
                default=True, cmdline="--log"),
 
@@ -138,6 +141,9 @@
     ArbitraryOption("instrumentctl", "internal",
                default=None),
     StrOption("output", "Output file name", cmdline="--output"),
+    StrOption("secondaryentrypoints",
+            "Comma separated list of keys choosing secondary entrypoints",
+            cmdline="--entrypoints", default=""),
 
     BoolOption("dump_static_data_info", "Dump static data info",
                cmdline="--dump_static_data_info",

Modified: pypy/branch/py12/pypy/conftest.py
==============================================================================
--- pypy/branch/py12/pypy/conftest.py	(original)
+++ pypy/branch/py12/pypy/conftest.py	Sun May  2 18:05:10 2010
@@ -59,7 +59,7 @@
     try:
         return _SPACECACHE[key]
     except KeyError:
-        if option.runappdirect:
+        if getattr(option, 'runappdirect', None):
             if name not in (None, 'std'):
                 myname = getattr(sys, 'pypy_objspaceclass', '')
                 if not myname.lower().startswith(name):

Modified: pypy/branch/py12/pypy/doc/project-ideas.txt
==============================================================================
--- pypy/branch/py12/pypy/doc/project-ideas.txt	(original)
+++ pypy/branch/py12/pypy/doc/project-ideas.txt	Sun May  2 18:05:10 2010
@@ -21,22 +21,9 @@
 --------------------------------
 
 PyPy's Just-In-Time compiler relies on backends for actual code
-generation.  We have so far a 32-bit Intel backend, and a CLI one.  Open
-ideas are to write a backend for **Intel 64** (AMD64); or a backend for
-Java; or trying again to use LLVM-JIT (which I do not really recommend).
-
-CTypes
-------
-
-Support ctypes on more backends.  Right now ctypes is supported only
-when compiling PyPy to C, and there is a bit of unfinished work to
-support it on **Intel 64.**  A nice project would be to support it when
-compiling to .NET or the JVM. That's not too hard, the only thing needed
-is to port a small module that does the actual invocation of external
-libraries (a related project is to port this module to Jython or
-IronPython to get support for ctypes there, which is something that was
-tried but not finished as far as I know).
-
+generation.  We have so far a 32-bit Intel backend, and a CLI one. There is
+Summer of Code project for 64bit (x86_64) backend, but other options
+(ARM, llvm) remain open.
 
 .. _distribution:
 .. _persistence:

Modified: pypy/branch/py12/pypy/interpreter/argument.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/argument.py	(original)
+++ pypy/branch/py12/pypy/interpreter/argument.py	Sun May  2 18:05:10 2010
@@ -128,19 +128,6 @@
                 kwds_w[self.keywords[i]] = self.keywords_w[i]
         return self.arguments_w, kwds_w
 
-    def unpack_cpy(self, starting_at=0):
-        assert starting_at >= 0
-        space = self.space
-        args_w = self.arguments_w
-        w_kw = space.newdict()
-        if self.keywords:
-            for i in range(len(self.keywords)):
-                space.setitem(w_kw, space.wrap(self.keywords[i]), self.keywords_w[i])
-        if starting_at != 0:
-            args_w = args_w[starting_at:]
-        args_tuple = space.newtuple([space.wrap(args_w), w_kw])
-        return args_tuple
-
     def replace_arguments(self, args_w):
         "Return a new Arguments with a args_w as positional arguments."
         return Arguments(self.space, args_w, self.keywords, self.keywords_w)

Modified: pypy/branch/py12/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/py12/pypy/interpreter/baseobjspace.py	Sun May  2 18:05:10 2010
@@ -4,7 +4,6 @@
 from pypy.interpreter.executioncontext import UserDelAction, FrameTraceAction
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.argument import Arguments
-from pypy.interpreter.pycompiler import PythonAstCompiler
 from pypy.interpreter.miscutils import ThreadLocals
 from pypy.tool.cache import Cache
 from pypy.tool.uid import HUGEVAL_BYTES
@@ -579,6 +578,7 @@
         try:
             return self.default_compiler
         except AttributeError:
+            from pypy.interpreter.pycompiler import PythonAstCompiler
             compiler = PythonAstCompiler(self)
             self.default_compiler = compiler
             return compiler

Modified: pypy/branch/py12/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/executioncontext.py	(original)
+++ pypy/branch/py12/pypy/interpreter/executioncontext.py	Sun May  2 18:05:10 2010
@@ -50,8 +50,7 @@
 
     def enter(self, frame):
         if self.framestackdepth > self.space.sys.recursionlimit:
-            raise OperationError(self.space.w_RuntimeError,
-                                 self.space.wrap("maximum recursion depth exceeded"))
+            raise self.space.prebuilt_recursion_error
         self.framestackdepth += 1
         frame.f_backref = self.topframeref
         self.topframeref = jit.virtual_ref(frame)

Modified: pypy/branch/py12/pypy/interpreter/main.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/main.py	(original)
+++ pypy/branch/py12/pypy/interpreter/main.py	Sun May  2 18:05:10 2010
@@ -1,7 +1,7 @@
-from pypy.interpreter import module, eval
+import sys
+from pypy.interpreter import eval, module
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.pycode import PyCode
-import sys, types
+
 
 def ensure__main__(space):
     w_main = space.wrap('__main__')

Modified: pypy/branch/py12/pypy/interpreter/pycompiler.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/pycompiler.py	(original)
+++ pypy/branch/py12/pypy/interpreter/pycompiler.py	Sun May  2 18:05:10 2010
@@ -3,10 +3,13 @@
 Compiler instances are stored into 'space.getexecutioncontext().compiler'.
 """
 
-import sys
-from pypy.interpreter.astcompiler.consts import PyCF_DONT_IMPLY_DEDENT
+from pypy.interpreter import pycode
+from pypy.interpreter.pyparser import future, pyparse, error as parseerror
+from pypy.interpreter.astcompiler import (astbuilder, codegen, consts, misc,
+                                          optimize)
 from pypy.interpreter.error import OperationError
 
+
 class AbstractCompiler(object):
     """Abstract base class for a bytecode compiler."""
 
@@ -33,7 +36,7 @@
         # Hackish default implementation based on the stdlib 'codeop' module.
         # See comments over there.
         space = self.space
-        flags |= PyCF_DONT_IMPLY_DEDENT
+        flags |= consts.PyCF_DONT_IMPLY_DEDENT
         # Check for source consisting of only blank lines and comments
         if mode != "eval":
             in_comment = False
@@ -82,8 +85,7 @@
     def getcodeflags(self, code):
         """Return the __future__ compiler flags that were used to compile
         the given code object."""
-        from pypy.interpreter.pycode import PyCode
-        if isinstance(code, PyCode):
+        if isinstance(code, pycode.PyCode):
             return code.co_flags & self.compiler_flags
         else:
             return 0
@@ -98,62 +100,49 @@
          the whole source after having only added a new '\n')
     """
     def __init__(self, space, override_version=None):
-
-        from pypy.interpreter.pyparser.pyparse import PythonParser
-        from pypy.interpreter.pyparser import future
         PyCodeCompiler.__init__(self, space)
-        self.parser = PythonParser(space)
+        self.parser = pyparse.PythonParser(space)
         self.additional_rules = {}
         self.future_flags = future.futureFlags_2_5
         self.compiler_flags = self.future_flags.allowed_flags
 
     def compile_ast(self, node, filename, mode, flags):
-        from pypy.interpreter.pyparser.pyparse import CompileInfo
-        from pypy.interpreter.astcompiler.misc import parse_future
-        info = CompileInfo(filename, mode, flags, parse_future(node))
+        future_pos = misc.parse_future(node)
+        info = pyparse.CompileInfo(filename, mode, flags, future_pos)
         return self._compile_ast(node, info)
 
     def _compile_ast(self, node, info):
-        from pypy.interpreter.astcompiler import optimize
-        from pypy.interpreter.astcompiler.codegen import compile_ast
-        from pypy.interpreter.pyparser.error import SyntaxError
         space = self.space
         try:
             mod = optimize.optimize_ast(space, node, info)
-            code = compile_ast(space, mod, info)
-        except SyntaxError, e:
+            code = codegen.compile_ast(space, mod, info)
+        except parseerror.SyntaxError, e:
             raise OperationError(space.w_SyntaxError,
                                  e.wrap_info(space))
         return code
 
     def compile_to_ast(self, source, filename, mode, flags):
-        from pypy.interpreter.pyparser.pyparse import CompileInfo
-        info = CompileInfo(filename, mode, flags)
+        info = pyparse.CompileInfo(filename, mode, flags)
         return self._compile_to_ast(source, info)
 
     def _compile_to_ast(self, source, info):
-        from pypy.interpreter.pyparser.future import get_futures
-        from pypy.interpreter.pyparser.error import (SyntaxError,
-                                                     IndentationError)
-        from pypy.interpreter.astcompiler.astbuilder import ast_from_node
         space = self.space
         try:
-            f_flags, future_info = get_futures(self.future_flags, source)
+            f_flags, future_info = future.get_futures(self.future_flags, source)
             info.last_future_import = future_info
             info.flags |= f_flags
             parse_tree = self.parser.parse_source(source, info)
-            mod = ast_from_node(space, parse_tree, info)
-        except IndentationError, e:
+            mod = astbuilder.ast_from_node(space, parse_tree, info)
+        except parseerror.IndentationError, e:
             raise OperationError(space.w_IndentationError,
                                  e.wrap_info(space))
-        except SyntaxError, e:
+        except parseerror.SyntaxError, e:
             raise OperationError(space.w_SyntaxError,
                                  e.wrap_info(space))
         return mod
 
     def compile(self, source, filename, mode, flags, hidden_applevel=False):
-        from pypy.interpreter.pyparser.pyparse import CompileInfo
-        info = CompileInfo(filename, mode, flags,
-                           hidden_applevel=hidden_applevel)
+        info = pyparse.CompileInfo(filename, mode, flags,
+                                   hidden_applevel=hidden_applevel)
         mod = self._compile_to_ast(source, info)
         return self._compile_ast(mod, info)

Modified: pypy/branch/py12/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/py12/pypy/interpreter/pyopcode.py	Sun May  2 18:05:10 2010
@@ -886,8 +886,6 @@
 
     @jit.unroll_safe
     def call_function(self, oparg, w_star=None, w_starstar=None):
-        from pypy.interpreter.function import is_builtin_code
-
         n_arguments = oparg & 0xff
         n_keywords = (oparg>>8) & 0xff
         if n_keywords:
@@ -909,7 +907,7 @@
         args = self.argument_factory(arguments, keywords, keywords_w, w_star,
                                      w_starstar)
         w_function  = self.popvalue()
-        if self.is_being_profiled and is_builtin_code(w_function):
+        if self.is_being_profiled and function.is_builtin_code(w_function):
             w_result = self.space.call_args_and_c_profile(self, w_function,
                                                           args)
         else:
@@ -1014,7 +1012,7 @@
                                  (ofs, ord(c), name) )
 
     STOP_CODE = MISSING_OPCODE
-    
+
     def BUILD_MAP(self, itemcount, next_instr):
         if itemcount != 0:
             raise BytecodeCorruption

Modified: pypy/branch/py12/pypy/interpreter/test/test_argument.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/test/test_argument.py	(original)
+++ pypy/branch/py12/pypy/interpreter/test/test_argument.py	Sun May  2 18:05:10 2010
@@ -135,12 +135,6 @@
         assert args1.keywords is args.keywords
         assert args1.keywords_w is args.keywords_w
 
-    def test_unpack_cpy(self):
-        space = DummySpace()
-        args = Arguments(space, ["0"])
-        assert space.eq_w(args.unpack_cpy(), space.newtuple([space.newlist([space.wrap("0")]), space.newdict()]))
-        assert space.eq_w(args.unpack_cpy(1), space.newtuple([space.newlist(), space.newdict()]))
-
     def test_fixedunpacked(self):
         space = DummySpace()
         

Modified: pypy/branch/py12/pypy/interpreter/test/test_typedef.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/test/test_typedef.py	(original)
+++ pypy/branch/py12/pypy/interpreter/test/test_typedef.py	Sun May  2 18:05:10 2010
@@ -1,5 +1,6 @@
 from pypy.interpreter import typedef
 from pypy.tool.udir import udir
+from pypy.interpreter.baseobjspace import Wrappable
 
 # this test isn't so much to test that the objspace interface *works*
 # -- it's more to test that it's *there*
@@ -132,6 +133,18 @@
             assert len(set) <= 6, "%s has %d subclasses:\n%r" % (
                 cls, len(set), [subcls.__name__ for subcls in set])
 
+    def test_getsetproperty(self):
+        class W_SomeType(Wrappable):
+            pass
+        def fget(self, space, w_self):
+            assert self is prop
+        prop = typedef.GetSetProperty(fget, use_closure=True)
+        W_SomeType.typedef = typedef.TypeDef(
+            'some_type',
+            x=prop)
+        w_obj = self.space.wrap(W_SomeType())
+        assert self.space.getattr(w_obj, self.space.wrap('x')) is self.space.w_None
+
 
 class AppTestTypeDef:
 

Modified: pypy/branch/py12/pypy/interpreter/typedef.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/typedef.py	(original)
+++ pypy/branch/py12/pypy/interpreter/typedef.py	Sun May  2 18:05:10 2010
@@ -9,7 +9,7 @@
     DescrMismatch
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.tool.sourcetools import compile2, func_with_new_name
-from pypy.rlib.objectmodel import instantiate, compute_identity_hash
+from pypy.rlib.objectmodel import instantiate, compute_identity_hash, specialize
 from pypy.rlib.jit import hint
 
 class TypeDef:
@@ -301,44 +301,63 @@
 
 # ____________________________________________________________
 
-def make_descr_typecheck_wrapper(func, extraargs=(), cls=None):
+ at specialize.arg(0)
+def make_descr_typecheck_wrapper(tag, func, extraargs=(), cls=None,
+                                 use_closure=False):
     if func is None:
         return None
-    if cls is None:
+    return _make_descr_typecheck_wrapper(tag, func, extraargs, cls, use_closure)
+
+ at specialize.memo()
+def _make_descr_typecheck_wrapper(tag, func, extraargs, cls, use_closure):
+    # - if cls is None, the wrapped object is passed to the function
+    # - if cls is a class, an unwrapped instance is passed
+    # - if cls is a string, XXX unused?
+    if cls is None and use_closure:
         return func
     if hasattr(func, 'im_func'):
         assert func.im_class is cls
         func = func.im_func
-    
+
     miniglobals = {
          func.__name__: func,
         'OperationError': OperationError
         }
     if isinstance(cls, str):
+        assert 0, "unused?"
         #print "<CHECK", func.__module__ or '?', func.__name__
         assert cls.startswith('<'),"pythontype typecheck should begin with <"
         source = """
-        def descr_typecheck_%(name)s(space, w_obj, %(extra)s):
+        def descr_typecheck_%(name)s(closure, space, w_obj, %(extra)s):
             if not space.is_true(space.isinstance(w_obj, space.w_%(cls_name)s)):
                 # xxx improve msg
                 msg =  "descriptor is for '%(expected)s'"
                 raise OperationError(space.w_TypeError, space.wrap(msg))
-            return %(name)s(space, w_obj, %(extra)s)
+            return %(name)s(%(closure)s space, w_obj, %(extra)s)
         """
         cls_name = cls[1:]
         expected = repr(cls_name)
+    elif cls is None:
+        source = """
+        def descr_typecheck_%(name)s(closure, space, w_obj, %(extra)s):
+            return %(name)s(%(closure)s space, w_obj, %(extra)s)
+        """
     else:
         cls_name = cls.__name__
         assert issubclass(cls, Wrappable)
         source = """
-        def descr_typecheck_%(name)s(space, w_obj, %(extra)s):
+        def descr_typecheck_%(name)s(closure, space, w_obj, %(extra)s):
             obj = space.descr_self_interp_w(%(cls_name)s, w_obj)
-            return %(name)s(space, obj, %(extra)s)
+            return %(name)s(%(closure)s space, obj, %(extra)s)
         """
         miniglobals[cls_name] = cls
     
     name = func.__name__
     extra = ', '.join(extraargs)
+    if use_closure:
+        closure = "closure,"
+    else:
+        closure = ""
     source = py.code.Source(source % locals())
     exec source.compile() in miniglobals
     return miniglobals['descr_typecheck_%s' % func.__name__]
@@ -348,16 +367,17 @@
     raise OperationError(space.w_AttributeError,
                          space.wrap("generic property has no __objclass__"))
 
-def make_objclass_getter(func, cls, cache={}):
-    if hasattr(func, 'im_func'):
+ at specialize.arg(0)
+def make_objclass_getter(tag, func, cls):
+    if func and hasattr(func, 'im_func'):
         assert not cls or cls is func.im_class
         cls = func.im_class
+    return _make_objclass_getter(cls)
+
+ at specialize.memo()
+def _make_objclass_getter(cls):
     if not cls:
         return unknown_objclass_getter, cls
-    try:
-        return cache[cls]
-    except KeyError:
-        pass
     miniglobals = {}
     if isinstance(cls, str):
         assert cls.startswith('<'),"pythontype typecheck should begin with <"
@@ -372,16 +392,19 @@
         \n""" % (typeexpr,)
     exec compile2(source) in miniglobals
     res = miniglobals['objclass_getter'], cls
-    cache[cls] = res
     return res
 
 class GetSetProperty(Wrappable):
-    def __init__(self, fget, fset=None, fdel=None, doc=None, cls=None):
-        "NOT_RPYTHON: initialization-time only"
-        objclass_getter, cls = make_objclass_getter(fget, cls)
-        fget = make_descr_typecheck_wrapper(fget, cls=cls)
-        fset = make_descr_typecheck_wrapper(fset, ('w_value',), cls=cls)
-        fdel = make_descr_typecheck_wrapper(fdel, cls=cls)
+    @specialize.arg(7)
+    def __init__(self, fget, fset=None, fdel=None, doc=None,
+                 cls=None, use_closure=False, tag=None):
+        objclass_getter, cls = make_objclass_getter(tag, fget, cls)
+        fget = make_descr_typecheck_wrapper((tag, 0), fget,
+                                            cls=cls, use_closure=use_closure)
+        fset = make_descr_typecheck_wrapper((tag, 1), fset, ('w_value',),
+                                            cls=cls, use_closure=use_closure)
+        fdel = make_descr_typecheck_wrapper((tag, 2), fdel,
+                                            cls=cls, use_closure=use_closure)
         self.fget = fget
         self.fset = fset
         self.fdel = fdel
@@ -389,7 +412,8 @@
         self.reqcls = cls
         self.name = '<generic property>'
         self.objclass_getter = objclass_getter
-    
+        self.use_closure = use_closure
+
     def descr_property_get(space, property, w_obj, w_cls=None):
         """property.__get__(obj[, type]) -> value
         Read the value of the property of the given obj."""
@@ -400,7 +424,7 @@
             return space.wrap(property)
         else:
             try:
-                return property.fget(space, w_obj)
+                return property.fget(property, space, w_obj)
             except DescrMismatch, e:
                 return w_obj.descr_call_mismatch(space, '__getattribute__',\
                     property.reqcls, Arguments(space, [w_obj,
@@ -414,7 +438,7 @@
             raise OperationError(space.w_TypeError,
                                  space.wrap("readonly attribute"))
         try:
-            fset(space, w_obj, w_value)
+            fset(property, space, w_obj, w_value)
         except DescrMismatch, e:
             w_obj.descr_call_mismatch(space, '__setattr__',\
                 property.reqcls, Arguments(space, [w_obj,
@@ -428,7 +452,7 @@
             raise OperationError(space.w_AttributeError,
                                  space.wrap("cannot delete attribute"))
         try:
-            fdel(space, w_obj)
+            fdel(property, space, w_obj)
         except DescrMismatch, e:
             w_obj.descr_call_mismatch(space, '__delattr__',\
                 property.reqcls, Arguments(space, [w_obj,

Modified: pypy/branch/py12/pypy/jit/backend/test/support.py
==============================================================================
--- pypy/branch/py12/pypy/jit/backend/test/support.py	(original)
+++ pypy/branch/py12/pypy/jit/backend/test/support.py	Sun May  2 18:05:10 2010
@@ -2,7 +2,7 @@
 import sys
 from pypy.rlib.debug import debug_print
 from pypy.rlib.jit import OPTIMIZER_FULL
-from pypy.translator.translator import TranslationContext
+from pypy.translator.translator import TranslationContext, graphof
 
 class BaseCompiledMixin(object):
 
@@ -56,7 +56,8 @@
             """ % (arglist,))
         exec src.compile() in locals()
 
-        t.buildannotator().build_types(function, [int] * len(args))
+        t.buildannotator().build_types(function, [int] * len(args),
+                                       main_entry_point=True)
         t.buildrtyper(type_system=self.type_system).specialize()
         warmrunnerdesc = WarmRunnerDesc(t, translate_support_code=True,
                                         CPUClass=self.CPUClass,

Modified: pypy/branch/py12/pypy/jit/backend/x86/test/test_zrpy_gc.py
==============================================================================
--- pypy/branch/py12/pypy/jit/backend/x86/test/test_zrpy_gc.py	(original)
+++ pypy/branch/py12/pypy/jit/backend/x86/test/test_zrpy_gc.py	Sun May  2 18:05:10 2010
@@ -82,7 +82,7 @@
     for name, value in kwds.items():
         setattr(t.config.translation, name, value)
     ann = t.buildannotator(policy=annpolicy.StrictAnnotatorPolicy())
-    ann.build_types(f, [s_list_of_strings])
+    ann.build_types(f, [s_list_of_strings], main_entry_point=True)
     t.buildrtyper().specialize()
     if kwds['jit']:
         apply_jit(t, optimizer=OPTIMIZER_SIMPLE)

Modified: pypy/branch/py12/pypy/jit/metainterp/support.py
==============================================================================
--- pypy/branch/py12/pypy/jit/metainterp/support.py	(original)
+++ pypy/branch/py12/pypy/jit/metainterp/support.py	Sun May  2 18:05:10 2010
@@ -41,7 +41,7 @@
     annpolicy.allow_someobjects = False
     a = t.buildannotator(policy=annpolicy)
     argtypes = getargtypes(a, values)
-    a.build_types(func, argtypes)
+    a.build_types(func, argtypes, main_entry_point=True)
     rtyper = t.buildrtyper(type_system = type_system)
     rtyper.specialize()
     if inline:

Modified: pypy/branch/py12/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/py12/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/py12/pypy/jit/metainterp/warmspot.py	Sun May  2 18:05:10 2010
@@ -231,7 +231,7 @@
     def check_access_directly_sanity(self, graphs):
         from pypy.translator.backendopt.inline import collect_called_graphs
         jit_graphs = set(graphs)
-        for graph in collect_called_graphs(self.translator.graphs[0],
+        for graph in collect_called_graphs(self.translator.entry_point_graph,
                                            self.translator):
             if graph in jit_graphs:
                 continue

Modified: pypy/branch/py12/pypy/lib/identity_dict.py
==============================================================================
--- pypy/branch/py12/pypy/lib/identity_dict.py	(original)
+++ pypy/branch/py12/pypy/lib/identity_dict.py	Sun May  2 18:05:10 2010
@@ -30,6 +30,12 @@
     def __contains__(self, arg):
         return id(arg) in self._dict
 
+    def copy(self):
+        d = type(self)()
+        d.update(self.iteritems())
+        assert len(d) == len(self)
+        return d
+
 
 class IdentityDictPyPy(object, DictMixin):
     __slots__ = ["_dict"]
@@ -52,6 +58,11 @@
     def __contains__(self, arg):
         return arg in self._dict
 
+    def copy(self):
+        d = type(self)()
+        d.update(self.iteritems())
+        assert len(d) == len(self)
+        return d
 
 if idict is None:
     identity_dict = IdentityDictPurePython

Modified: pypy/branch/py12/pypy/module/imp/importing.py
==============================================================================
--- pypy/branch/py12/pypy/module/imp/importing.py	(original)
+++ pypy/branch/py12/pypy/module/imp/importing.py	Sun May  2 18:05:10 2010
@@ -25,6 +25,11 @@
 # PY_CODERESOURCE = 8
 IMP_HOOK = 9
 
+if sys.platform.startswith('win'):
+    so_extension = ".pyd"
+else:
+    so_extension = ".so"
+
 def find_modtype(space, filepart):
     """Check which kind of module to import for the given filepart,
     which is a path without extension.  Returns PY_SOURCE, PY_COMPILED or
@@ -40,16 +45,18 @@
     # look for a lone .pyc file.
     # The "imp" module does not respect this, and is allowed to find
     # lone .pyc files.
-    if not space.config.objspace.lonepycfiles:
-        return SEARCH_ERROR, None, None
-
     # check the .pyc file
-    if space.config.objspace.usepycfiles:
+    if space.config.objspace.usepycfiles and space.config.objspace.lonepycfiles:
         pycfile = filepart + ".pyc"
         if os.path.exists(pycfile) and case_ok(pycfile):
             # existing .pyc file
             return PY_COMPILED, ".pyc", "rb"
 
+    if space.config.objspace.usemodules.cpyext:
+        pydfile = filepart + so_extension
+        if os.path.exists(pydfile) and case_ok(pydfile):
+            return C_EXTENSION, so_extension, "rb"
+
     return SEARCH_ERROR, None, None
 
 if sys.platform in ['linux2', 'freebsd']:
@@ -332,6 +339,9 @@
                     except:
                         stream.close()
                         raise
+                if modtype == C_EXTENSION:
+                    filename = filepart + suffix
+                    return FindInfo(modtype, filename, None, suffix, filemode)
             except StreamErrors:
                 pass
 
@@ -356,7 +366,7 @@
     if find_info.modtype == C_BUILTIN:
         return space.getbuiltinmodule(find_info.filename, force_init=True)
 
-    if find_info.modtype in (PY_SOURCE, PY_COMPILED, PKG_DIRECTORY):
+    if find_info.modtype in (PY_SOURCE, PY_COMPILED, C_EXTENSION, PKG_DIRECTORY):
         w_mod = None
         if reuse:
             try:
@@ -397,6 +407,12 @@
                 # fetch the module again, in case of "substitution"
                 w_mod = check_sys_modules(space, w_modulename)
                 return w_mod
+            elif find_info.modtype == C_EXTENSION and space.config.objspace.usemodules.cpyext:
+                # the next line is mandantory to init cpyext
+                space.getbuiltinmodule("cpyext")
+                from pypy.module.cpyext.api import load_extension_module
+                load_extension_module(space, find_info.filename, space.str_w(w_modulename))
+                return check_sys_modules(space, w_modulename)
         except OperationError:
             w_mods = space.sys.get('modules')
             space.call_method(w_mods, 'pop', w_modulename, space.w_None)

Modified: pypy/branch/py12/pypy/module/thread/ll_thread.py
==============================================================================
--- pypy/branch/py12/pypy/module/thread/ll_thread.py	(original)
+++ pypy/branch/py12/pypy/module/thread/ll_thread.py	Sun May  2 18:05:10 2010
@@ -35,15 +35,15 @@
         ident = thread.start_new_thread(func, ())
     except thread.error:
         ident = -1
-    return rffi.cast(rffi.INT, ident)
+    return rffi.cast(rffi.LONG, ident)
 
 CALLBACK = lltype.Ptr(lltype.FuncType([], lltype.Void))
-c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.INT,
+c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.LONG,
                             _callable=_emulated_start_new_thread,
                             threadsafe=True)  # release the GIL, but most
                                               # importantly, reacquire it
                                               # around the callback
-c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT,
+c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.LONG,
                                 _nowrapper=True)    # always call directly
 
 TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock',

Modified: pypy/branch/py12/pypy/module/thread/test/test_ll_thread.py
==============================================================================
--- pypy/branch/py12/pypy/module/thread/test/test_ll_thread.py	(original)
+++ pypy/branch/py12/pypy/module/thread/test/test_ll_thread.py	Sun May  2 18:05:10 2010
@@ -47,15 +47,16 @@
                 state.freed_counter += 1
 
         def bootstrap():
-            state.my_thread_ident = get_ident()
+            state.my_thread_ident = state.z.ident = get_ident()
             assert state.my_thread_ident == get_ident()
+            assert get_ident() == state.z.ident
             state.seen_value = state.z.value
             state.z = None
             state.done = 1
 
         def g(i):
             state.z = Z(i)
-            start_new_thread(bootstrap, ())
+            return start_new_thread(bootstrap, ())
         g._dont_inline_ = True
 
         def f():
@@ -65,7 +66,7 @@
             for i in range(50):
                 state.done = 0
                 state.seen_value = 0
-                g(i)
+                ident = g(i)
                 gc.collect()
                 willing_to_wait_more = 1000
                 while not state.done:
@@ -74,6 +75,7 @@
                         raise Exception("thread didn't start?")
                     time.sleep(0.01)
                 assert state.my_thread_ident != main_ident
+                assert state.my_thread_ident == ident
                 assert state.seen_value == i
             # try to force Boehm to do some freeing
             for i in range(3):

Modified: pypy/branch/py12/pypy/objspace/std/fake.py
==============================================================================
--- pypy/branch/py12/pypy/objspace/std/fake.py	(original)
+++ pypy/branch/py12/pypy/objspace/std/fake.py	Sun May  2 18:05:10 2010
@@ -114,6 +114,13 @@
             cpy_type.__name__, base, **kw)
         def __init__(w_self, space, val):
             w_self.val = val
+            w_self.space = space
+        def getdict(w_self):
+            try:
+                d = w_self.val.__dict__
+            except AttributeError:
+                return W_Object.getdict(w_self)
+            return w_self.space.wrap(d)
         def unwrap(w_self, space):
             return w_self.val
     W_Fake.__name__ = 'W_Fake%s'%(cpy_type.__name__.capitalize())

Modified: pypy/branch/py12/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/py12/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/py12/pypy/objspace/std/objspace.py	Sun May  2 18:05:10 2010
@@ -7,7 +7,7 @@
 from pypy.objspace.std import (builtinshortcut, stdtypedef, frame, model,
                                transparent, callmethod, proxyobject)
 from pypy.objspace.descroperation import DescrOperation, raiseattrerror
-from pypy.rlib.objectmodel import instantiate
+from pypy.rlib.objectmodel import instantiate, r_dict
 from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib.rarithmetic import base_int
 from pypy.rlib.objectmodel import we_are_translated
@@ -206,8 +206,11 @@
             return W_ComplexObject(x.real, x.imag)
 
         if isinstance(x, set):
-            wrappeditems = [self.wrap(item) for item in x]
-            return W_SetObject(self, wrappeditems)
+            rdict_w = r_dict(self.eq_w, self.hash_w)
+            for item in x:
+                rdict_w[self.wrap(item)] = None
+            res = W_SetObject(self, rdict_w)
+            return res
 
         if isinstance(x, frozenset):
             wrappeditems = [self.wrap(item) for item in x]
@@ -450,21 +453,33 @@
             raiseattrerror(self, w_obj, name)
 
     def finditem_str(self, w_obj, key):
-        # performance shortcut to avoid creating the OperationError(KeyError)
+        """ Perform a getitem on w_obj with key (string). Returns found
+        element or None on element not found.
+
+        performance shortcut to avoid creating the OperationError(KeyError)
+        and allocating W_StringObject
+        """
         if (isinstance(w_obj, W_DictMultiObject) and
                 not w_obj.user_overridden_class):
             return w_obj.getitem_str(key)
         return ObjSpace.finditem_str(self, w_obj, key)
 
     def finditem(self, w_obj, w_key):
-        # performance shortcut to avoid creating the OperationError(KeyError)
+        """ Perform a getitem on w_obj with w_key (any object). Returns found
+        element or None on element not found.
+
+        performance shortcut to avoid creating the OperationError(KeyError).
+        """
         if (isinstance(w_obj, W_DictMultiObject) and
                 not w_obj.user_overridden_class):
             return w_obj.getitem(w_key)
         return ObjSpace.finditem(self, w_obj, w_key)
 
     def setitem_str(self, w_obj, key, w_value, shadows_type=True):
-        # performance shortcut to avoid creating the OperationError(KeyError)
+        """ Same as setitem, but takes string instead of any wrapped object
+
+        XXX what shadows_type means???
+        """
         if (isinstance(w_obj, W_DictMultiObject) and
                 not w_obj.user_overridden_class):
             w_obj.setitem_str(key, w_value, shadows_type)

Modified: pypy/branch/py12/pypy/objspace/std/test/test_setobject.py
==============================================================================
--- pypy/branch/py12/pypy/objspace/std/test/test_setobject.py	(original)
+++ pypy/branch/py12/pypy/objspace/std/test/test_setobject.py	Sun May  2 18:05:10 2010
@@ -46,6 +46,8 @@
         t = W_SetObject(self.space, None)
         _initialize_set(self.space, t, self.word)
         assert self.space.eq_w(s,t)
+        u = self.space.wrap(set('simsalabim'))
+        assert self.space.eq_w(s,u)
 
 class AppTestAppSetTest:
     def test_subtype(self):

Modified: pypy/branch/py12/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/py12/pypy/objspace/std/typeobject.py	(original)
+++ pypy/branch/py12/pypy/objspace/std/typeobject.py	Sun May  2 18:05:10 2010
@@ -14,6 +14,7 @@
 from pypy.rlib.rarithmetic import intmask, r_uint
 
 from copy_reg import _HEAPTYPE
+_CPYTYPE = 1 # used for non-heap types defined in C
 
 # from compiler/misc.py
 
@@ -96,7 +97,7 @@
         w_self.needsdel = False
         w_self.weakrefable = False
         w_self.weak_subclasses = []
-        w_self.__flags__ = 0           # or _HEAPTYPE
+        w_self.__flags__ = 0           # or _HEAPTYPE or _CPYTYPE
         w_self.instancetypedef = overridetypedef
 
         if overridetypedef is not None:
@@ -353,6 +354,9 @@
     def is_heaptype(w_self):
         return w_self.__flags__&_HEAPTYPE
 
+    def is_cpytype(w_self):
+        return w_self.__flags__ & _CPYTYPE
+
     def get_module(w_self):
         space = w_self.space
         if w_self.is_heaptype() and '__module__' in w_self.dict_w:

Modified: pypy/branch/py12/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/rarithmetic.py	(original)
+++ pypy/branch/py12/pypy/rlib/rarithmetic.py	Sun May  2 18:05:10 2010
@@ -126,6 +126,10 @@
     raise OverflowError
 
 def compute_restype(self_type, other_type):
+    if self_type is other_type:
+        if self_type is bool:
+            return int
+        return self_type
     if other_type in (bool, int, long):
         if self_type is bool:
             return int

Modified: pypy/branch/py12/pypy/rlib/rstring.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/rstring.py	(original)
+++ pypy/branch/py12/pypy/rlib/rstring.py	Sun May  2 18:05:10 2010
@@ -1,11 +1,49 @@
-
-""" String builder interface
+""" String builder interface and string functions
 """
 
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.annotation.model import SomeObject, SomeString, s_None,\
      SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString
 
+
+# -------------- public API for string functions -----------------------
+def split(value, by, maxsplit=-1):
+    bylen = len(by)
+    if bylen == 0:
+        raise ValueError("empty separator")
+
+    res = []
+    start = 0
+    while maxsplit != 0:
+        next = value.find(by, start)
+        if next < 0:
+            break
+        res.append(value[start:next])
+        start = next + bylen
+        maxsplit -= 1   # NB. if it's already < 0, it stays < 0
+
+    res.append(value[start:len(value)])
+    return res
+
+def rsplit(value, by, maxsplit=-1):
+    res = []
+    end = len(value)
+    bylen = len(by)
+    if bylen == 0:
+        raise ValueError("empty separator")
+
+    while maxsplit != 0:
+        next = value.rfind(by, 0, end)
+        if next < 0:
+            break
+        res.append(value[next+bylen:end])
+        end = next
+        maxsplit -= 1   # NB. if it's already < 0, it stays < 0
+
+    res.append(value[:end])
+    res.reverse()
+    return res
+
 # -------------- public API ---------------------------------
 
 INIT_SIZE = 100 # XXX tweak

Modified: pypy/branch/py12/pypy/rlib/rweakref.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/rweakref.py	(original)
+++ pypy/branch/py12/pypy/rlib/rweakref.py	Sun May  2 18:05:10 2010
@@ -1,6 +1,7 @@
 """
 Weakref support in RPython.  Supports ref() without callbacks,
-and a limited version of WeakValueDictionary.  LLType only for now!
+a form of WeakKeyDictionary, and a limited version of WeakValueDictionary.
+LLType only for now!
 """
 
 import weakref
@@ -27,6 +28,36 @@
             self._dict[key] = value
 
 
+class RWeakKeyDictionary(object):
+    """A dictionary containing weak keys.
+    Keys and values must be instances.
+    Prebuilt RWeakKeyDictionaries must be empty.
+    """
+
+    def __init__(self, keyclass, valueclass):
+        self._dict = weakref.WeakKeyDictionary()
+        self._keyclass = keyclass
+        self._valueclass = valueclass
+
+    def get(self, key):
+        """Get the value associated to 'key', or None by default."""
+        assert isinstance(key, self._keyclass)
+        return self._dict.get(key, None)
+
+    def set(self, key, value):
+        """Set the key/value pair (or delete it if value is None)."""
+        assert isinstance(key, self._keyclass)
+        if value is None:
+            self._dict.pop(key, None)
+        else:
+            assert isinstance(value, self._valueclass)
+            self._dict[key] = value
+
+    def length(self):
+        """Mostly for debugging.  Slow, don't use in real code."""
+        return len(self._dict)
+
+
 # ____________________________________________________________
 
 from pypy.rpython import extregistry
@@ -41,8 +72,8 @@
         self.valueclassdef = valueclassdef
 
     def rtyper_makerepr(self, rtyper):
-        from pypy.rlib import rweakrefimpl
-        return rweakrefimpl.WeakValueDictRepr(rtyper)
+        from pypy.rlib import _rweakvaldict
+        return _rweakvaldict.WeakValueDictRepr(rtyper)
 
     def rtyper_makekey_ex(self, rtyper):
         return self.__class__,
@@ -65,14 +96,11 @@
     _about_ = RWeakValueDictionary
 
     def compute_result_annotation(self, s_valueclass):
-        assert isinstance(s_valueclass, annmodel.SomePBC)
-        assert s_valueclass.is_constant()
-        [desc] = s_valueclass.descriptions
-        return SomeWeakValueDict(desc.getuniqueclassdef())
+        return SomeWeakValueDict(_getclassdef(s_valueclass))
 
     def specialize_call(self, hop):
-        from pypy.rlib import rweakrefimpl
-        return rweakrefimpl.specialize_make_weakdict(hop)
+        from pypy.rlib import _rweakvaldict
+        return _rweakvaldict.specialize_make_weakdict(hop)
 
 class Entry(extregistry.ExtRegistryEntry):
     _type_ = RWeakValueDictionary
@@ -81,3 +109,65 @@
         bk = self.bookkeeper
         x = self.instance
         return SomeWeakValueDict(bk.getuniqueclassdef(x._valueclass))
+
+def _getclassdef(s_instance):
+    assert isinstance(s_instance, annmodel.SomePBC)
+    assert s_instance.is_constant()
+    [desc] = s_instance.descriptions
+    return desc.getuniqueclassdef()
+
+# ____________________________________________________________
+
+class SomeWeakKeyDict(annmodel.SomeObject):
+    knowntype = RWeakKeyDictionary
+
+    def __init__(self, keyclassdef, valueclassdef):
+        self.keyclassdef = keyclassdef
+        self.valueclassdef = valueclassdef
+
+    def rtyper_makerepr(self, rtyper):
+        from pypy.rlib import _rweakkeydict
+        return _rweakkeydict.WeakKeyDictRepr(rtyper)
+
+    def rtyper_makekey_ex(self, rtyper):
+        return self.__class__,
+
+    def method_get(self, s_key):
+        assert isinstance(s_key, annmodel.SomeInstance)
+        assert s_key.classdef.issubclass(self.keyclassdef)
+        return annmodel.SomeInstance(self.valueclassdef, can_be_None=True)
+
+    def method_set(self, s_key, s_value):
+        s_oldvalue = self.method_get(s_key)
+        assert s_oldvalue.contains(s_value)
+
+    def method_length(self):
+        return annmodel.SomeInteger(nonneg=True)
+
+class __extend__(pairtype(SomeWeakKeyDict, SomeWeakKeyDict)):
+    def union((s_wkd1, s_wkd2)):
+        if s_wkd1.keyclassdef is not s_wkd2.keyclassdef:
+            return SomeObject() # not the same key class! complain...
+        if s_wkd1.valueclassdef is not s_wkd2.valueclassdef:
+            return SomeObject() # not the same value class! complain...
+        return SomeWeakKeyDict(s_wkd1.keyclassdef, s_wkd1.valueclassdef)
+
+class Entry(extregistry.ExtRegistryEntry):
+    _about_ = RWeakKeyDictionary
+
+    def compute_result_annotation(self, s_keyclass, s_valueclass):
+        return SomeWeakKeyDict(_getclassdef(s_keyclass),
+                               _getclassdef(s_valueclass))
+
+    def specialize_call(self, hop):
+        from pypy.rlib import _rweakkeydict
+        return _rweakkeydict.specialize_make_weakdict(hop)
+
+class Entry(extregistry.ExtRegistryEntry):
+    _type_ = RWeakKeyDictionary
+
+    def compute_annotation(self):
+        bk = self.bookkeeper
+        x = self.instance
+        return SomeWeakKeyDict(bk.getuniqueclassdef(x._keyclass),
+                               bk.getuniqueclassdef(x._valueclass))

Modified: pypy/branch/py12/pypy/rlib/test/test_rarithmetic.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/test/test_rarithmetic.py	(original)
+++ pypy/branch/py12/pypy/rlib/test/test_rarithmetic.py	Sun May  2 18:05:10 2010
@@ -365,3 +365,7 @@
 
 def test_isnan():
     assert isnan(NAN)
+
+def test_int_real_union():
+    from pypy.rpython.lltypesystem.rffi import r_int_real
+    assert compute_restype(r_int_real, r_int_real) is r_int_real

Modified: pypy/branch/py12/pypy/rlib/test/test_rbigint.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/test/test_rbigint.py	(original)
+++ pypy/branch/py12/pypy/rlib/test/test_rbigint.py	Sun May  2 18:05:10 2010
@@ -474,10 +474,11 @@
     def test_args_from_rarith_int(self):
         from pypy.rpython.tool.rfficache import platform
         from pypy.rlib.rarithmetic import r_int
+        from pypy.rpython.lltypesystem.rffi import r_int_real
         classlist = platform.numbertype_to_rclass.values()
         fnlist = []
         for r in classlist:
-            if r is r_int:     # and also r_longlong on 64-bit
+            if r in (r_int, r_int_real):     # and also r_longlong on 64-bit
                 continue
             if r is int:
                 mask = sys.maxint*2+1

Modified: pypy/branch/py12/pypy/rlib/test/test_rstring.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/test/test_rstring.py	(original)
+++ pypy/branch/py12/pypy/rlib/test/test_rstring.py	Sun May  2 18:05:10 2010
@@ -1,5 +1,26 @@
 
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
+from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit
+
+def test_split():
+    assert split("", 'x') == ['']
+    assert split("a", "a", 1) == ['', '']
+    assert split(" ", " ", 1) == ['', '']
+    assert split("aa", "a", 2) == ['', '', '']
+    assert split('a|b|c|d', '|') == ['a', 'b', 'c', 'd']
+    assert split('a|b|c|d', '|', 2) == ['a', 'b', 'c|d']
+    assert split('a//b//c//d', '//') == ['a', 'b', 'c', 'd']
+    assert split('endcase test', 'test') == ['endcase ', '']
+    raises(ValueError, split, 'abc', '')
+
+def test_rsplit():
+    assert rsplit("a", "a", 1) == ['', '']
+    assert rsplit(" ", " ", 1) == ['', '']
+    assert rsplit("aa", "a", 2) == ['', '', '']
+    assert rsplit('a|b|c|d', '|') == ['a', 'b', 'c', 'd']
+    assert rsplit('a|b|c|d', '|', 2) == ['a|b', 'c', 'd']
+    assert rsplit('a//b//c//d', '//') == ['a', 'b', 'c', 'd']
+    assert rsplit('endcase test', 'test') == ['endcase ', '']
+    raises(ValueError, rsplit, "abc", '')
 
 def test_string_builder():
     s = StringBuilder()

Modified: pypy/branch/py12/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/annlowlevel.py	(original)
+++ pypy/branch/py12/pypy/rpython/annlowlevel.py	Sun May  2 18:05:10 2010
@@ -34,6 +34,7 @@
             else:
                 s = compact()        
         return s + 'Const'
+    __repr__ = __str__
 
 class LowLevelAnnotatorPolicy(AnnotatorPolicy):
     allow_someobjects = False

Modified: pypy/branch/py12/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/ll2ctypes.py	Sun May  2 18:05:10 2010
@@ -675,7 +675,8 @@
     if T is lltype.Void:
         return None
     if isinstance(T, lltype.Ptr):
-        if not cobj:   # NULL pointer
+        if not cobj or not ctypes.cast(cobj, ctypes.c_void_p).value:   # NULL pointer
+            # CFunctionType.__nonzero__ is broken before Python 2.6
             return lltype.nullptr(T.TO)
         if isinstance(T.TO, lltype.Struct):
             REAL_TYPE = T.TO
@@ -963,7 +964,7 @@
     def invoke_via_ctypes(*argvalues):
         global _callback_exc_info
         cargs = []
-        for i in range(len(FUNCTYPE.ARGS)):
+        for i in range(len(argvalues)):
             if i not in void_arguments:
                 cvalue = lltype2ctypes(argvalues[i])
                 if i in container_arguments:
@@ -1001,7 +1002,7 @@
     elif isinstance(cvalue, (str, unicode)):
         cvalue = ord(cvalue)     # character -> integer
 
-    if not isinstance(cvalue, (int, long)):
+    if not isinstance(cvalue, (int, long, float)):
         raise NotImplementedError("casting %r to %r" % (TYPE1, RESTYPE))
 
     if isinstance(RESTYPE, lltype.Ptr):

Modified: pypy/branch/py12/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/lltype.py	Sun May  2 18:05:10 2010
@@ -1,3 +1,8 @@
+import StringIO
+import traceback
+import sys
+
+import py
 from pypy.rlib.rarithmetic import (r_int, r_uint, intmask, r_singlefloat,
                                    r_ulonglong, r_longlong, base_int,
                                    normalizedinttype)
@@ -12,6 +17,20 @@
 
 TLS = tlsobject()
 
+# Track allocations to detect memory leaks
+# Don't track 'gc' and immortal mallocs
+TRACK_ALLOCATIONS = False
+ALLOCATED = identity_dict()
+
+def start_tracking_allocations():
+    global TRACK_ALLOCATIONS
+    TRACK_ALLOCATIONS = True
+    ALLOCATED.clear()
+
+def stop_tracking_allocations():
+    global TRACK_ALLOCATIONS
+    TRACK_ALLOCATIONS = False
+
 class _uninitialized(object):
     def __init__(self, TYPE):
         self.TYPE = TYPE
@@ -1318,21 +1337,41 @@
     __slots__ = ('_TYPE',
                  '_parent_type', '_parent_index', '_keepparent',
                  '_wrparent',
-                 '__weakref__',
-                 '_storage')
+                 '__weakref__', '_traceback',
+                 '__storage')
 
-    def __init__(self, TYPE):
+    def __init__(self, TYPE, track_allocation=None):
         self._wrparent = None
         self._TYPE = TYPE
         self._storage = True    # means "use default storage", as opposed to:
                                 #    None            - container was freed
                                 #    <ctypes object> - using ctypes
                                 #                      (see ll2ctypes.py)
+        if track_allocation is not False and TRACK_ALLOCATIONS:
+            self._traceback = self._get_traceback()
+            ALLOCATED[self] = None
+        else:
+            self._traceback = None
+
+    def _get_traceback(self):
+        frame = sys._getframe().f_back.f_back.f_back.f_back
+        sio = StringIO.StringIO()
+        traceback.print_stack(frame, file=sio)
+        return sio.getvalue()
 
     def _free(self):
         self._check()   # no double-frees
         self._storage = None
 
+    def _storage_get(self):
+        return self.__storage
+
+    def _storage_set(self, value):
+        self.__storage = value
+        if value is not True and self in ALLOCATED:
+            del ALLOCATED[self]
+    _storage = property(_storage_get, _storage_set)
+
     def _was_freed(self):
         if self._storage is None:
             return True
@@ -1409,14 +1448,14 @@
 class _struct(_parentable):
     _kind = "structure"
 
-    __slots__ = ('_hash_cache_',)
+    __slots__ = ('_hash_cache_', '_compilation_info')
 
-    def __new__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None):
+    def __new__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None, track_allocation=None):
         my_variety = _struct_variety(TYPE._names)
         return object.__new__(my_variety)
 
-    def __init__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None):
-        _parentable.__init__(self, TYPE)
+    def __init__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None, track_allocation=None):
+        _parentable.__init__(self, TYPE, track_allocation)
         if n is not None and TYPE._arrayfld is None:
             raise TypeError("%r is not variable-sized" % (TYPE,))
         if n is None and TYPE._arrayfld is not None:
@@ -1424,7 +1463,8 @@
         first, FIRSTTYPE = TYPE._first_struct()
         for fld, typ in TYPE._flds.items():
             if fld == TYPE._arrayfld:
-                value = _array(typ, n, initialization=initialization, parent=self, parentindex=fld)
+                value = _array(typ, n, initialization=initialization, parent=self, parentindex=fld,
+                               track_allocation=track_allocation)
             else:
                 value = typ._allocate(initialization=initialization, parent=self, parentindex=fld)
             setattr(self, fld, value)
@@ -1485,12 +1525,12 @@
 
     __slots__ = ('items',)
 
-    def __init__(self, TYPE, n, initialization=None, parent=None, parentindex=None):
+    def __init__(self, TYPE, n, initialization=None, parent=None, parentindex=None, track_allocation=None):
         if not isinstance(n, int):
             raise TypeError, "array length must be an int"
         if n < 0:
             raise ValueError, "negative array length"
-        _parentable.__init__(self, TYPE)
+        _parentable.__init__(self, TYPE, track_allocation)
         try:
             myrange = range(n)
         except OverflowError:
@@ -1557,7 +1597,7 @@
     _cache = weakref.WeakKeyDictionary()  # parentarray -> {subarrays}
 
     def __init__(self, TYPE, parent, baseoffset_or_fieldname):
-        _parentable.__init__(self, TYPE)
+        _parentable.__init__(self, TYPE, track_allocation=False)
         self._setparentstructure(parent, baseoffset_or_fieldname)
         # Keep the parent array alive, we share the same allocation.
         # Don't do it if we are inside a GC object, though -- it's someone
@@ -1787,9 +1827,9 @@
     else:
         initialization = 'malloc'
     if isinstance(T, Struct):
-        o = _struct(T, n, initialization=initialization)
+        o = _struct(T, n, initialization=initialization, track_allocation=flavor == "raw" and not immortal)
     elif isinstance(T, Array):
-        o = _array(T, n, initialization=initialization)
+        o = _array(T, n, initialization=initialization, track_allocation=flavor == "raw" and not immortal)
     elif isinstance(T, OpaqueType):
         assert n is None
         o = _opaque(T, initialization=initialization)

Modified: pypy/branch/py12/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/rdict.py	(original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/rdict.py	Sun May  2 18:05:10 2010
@@ -508,12 +508,14 @@
 
 def ll_dict_lookup(d, key, hash):
     entries = d.entries
+    ENTRIES = lltype.typeOf(entries).TO
+    direct_compare = not hasattr(ENTRIES, 'no_direct_compare')
     mask = len(entries) - 1
     i = hash & mask
     # do the first try before any looping 
     if entries.valid(i):
         checkingkey = entries[i].key
-        if checkingkey == key:
+        if direct_compare and checkingkey == key:
             return i   # found the entry
         if d.keyeq is not None and entries.hash(i) == hash:
             # correct hash, maybe the key is e.g. a different pointer to
@@ -548,7 +550,7 @@
             return freeslot
         elif entries.valid(i):
             checkingkey = entries[i].key
-            if checkingkey == key:
+            if direct_compare and checkingkey == key:
                 return i
             if d.keyeq is not None and entries.hash(i) == hash:
                 # correct hash, maybe the key is e.g. a different pointer to

Modified: pypy/branch/py12/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/rffi.py	Sun May  2 18:05:10 2010
@@ -48,6 +48,7 @@
         result = isinstance(s_p, annmodel.SomePtr)
         return self.bookkeeper.immutablevalue(result)
     def specialize_call(self, hop):
+        hop.exception_cannot_occur()
         return hop.inputconst(lltype.Bool, hop.s_result.const)
 
 def llexternal(name, args, result, _callable=None,
@@ -388,6 +389,7 @@
 r_int_real = rarithmetic.build_int("r_int_real", r_int.SIGN, r_int.BITS, True)
 INT_real = lltype.build_number("INT", r_int_real)
 platform.numbertype_to_rclass[INT_real] = r_int_real
+NUMBER_TYPES.append(INT_real)
 
 # ^^^ this creates at least the following names:
 # --------------------------------------------------------------------

Modified: pypy/branch/py12/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	(original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	Sun May  2 18:05:10 2010
@@ -432,6 +432,29 @@
         rffi.free_charp(p)
         assert not ALLOCATED     # detects memory leaks in the test
 
+    def test_funcptr_cast(self):
+        eci = ExternalCompilationInfo(
+            separate_module_sources=["""
+            long mul(long x, long y) { return x*y; }
+            long(*get_mul(long x)) () { return &mul; }
+            """],
+            export_symbols=['get_mul'])
+        get_mul = rffi.llexternal(
+            'get_mul', [],
+            lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)),
+            compilation_info=eci)
+        # This call returns a pointer to a function taking one argument
+        funcptr = get_mul()
+        # cast it to the "real" function type
+        FUNCTYPE2 = lltype.FuncType([lltype.Signed, lltype.Signed],
+                                    lltype.Signed)
+        cmul = rffi.cast(lltype.Ptr(FUNCTYPE2), funcptr)
+        # and it can be called with the expected number of arguments
+        res = cmul(41, 42)
+        assert res == 41 * 42
+        raises(TypeError, cmul, 41)
+        raises(TypeError, cmul, 41, 42, 43)
+
     def test_qsort(self):
         CMPFUNC = lltype.FuncType([rffi.VOIDP, rffi.VOIDP], rffi.INT)
         qsort = rffi.llexternal('qsort', [rffi.VOIDP,

Modified: pypy/branch/py12/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/test/test_lltype.py	(original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/test/test_lltype.py	Sun May  2 18:05:10 2010
@@ -1,5 +1,6 @@
 import py
 from pypy.rpython.lltypesystem.lltype import *
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.lib.identity_dict import identity_dict
 
 def isweak(p, T):
@@ -777,3 +778,42 @@
     assert hash1 == identityhash(a)
     p = cast_opaque_ptr(llmemory.GCREF, a)
     assert hash1 == identityhash(p)
+
+class TestTrackAllocation:
+    def setup_method(self, func):
+        start_tracking_allocations()
+
+    def teardown_method(self, func):
+        assert not lltype.ALLOCATED, "Memory was not correctly freed"
+        stop_tracking_allocations()
+
+    def test_track_allocation(self):
+        """A malloc'd buffer fills the ALLOCATED dictionary"""
+        assert lltype.TRACK_ALLOCATIONS
+        assert not lltype.ALLOCATED
+        buf = malloc(Array(Signed), 1, flavor="raw")
+        assert len(lltype.ALLOCATED) == 1
+        assert lltype.ALLOCATED.keys() == [buf._obj]
+        free(buf, flavor="raw")
+        assert not lltype.ALLOCATED
+
+    def test_str_from_buffer(self):
+        """gc-managed memory does not need to be freed"""
+        size = 50
+        raw_buf, gc_buf = rffi.alloc_buffer(size)
+        for i in range(size): raw_buf[i] = 'a'
+        rstr = rffi.str_from_buffer(raw_buf, gc_buf, size, size)
+        rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+        assert not lltype.ALLOCATED
+
+    def test_leak_traceback(self):
+        """Test info stored for allocated items"""
+        buf = malloc(Array(Signed), 1, flavor="raw")
+        traceback = lltype.ALLOCATED.keys()[0]._traceback
+        lines = traceback.splitlines()
+        assert 'malloc(' in lines[-1] and 'flavor="raw")' in lines[-1]
+
+        # XXX The traceback should not be too long
+        print traceback
+
+        free(buf, flavor="raw")

Modified: pypy/branch/py12/pypy/rpython/test/test_llinterp.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/test/test_llinterp.py	(original)
+++ pypy/branch/py12/pypy/rpython/test/test_llinterp.py	Sun May  2 18:05:10 2010
@@ -43,7 +43,7 @@
     t = TranslationContext(config=config)
     t.config.set(**extraconfigopts)
     a = t.buildannotator(policy=policy)
-    timelog("annotating", a.build_types, func, argtypes)
+    timelog("annotating", a.build_types, func, argtypes, main_entry_point=True)
     if viewbefore == 'auto':
         viewbefore = getattr(conftest.option, 'view', False)
     if viewbefore:

Modified: pypy/branch/py12/pypy/tool/fixeol
==============================================================================
--- pypy/branch/py12/pypy/tool/fixeol	(original)
+++ pypy/branch/py12/pypy/tool/fixeol	Sun May  2 18:05:10 2010
@@ -48,7 +48,7 @@
     return True
 
 def checkeolfile(path):     
-    return path.ext in ('.txt', '.py', '.asc')
+    return path.ext in ('.txt', '.py', '.asc', '.h', '.c')
 
 def fixdirectory(path): 
     print "+ checking directory", path, 

Modified: pypy/branch/py12/pypy/translator/c/gcc/test/test_asmgcroot.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/gcc/test/test_asmgcroot.py	(original)
+++ pypy/branch/py12/pypy/translator/c/gcc/test/test_asmgcroot.py	Sun May  2 18:05:10 2010
@@ -1,10 +1,14 @@
 import py
-import sys, os
+import sys, os, gc
 from pypy.translator.c.test import test_newgc
 from pypy.translator.translator import TranslationContext
 from pypy.translator.c.genc import CStandaloneBuilder
 from pypy.annotation.listdef import s_list_of_strings
 from pypy import conftest
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib.entrypoint import entrypoint, secondary_entrypoints
+from pypy.rpython.lltypesystem.lloperation import llop
 
 class AbstractTestAsmGCRoot:
     # the asmgcroot gc transformer doesn't generate gc_reload_possibly_moved
@@ -34,11 +38,15 @@
         config = cls.make_config()
         t = TranslationContext(config=config)
         a = t.buildannotator()
+        sec_ep = getattr(cls, 'secondary_entrypoints', [])
+        for f, inputtypes in sec_ep:
+            a.build_types(f, inputtypes, False)
         a.build_types(main, [s_list_of_strings])
         t.buildrtyper().specialize()
         t.checkgraphs()
 
-        cbuilder = CStandaloneBuilder(t, main, config=config)
+        cbuilder = CStandaloneBuilder(t, main, config=config,
+                secondary_entrypoints=sec_ep)
         c_source_filename = cbuilder.generate_source(
             defines = cbuilder.DEBUG_DEFINES)
         cls._patch_makefile(cbuilder.targetdir)
@@ -53,7 +61,12 @@
                 redirect = ' 2> NUL'
             else:
                 redirect = ''
-            g = os.popen('"%s" %s %d%s' % (exe_name, arg0, arg1, redirect), 'r')
+            if config.translation.shared and os.name == 'posix':
+                env = 'LD_LIBRARY_PATH="%s" ' % (exe_name.dirpath(),)
+            else:
+                env = ''
+            g = os.popen(
+                '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r')
             for line in g:
                 print >> sys.stderr, 'RUN:', line.rstrip()
                 lines.append(line)
@@ -101,6 +114,7 @@
                                    test_newgc.TestSemiSpaceGC):
     # for the individual tests see
     # ====> ../../test/test_newgc.py
+    secondary_entrypoints = []
 
     def define_large_function(cls):
         class A(object):
@@ -123,11 +137,6 @@
         assert res == 1000
 
     def define_callback_simple(cls):
-        import gc
-        from pypy.rpython.lltypesystem import lltype, rffi
-        from pypy.rpython.annlowlevel import llhelper
-        from pypy.translator.tool.cbuild import ExternalCompilationInfo
-
         c_source = py.code.Source("""
         int mystuff(int(*cb)(int, int))
         {
@@ -153,11 +162,50 @@
 
         return f
 
-
     def test_callback_simple(self):
         res = self.run('callback_simple')
         assert res == 4900
 
+    def define_secondary_entrypoint_callback(cls):
+        # XXX this is baaaad, cleanup global state
+        try:
+            del secondary_entrypoints["x42"]
+        except KeyError:
+            pass
+        
+        @entrypoint("x42", [lltype.Signed, lltype.Signed], c_name='callback')
+        def mycallback(a, b):
+            llop.gc_stack_bottom(lltype.Void)
+            rffi.stackcounter.stacks_counter += 1
+            gc.collect()
+            rffi.stackcounter.stacks_counter -= 1
+            return a + b
+
+        c_source = py.code.Source("""
+        int mystuff2()
+        {
+            return callback(40, 2) + callback(3, 4);
+        }
+        """)
+
+        eci = ExternalCompilationInfo(separate_module_sources=[c_source])
+        z = rffi.llexternal('mystuff2', [], lltype.Signed,
+                            compilation_info=eci)
+        S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+        cls.secondary_entrypoints = secondary_entrypoints["x42"]
+
+        def f():
+            p = lltype.malloc(S)
+            p.x = 100
+            result = z()
+            return result * p.x
+
+        return f
+
+    def test_secondary_entrypoint_callback(self):
+        res = self.run('secondary_entrypoint_callback')
+        assert res == 4900
 
 class TestAsmGCRootWithSemiSpaceGC_Mingw32(TestAsmGCRootWithSemiSpaceGC):
     # for the individual tests see
@@ -186,6 +234,13 @@
     def define_callback_with_collect(cls):
         return lambda: 0
 
+class TestAsmGCRootWithSemiSpaceGC_Shared(TestAsmGCRootWithSemiSpaceGC):
+    @classmethod
+    def make_config(cls):
+        config = TestAsmGCRootWithSemiSpaceGC.make_config()
+        config.translation.shared = True
+        return config
+
 class TestAsmGCRootWithHybridTagged(AbstractTestAsmGCRoot,
                                     test_newgc.TestHybridTaggedPointers):
     pass

Modified: pypy/branch/py12/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/py12/pypy/translator/c/gcc/trackgcroot.py	Sun May  2 18:05:10 2010
@@ -1640,6 +1640,7 @@
         format = 'mingw32'
     else:
         format = 'elf'
+    entrypoint = 'main'
     while len(sys.argv) > 1:
         if sys.argv[1] == '-v':
             del sys.argv[1]
@@ -1653,6 +1654,9 @@
         elif sys.argv[1].startswith('-f'):
             format = sys.argv[1][2:]
             del sys.argv[1]
+        elif sys.argv[1].startswith('-m'):
+            entrypoint = sys.argv[1][2:]
+            del sys.argv[1]
         else:
             break
     tracker = GcRootTracker(verbose=verbose, shuffle=shuffle, format=format)
@@ -1669,7 +1673,7 @@
             lblfn = fn[:-2] + '.lbl.s'
             g = open(lblfn, 'w')
             try:
-                tracker.process(f, g, filename=fn)
+                tracker.process(f, g, entrypoint=entrypoint, filename=fn)
             except:
                 g.close()
                 os.unlink(lblfn)

Modified: pypy/branch/py12/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/genc.py	(original)
+++ pypy/branch/py12/pypy/translator/c/genc.py	Sun May  2 18:05:10 2010
@@ -13,6 +13,7 @@
 from pypy.translator.c.support import log, c_string_constant
 from pypy.rpython.typesystem import getfunctionptr
 from pypy.translator.c import gc
+from pypy.rlib import exports
 
 def import_module_from_directory(dir, modname):
     file, pathname, description = imp.find_module(modname, [str(dir)])
@@ -77,14 +78,22 @@
         self.outputfilename = outputfilename
         self.profbased = profbased
 
-    def _build(self, eci=ExternalCompilationInfo()):
+    def _build(self, eci=ExternalCompilationInfo(), shared=False):
+        outputfilename = self.outputfilename
+        if shared:
+            if outputfilename:
+                basename = outputfilename
+            else:
+                basename = self.cfiles[0].purebasename
+            outputfilename = 'lib' + basename
         return self.platform.compile(self.cfiles, self.eci.merge(eci),
-                                     outputfilename=self.outputfilename)
+                                     outputfilename=outputfilename,
+                                     standalone=not shared)
 
-    def build(self):
+    def build(self, shared=False):
         if self.profbased:
             return self._do_profbased()
-        return self._build()
+        return self._build(shared=shared)
 
     def _do_profbased(self):
         ProfDriver, args = self.profbased
@@ -103,7 +112,8 @@
     modulename = None
     split = False
     
-    def __init__(self, translator, entrypoint, config, gcpolicy=None):
+    def __init__(self, translator, entrypoint, config, gcpolicy=None,
+            secondary_entrypoints=()):
         self.translator = translator
         self.entrypoint = entrypoint
         self.entrypoint_name = getattr(self.entrypoint, 'func_name', None)
@@ -113,6 +123,7 @@
         if gcpolicy is not None and gcpolicy.requires_stackless:
             config.translation.stackless = True
         self.eci = self.get_eci()
+        self.secondary_entrypoints = secondary_entrypoints
 
     def get_eci(self):
         pypy_include_dir = py.path.local(autopath.pypydir).join('translator', 'c')
@@ -159,7 +170,16 @@
             self.c_entrypoint_name = None
         else:
             pfname = db.get(pf)
+
+            for func, _ in self.secondary_entrypoints:
+                bk = translator.annotator.bookkeeper
+                db.get(getfunctionptr(bk.getdesc(func).getuniquegraph()))
+
             self.c_entrypoint_name = pfname
+
+        for obj in exports.EXPORTS_obj2name.keys():
+            db.getcontainernode(obj)
+        exports.clear()
         db.complete()
 
         self.collect_compilation_info(db)
@@ -240,6 +260,10 @@
             if CBuilder.have___thread:
                 if not self.config.translation.no__thread:
                     defines['USE___THREAD'] = 1
+            if self.config.translation.shared:
+                defines['PYPY_MAIN_FUNCTION'] = "pypy_main_startup"
+                self.eci = self.eci.merge(ExternalCompilationInfo(
+                    export_symbols=["pypy_main_startup"]))
             self.eci, cfile, extra = gen_source_standalone(db, modulename,
                                                  targetdir,
                                                  self.eci,
@@ -404,12 +428,13 @@
         if isinstance(self._module, isolate.Isolate):
             isolate.close_isolate(self._module)
 
-    def gen_makefile(self, targetdir):
+    def gen_makefile(self, targetdir, exe_name=None):
         pass
 
 class CStandaloneBuilder(CBuilder):
     standalone = True
     executable_name = None
+    shared_library_name = None
 
     def getprofbased(self):
         profbased = None
@@ -450,9 +475,40 @@
             return res.out, res.err
         return res.out
 
-    def compile(self):
+    def build_main_for_shared(self, shared_library_name, entrypoint, exe_name):
+        import time
+        time.sleep(1)
+        self.shared_library_name = shared_library_name
+        # build main program
+        eci = self.get_eci()
+        kw = {}
+        if self.translator.platform.so_ext == 'so':
+            kw['libraries'] = [self.shared_library_name.purebasename[3:]]
+            kw['library_dirs'] = [self.targetdir]
+        else:
+            kw['libraries'] = [self.shared_library_name.new(ext='')]
+        eci = eci.merge(ExternalCompilationInfo(
+            separate_module_sources=['''
+                int %s(int argc, char* argv[]);
+
+                int main(int argc, char* argv[])
+                { return %s(argc, argv); }
+                ''' % (entrypoint, entrypoint)
+                ],
+            **kw
+            ))
+        eci = eci.convert_sources_to_files(
+            cache_dir=self.targetdir)
+        return self.translator.platform.compile(
+            [], eci,
+            outputfilename=exe_name)
+
+    def compile(self, exe_name=None):
         assert self.c_source_filename
         assert not self._compiled
+
+        shared = self.config.translation.shared
+
         if (self.config.translation.gcrootfinder == "asmgcc" or
             self.config.translation.force_make):
             extra_opts = []
@@ -463,16 +519,23 @@
         else:
             compiler = CCompilerDriver(self.translator.platform,
                                        [self.c_source_filename] + self.extrafiles,
-                                       self.eci, profbased=self.getprofbased())
-            self.executable_name = compiler.build()
+                                       self.eci, profbased=self.getprofbased(),
+                                       outputfilename=exe_name)
+            self.executable_name = compiler.build(shared=shared)
+            if shared:
+                self.executable_name = self.build_main_for_shared(
+                    self.executable_name, "pypy_main_startup", exe_name)
             assert self.executable_name
         self._compiled = True
         return self.executable_name
 
-    def gen_makefile(self, targetdir):
+    def gen_makefile(self, targetdir, exe_name=None):
         cfiles = [self.c_source_filename] + self.extrafiles
-        mk = self.translator.platform.gen_makefile(cfiles, self.eci,
-                                                   path=targetdir)
+        mk = self.translator.platform.gen_makefile(
+            cfiles, self.eci,
+            path=targetdir, exe_name=exe_name,
+            shared=self.config.translation.shared)
+
         if self.has_profopt():
             profopt = self.config.translation.profopt
             mk.definition('ABS_TARGET', '$(shell python -c "import sys,os; print os.path.abspath(sys.argv[1])" $(TARGET))')
@@ -516,6 +579,11 @@
             mk.definition('GCMAPFILES', gcmapfiles)
             mk.definition('DEBUGFLAGS', '-O2 -fomit-frame-pointer -g')
 
+            if self.config.translation.shared:
+                mk.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup")
+            else:
+                mk.definition('PYPY_MAIN_FUNCTION', "main")
+
             if sys.platform == 'win32':
                 python = sys.executable.replace('\\', '/') + ' '
             else:
@@ -541,7 +609,7 @@
                         'cmd /c $(MASM) /nologo /Cx /Cp /Zm /coff /Fo$@ /c $< $(INCLUDEDIRS)')
                 mk.rule('.c.gcmap', '',
                         ['$(CC) /nologo $(ASM_CFLAGS) /c /FAs /Fa$*.s $< $(INCLUDEDIRS)',
-                         'cmd /c ' + python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -fmsvc -t $*.s > $@']
+                         'cmd /c ' + python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -fmsvc -m$(PYPY_MAIN_FUNCTION) -t $*.s > $@']
                         )
                 mk.rule('gcmaptable.c', '$(GCMAPFILES)',
                         'cmd /c ' + python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -fmsvc $(GCMAPFILES) > $@')
@@ -550,7 +618,7 @@
                 mk.definition('OBJECTS', '$(ASMLBLFILES) gcmaptable.s')
                 mk.rule('%.s', '%.c', '$(CC) $(CFLAGS) $(CFLAGSEXTRA) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS)')
                 mk.rule('%.lbl.s %.gcmap', '%.s',
-                        python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -t $< > $*.gcmap')
+                        python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -m$(PYPY_MAIN_FUNCTION) -t $< > $*.gcmap')
                 mk.rule('gcmaptable.s', '$(GCMAPFILES)',
                         python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@')
 

Modified: pypy/branch/py12/pypy/translator/c/node.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/node.py	(original)
+++ pypy/branch/py12/pypy/translator/c/node.py	Sun May  2 18:05:10 2010
@@ -10,6 +10,7 @@
 from pypy.translator.c.support import cdecl, forward_cdecl, somelettersfrom
 from pypy.translator.c.support import c_char_array_constant, barebonearray
 from pypy.translator.c.primitive import PrimitiveType, name_signed
+from pypy.rlib import exports
 from pypy.rlib.rarithmetic import isinf, isnan
 from pypy.rlib.rstackovf import _StackOverflow
 from pypy.translator.c import extfunc
@@ -468,7 +469,7 @@
     if USESLOTS:
         __slots__ = """db T obj 
                        typename implementationtypename
-                        name ptrname
+                        name ptrname compilation_info
                         globalcontainer""".split()
 
     def __init__(self, db, T, obj):
@@ -479,7 +480,10 @@
         self.typename = db.gettype(T)  #, who_asks=self)
         self.implementationtypename = db.gettype(T, varlength=self.getlength())
         parent, parentindex = parentlink(obj)
-        if parent is None:
+        if obj in exports.EXPORTS_obj2name:
+            self.name = exports.EXPORTS_obj2name[obj]
+            self.globalcontainer = True
+        elif parent is None:
             self.name = db.namespace.uniquename('g_' + self.basename())
             self.globalcontainer = True
         else:
@@ -490,6 +494,7 @@
         if self.typename != self.implementationtypename:
             if db.gettypedefnode(T).extra_union_for_varlength:
                 self.name += '.b'
+        self.compilation_info = getattr(obj, '_compilation_info', None)
         self.ptrname = '(&%s)' % self.name
 
     def is_thread_local(self):
@@ -922,6 +927,8 @@
         else:
             assert fnobj.external == 'CPython'
             return [CExternalFunctionCodeGenerator(fnobj, db)]
+    elif hasattr(fnobj._callable, "c_name"):
+        return []
     else:
         raise ValueError, "don't know how to generate code for %r" % (fnobj,)
 

Modified: pypy/branch/py12/pypy/translator/c/src/commondefs.h
==============================================================================
--- pypy/branch/py12/pypy/translator/c/src/commondefs.h	(original)
+++ pypy/branch/py12/pypy/translator/c/src/commondefs.h	Sun May  2 18:05:10 2010
@@ -15,6 +15,13 @@
 
 #include <limits.h>
 
+#ifndef LLONG_MAX
+#define LLONG_MAX __LONG_LONG_MAX__
+#endif
+#ifndef LLONG_MIN
+#define LLONG_MIN (-LLONG_MAX - 1LL)
+#endif
+
 #if INT_MAX != 2147483647
 #  error "unsupported value for INT_MAX"
 #endif
@@ -62,9 +69,6 @@
 
 /********************************************************/
 
-typedef long Py_intptr_t;
-typedef unsigned long Py_uintptr_t;
-
 #if ((-1) >> 1) > 0
 #  define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) \
 	  ((I) < 0 ? -1-((-1-(I)) >> (J)) : (I) >> (J))

Modified: pypy/branch/py12/pypy/translator/c/src/main.h
==============================================================================
--- pypy/branch/py12/pypy/translator/c/src/main.h	(original)
+++ pypy/branch/py12/pypy/translator/c/src/main.h	Sun May  2 18:05:10 2010
@@ -15,11 +15,15 @@
 
 #ifndef PYPY_NOT_MAIN_FILE
 
+#ifndef PYPY_MAIN_FUNCTION
+#define PYPY_MAIN_FUNCTION main
+#endif
+
 #ifdef MS_WINDOWS
 #include "src/winstuff.c"
 #endif
 
-int main(int argc, char *argv[])
+int PYPY_MAIN_FUNCTION(int argc, char *argv[])
 {
     char *errmsg;
     int i, exitcode;

Modified: pypy/branch/py12/pypy/translator/c/src/obmalloc.c
==============================================================================
--- pypy/branch/py12/pypy/translator/c/src/obmalloc.c	(original)
+++ pypy/branch/py12/pypy/translator/c/src/obmalloc.c	Sun May  2 18:05:10 2010
@@ -225,7 +225,7 @@
 #define ulong			unsigned long	/* assuming >= 32 bits */
 
 #undef uptr
-#define uptr			Py_uintptr_t
+#define uptr			unsigned long
 
 /* When you say memory, my mind reasons in terms of (pointers to) blocks */
 typedef uchar block;
@@ -439,7 +439,7 @@
 	arenabase = bp;
 	nfreepools = ARENA_SIZE / POOL_SIZE;
 	assert(POOL_SIZE * nfreepools == ARENA_SIZE);
-	excess = (uint) ((Py_uintptr_t)bp & POOL_SIZE_MASK);
+	excess = (uint) ((uint)bp & POOL_SIZE_MASK);
 	if (excess != 0) {
 		--nfreepools;
 		arenabase += POOL_SIZE - excess;

Modified: pypy/branch/py12/pypy/translator/c/test/test_genc.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/test/test_genc.py	(original)
+++ pypy/branch/py12/pypy/translator/c/test/test_genc.py	Sun May  2 18:05:10 2010
@@ -12,6 +12,7 @@
 from pypy.translator.gensupp import uniquemodulename
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.interactive import Translation
+from pypy.rlib.entrypoint import entrypoint
 
 def compile(fn, argtypes, view=False, gcpolicy="ref", backendopt=True,
             annotatorpolicy=None):
@@ -396,3 +397,85 @@
     if py.test.config.option.view:
         t.view()
     assert 'pypy_xyz_f' in t.driver.cbuilder.c_source_filename.read()
+
+def test_entrypoints():
+    def f():
+        return 3
+
+    key = "test_entrypoints42"
+    @entrypoint(key, [int], "foobar")
+    def g(x):
+        return x + 42
+
+    t = Translation(f, [], backend="c", secondaryentrypoints="test_entrypoints42")
+    t.annotate()
+    compiled_fn = t.compile_c()
+    if py.test.config.option.view:
+        t.view()
+    assert 'foobar' in t.driver.cbuilder.c_source_filename.read()
+
+def test_exportstruct():
+    from pypy.rlib.exports import export_struct
+    def f():
+        return 42
+    FOO = Struct("FOO", ("field1", Signed))
+    foo = malloc(FOO, flavor="raw")
+    foo.field1 = 43
+    export_struct("BarStruct", foo._obj)
+    t = Translation(f, [], backend="c")
+    t.annotate()
+    compiled_fn = t.compile_c()
+    if py.test.config.option.view:
+        t.view()
+    assert ' BarStruct ' in t.driver.cbuilder.c_source_filename.read()
+
+def test_recursive_llhelper():
+    from pypy.rpython.annlowlevel import llhelper
+    from pypy.rpython.lltypesystem import lltype
+    from pypy.rlib.objectmodel import specialize
+    from pypy.rlib.nonconst import NonConstant
+    FT = lltype.ForwardReference()
+    FTPTR = lltype.Ptr(FT)
+    STRUCT = lltype.Struct("foo", ("bar", FTPTR))
+    FT.become(lltype.FuncType([lltype.Ptr(STRUCT)], lltype.Signed))
+
+    class A:
+        def __init__(self, func, name):
+            self.func = func
+            self.name = name
+        def _freeze_(self):
+            return True
+        @specialize.memo()
+        def make_func(self):
+            f = getattr(self, "_f", None)
+            if f is not None:
+                return f
+            f = lambda *args: self.func(*args)
+            f.c_name = self.name
+            f.relax_sig_check = True
+            f.__name__ = "WRAP%s" % (self.name, )
+            self._f = f
+            return f
+        def get_llhelper(self):
+            return llhelper(FTPTR, self.make_func())
+    def f(s):
+        if s.bar == t.bar:
+            lltype.free(s, flavor="raw")
+            return 1
+        lltype.free(s, flavor="raw")
+        return 0
+    def g(x):
+        return 42
+    def chooser(x):
+        s = lltype.malloc(STRUCT, flavor="raw")
+        if x:
+            s.bar = llhelper(FTPTR, a_f.make_func())
+        else:
+            s.bar = llhelper(FTPTR, a_g.make_func())
+        return f(s)
+    a_f = A(f, "f")
+    a_g = A(g, "g")
+    t = lltype.malloc(STRUCT, flavor="raw")
+    t.bar = llhelper(FTPTR, a_f.make_func())
+    fn = compile(chooser, [bool])
+    assert fn(True)

Modified: pypy/branch/py12/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/branch/py12/pypy/translator/c/test/test_newgc.py	Sun May  2 18:05:10 2010
@@ -66,6 +66,12 @@
         for fullname in dir(cls):
             if not fullname.startswith('define'):
                 continue
+            keyword = conftest.option.keyword
+            if keyword:
+                if keyword.startswith('test_'):
+                    keyword = keyword[len('test_'):]
+                if keyword not in fullname:
+                    continue
             prefix, name = fullname.split('_', 1)
             definefunc = getattr(cls, fullname)
             func = definefunc.im_func(cls)

Modified: pypy/branch/py12/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/branch/py12/pypy/translator/c/test/test_standalone.py	Sun May  2 18:05:10 2010
@@ -16,11 +16,13 @@
 class StandaloneTests(object):
     config = None
 
-    def compile(self, entry_point, debug=True):
+    def compile(self, entry_point, debug=True, shared=False):
         t = TranslationContext(self.config)
         t.buildannotator().build_types(entry_point, [s_list_of_strings])
         t.buildrtyper().specialize()
 
+        t.config.translation.shared = shared
+
         cbuilder = CStandaloneBuilder(t, entry_point, t.config)
         if debug:
             cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
@@ -587,6 +589,19 @@
         # The traceback stops at f() because it's the first function that
         # captures the AssertionError, which makes the program abort.
 
+    def test_shared(self, monkeypatch):
+        def f(argv):
+            print len(argv)
+        def entry_point(argv):
+            f(argv)
+            return 0
+        t, cbuilder = self.compile(entry_point, shared=True)
+        assert cbuilder.shared_library_name is not None
+        assert cbuilder.shared_library_name != cbuilder.executable_name
+        monkeypatch.setenv('LD_LIBRARY_PATH',
+                           cbuilder.shared_library_name.dirpath())
+        out, err = cbuilder.cmdexec("a b")
+        assert out == "3"
 
 class TestMaemo(TestStandalone):
     def setup_class(cls):

Modified: pypy/branch/py12/pypy/translator/driver.py
==============================================================================
--- pypy/branch/py12/pypy/translator/driver.py	(original)
+++ pypy/branch/py12/pypy/translator/driver.py	Sun May  2 18:05:10 2010
@@ -12,6 +12,7 @@
 import optparse
 from pypy.tool.udir import udir
 from pypy.rlib.jit import DEBUG_OFF, DEBUG_DETAILED, DEBUG_PROFILE, DEBUG_STEPS
+from pypy.rlib.entrypoint import secondary_entrypoints
 
 import py
 from pypy.tool.ansi_print import ansi_log
@@ -93,7 +94,7 @@
 
         if setopts is not None:
             self.config.set(**setopts)
-        
+
         self.exe_name = exe_name
         self.extmod_name = extmod_name
 
@@ -210,12 +211,25 @@
         self.entry_point = entry_point
         self.translator = translator
         self.libdef = None
+        self.secondary_entrypoints = []
+
+        if self.config.translation.secondaryentrypoints:
+            for key in self.config.translation.secondaryentrypoints.split(","):
+                try:
+                    points = secondary_entrypoints[key]
+                except KeyError:
+                    raise KeyError(
+                        "Entrypoints not found. I only know the keys %r." %
+                        (", ".join(secondary_entrypoints.keys()), ))
+                self.secondary_entrypoints.extend(points)
 
         self.translator.driver_instrument_result = self.instrument_result
 
     def setup_library(self, libdef, policy=None, extra={}, empty_translator=None):
+        """ Used by carbon python only. """
         self.setup(None, None, policy, extra, empty_translator)
         self.libdef = libdef
+        self.secondary_entrypoints = libdef.functions
 
     def instrument_result(self, args):
         backend, ts = self.get_backend_and_type_system()
@@ -304,23 +318,26 @@
         annmodel.DEBUG = self.config.translation.debug
         annotator = translator.buildannotator(policy=policy)
 
+        if self.secondary_entrypoints is not None:
+            for func, inputtypes in self.secondary_entrypoints:
+                if inputtypes == Ellipsis:
+                    continue
+                rettype = annotator.build_types(func, inputtypes, False)
+
         if self.entry_point:
             s = annotator.build_types(self.entry_point, self.inputtypes)
-
-            self.sanity_check_annotation()
-            if self.standalone and s.knowntype != int:
-                raise Exception("stand-alone program entry point must return an "
-                                "int (and not, e.g., None or always raise an "
-                                "exception).")
-            annotator.simplify()
-            return s
+            translator.entry_point_graph = annotator.bookkeeper.getdesc(self.entry_point).getuniquegraph()
         else:
-            assert self.libdef is not None
-            for func, inputtypes in self.libdef.functions:
-                annotator.build_types(func, inputtypes)
-                func.c_name = func.func_name
-            self.sanity_check_annotation()
-            annotator.simplify()
+            s = None
+
+        self.sanity_check_annotation()
+        if self.entry_point and self.standalone and s.knowntype != int:
+            raise Exception("stand-alone program entry point must return an "
+                            "int (and not, e.g., None or always raise an "
+                            "exception).")
+        annotator.simplify()
+        return s
+
     #
     task_annotate = taskdef(task_annotate, [], "Annotating&simplifying")
 
@@ -471,7 +488,8 @@
             else:
                 from pypy.translator.c.genc import CExtModuleBuilder as CBuilder
             cbuilder = CBuilder(self.translator, self.entry_point,
-                                config=self.config)
+                                config=self.config,
+                                secondary_entrypoints=self.secondary_entrypoints)
             cbuilder.stackless = self.config.translation.stackless
         if not standalone:     # xxx more messy
             cbuilder.modulename = self.extmod_name
@@ -521,6 +539,10 @@
             exename = mkexename(self.c_entryp)
             newexename = self.compute_exe_name()
             shutil.copy(str(exename), str(newexename))
+            if self.cbuilder.shared_library_name is not None:
+                soname = self.cbuilder.shared_library_name
+                newsoname = newexename.new(basename=soname.basename)
+                shutil.copy(str(soname), str(newsoname))
             self.c_entryp = newexename
         self.log.info("created: %s" % (self.c_entryp,))
 
@@ -529,7 +551,10 @@
         translator/platform
         """
         cbuilder = self.cbuilder
-        cbuilder.compile()
+        kwds = {}
+        if self.standalone and self.exe_name is not None:
+            kwds['exe_name'] = self.compute_exe_name().basename
+        cbuilder.compile(**kwds)
 
         if self.standalone:
             self.c_entryp = cbuilder.executable_name

Modified: pypy/branch/py12/pypy/translator/goal/ann_override.py
==============================================================================
--- pypy/branch/py12/pypy/translator/goal/ann_override.py	(original)
+++ pypy/branch/py12/pypy/translator/goal/ann_override.py	Sun May  2 18:05:10 2010
@@ -81,7 +81,7 @@
     
     def attach_lookup(pol, t, attr):
         cached = "cached_%s" % attr
-        if not t.is_heaptype():
+        if not t.is_heaptype() and not t.is_cpytype():
             pol._remember_immutable(t, cached)
             setattr(t, cached, t._lookup(attr))
             return True
@@ -89,7 +89,7 @@
 
     def attach_lookup_in_type_where(pol, t, attr):
         cached = "cached_where_%s" % attr
-        if not t.is_heaptype():
+        if not t.is_heaptype() and not t.is_cpytype():
             pol._remember_immutable(t, cached)
             setattr(t, cached, t._lookup_where(attr))
             return True
@@ -177,14 +177,14 @@
 CACHED_LOOKUP = """
 def lookup_%(attr)s(space, w_obj, name):
     w_type = space.type(w_obj)
-    if not w_type.is_heaptype():
+    if not w_type.is_heaptype() and not w_type.is_cpytype():
         return w_type.cached_%(attr)s
     return w_type.lookup("%(attr)s")
 """
 
 CACHED_LOOKUP_IN_TYPE_WHERE = """
 def lookup_in_type_where_%(attr)s(space, w_type, name):
-    if not w_type.is_heaptype():
+    if not w_type.is_heaptype() and not w_type.is_cpytype():
         return w_type.cached_where_%(attr)s
     return w_type.lookup_where("%(attr)s")
 """

Modified: pypy/branch/py12/pypy/translator/platform/__init__.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/__init__.py	(original)
+++ pypy/branch/py12/pypy/translator/platform/__init__.py	Sun May  2 18:05:10 2010
@@ -69,7 +69,8 @@
                                                      env)
         return ExecutionResult(returncode, stdout, stderr)
 
-    def gen_makefile(self, cfiles, eci, exe_name=None, path=None):
+    def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
+                     shared=False):
         raise NotImplementedError("Pure abstract baseclass")
 
     def __repr__(self):
@@ -104,10 +105,8 @@
             errorfile = outname.new(ext='errors')
             errorfile.write(stderr, 'wb')
             stderrlines = stderr.splitlines()
-            for line in stderrlines[:50]:
+            for line in stderrlines:
                 log.ERROR(line)
-            if len(stderrlines) > 50:
-                log.ERROR('...')
             raise CompilationError(stdout, stderr)
         else:
             for line in stderr.splitlines():

Modified: pypy/branch/py12/pypy/translator/platform/darwin.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/darwin.py	(original)
+++ pypy/branch/py12/pypy/translator/platform/darwin.py	Sun May  2 18:05:10 2010
@@ -18,7 +18,7 @@
         self.cc = cc
 
     def _args_for_shared(self, args):
-        return (self.shared_only + ['-bundle', '-undefined', 'dynamic_lookup']
+        return (self.shared_only + ['-dynamiclib', '-undefined', 'dynamic_lookup']
                                  + args)
 
     def include_dirs_for_libffi(self):

Modified: pypy/branch/py12/pypy/translator/platform/linux.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/linux.py	(original)
+++ pypy/branch/py12/pypy/translator/platform/linux.py	Sun May  2 18:05:10 2010
@@ -7,7 +7,7 @@
     name = "linux"
     
     link_flags = ['-pthread', '-lrt']
-    cflags = ['-O3', '-pthread', '-fomit-frame-pointer', '-Wall']
+    cflags = ['-O3', '-pthread', '-fomit-frame-pointer', '-Wall', '-Wno-unused']
     standalone_only = []
     shared_only = ['-fPIC']
     so_ext = 'so'

Modified: pypy/branch/py12/pypy/translator/platform/posix.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/posix.py	(original)
+++ pypy/branch/py12/pypy/translator/platform/posix.py	Sun May  2 18:05:10 2010
@@ -36,6 +36,10 @@
                                  cwd=str(cfile.dirpath()))
         return oname
 
+    def _link_args_from_eci(self, eci, standalone):
+        eci = eci.convert_exportsymbols_to_file()
+        return Platform._link_args_from_eci(self, eci, standalone)
+
     def _link(self, cc, ofiles, link_args, standalone, exe_name):
         args = [str(ofile) for ofile in ofiles] + link_args
         args += ['-o', str(exe_name)]
@@ -55,7 +59,9 @@
         # strip compiler flags
         return [entry[2:] for entry in out.split()]
 
-    def gen_makefile(self, cfiles, eci, exe_name=None, path=None):
+    def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
+                     shared=False):
+        eci = eci.convert_exportsymbols_to_file()
         cfiles = [py.path.local(f) for f in cfiles]
         cfiles += [py.path.local(f) for f in eci.separate_module_files]
 
@@ -67,6 +73,16 @@
         if exe_name is None:
             exe_name = cfiles[0].new(ext=self.exe_ext)
 
+        linkflags = self.link_flags
+        if shared:
+            linkflags = self._args_for_shared(linkflags)
+
+        if shared:
+            libname = exe_name.new(ext='').basename
+            target_name = 'lib' + exe_name.new(ext=self.so_ext).basename
+        else:
+            target_name = exe_name.basename
+
         m = GnuMakefile(path)
         m.exe_name = exe_name
         m.eci = eci
@@ -88,8 +104,8 @@
         m.comment('automatically generated makefile')
         definitions = [
             ('PYPYDIR', autopath.pypydir),
-            ('TARGET', exe_name.basename),
-            ('DEFAULT_TARGET', '$(TARGET)'),
+            ('TARGET', target_name),
+            ('DEFAULT_TARGET', exe_name.basename),
             ('SOURCES', rel_cfiles),
             ('OBJECTS', rel_ofiles),
             ('LIBS', self._libs(eci.libraries)),
@@ -97,7 +113,7 @@
             ('INCLUDEDIRS', self._includedirs(rel_includedirs)),
             ('CFLAGS', self.cflags),
             ('CFLAGSEXTRA', list(eci.compile_extra)),
-            ('LDFLAGS', self.link_flags),
+            ('LDFLAGS', linkflags),
             ('LDFLAGSEXTRA', list(eci.link_extra)),
             ('CC', self.cc),
             ('CC_LINK', eci.use_cpp_linker and 'g++' or '$(CC)'),
@@ -115,6 +131,16 @@
         for rule in rules:
             m.rule(*rule)
 
+        if shared:
+            m.definition('SHARED_IMPORT_LIB', libname),
+            m.rule('main.c', '',
+                   'echo "'
+                   'int $(PYPY_MAIN_FUNCTION)(int, char*[]); '
+                   'int main(int argc, char* argv[]) '
+                   '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); }" > $@')
+            m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.o'],
+                   '$(CC_LINK) main.o -L. -l$(SHARED_IMPORT_LIB) -o $@')
+
         return m
 
     def execute_makefile(self, path_to_makefile, extra_opts=[]):

Modified: pypy/branch/py12/pypy/translator/platform/windows.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/windows.py	(original)
+++ pypy/branch/py12/pypy/translator/platform/windows.py	Sun May  2 18:05:10 2010
@@ -186,7 +186,8 @@
             raise CompilationError(stdout, stderr)
 
 
-    def gen_makefile(self, cfiles, eci, exe_name=None, path=None):
+    def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
+                     shared=False):
         cfiles = [py.path.local(f) for f in cfiles]
         cfiles += [py.path.local(f) for f in eci.separate_module_files]
 
@@ -202,6 +203,17 @@
         m.exe_name = exe_name
         m.eci = eci
 
+        linkflags = self.link_flags
+        if shared:
+            linkflags = self._args_for_shared(linkflags) + [
+                '/EXPORT:$(PYPY_MAIN_FUNCTION)']
+
+        if shared:
+            so_name = exe_name.new(ext=self.so_ext)
+            target_name = so_name.basename
+        else:
+            target_name = exe_name.basename
+
         def pypyrel(fpath):
             rel = py.path.local(fpath).relto(pypypath)
             if rel:
@@ -218,8 +230,8 @@
         m.comment('automatically generated makefile')
         definitions = [
             ('PYPYDIR', autopath.pypydir),
-            ('TARGET', exe_name.basename),
-            ('DEFAULT_TARGET', '$(TARGET)'),
+            ('TARGET', target_name),
+            ('DEFAULT_TARGET', exe_name.basename),
             ('SOURCES', rel_cfiles),
             ('OBJECTS', rel_ofiles),
             ('LIBS', self._libs(eci.libraries)),
@@ -227,12 +239,13 @@
             ('INCLUDEDIRS', self._includedirs(rel_includedirs)),
             ('CFLAGS', self.cflags),
             ('CFLAGSEXTRA', list(eci.compile_extra)),
-            ('LDFLAGS', self.link_flags),
+            ('LDFLAGS', linkflags),
             ('LDFLAGSEXTRA', list(eci.link_extra)),
             ('CC', self.cc),
             ('CC_LINK', self.link),
             ('MASM', self.masm),
             ]
+
         for args in definitions:
             m.definition(*args)
 
@@ -253,6 +266,16 @@
                     'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1',
                     ])
 
+        if shared:
+            m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename),
+            m.rule('main.c', '',
+                   'echo '
+                   'int $(PYPY_MAIN_FUNCTION)(int, char*[]); '
+                   'int main(int argc, char* argv[]) '
+                   '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); } > $@')
+            m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.obj'],
+                   '$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@')
+
         return m
 
     def execute_makefile(self, path_to_makefile, extra_opts=[]):

Modified: pypy/branch/py12/pypy/translator/test/test_unsimplify.py
==============================================================================
--- pypy/branch/py12/pypy/translator/test/test_unsimplify.py	(original)
+++ pypy/branch/py12/pypy/translator/test/test_unsimplify.py	Sun May  2 18:05:10 2010
@@ -9,6 +9,7 @@
 def translate(func, argtypes, type_system="lltype"):
     t = TranslationContext()
     t.buildannotator().build_types(func, argtypes)
+    t.entry_point_graph = graphof(t, func)
     t.buildrtyper(type_system=type_system).specialize()
     return graphof(t, func), t
 

Modified: pypy/branch/py12/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/branch/py12/pypy/translator/tool/cbuild.py	(original)
+++ pypy/branch/py12/pypy/translator/tool/cbuild.py	Sun May  2 18:05:10 2010
@@ -260,24 +260,49 @@
         d['separate_module_files'] += tuple(files)
         return ExternalCompilationInfo(**d)
 
+    def convert_exportsymbols_to_file(self):
+        if not self.export_symbols:
+            return self
+        num = 0
+        while 1:
+            file_name = udir.join('dynamic-symbols-%i' % num)
+            num += 1
+            if not file_name.check():
+                break
+
+        f = file_name.open("w")
+        f.write("{\n")
+        for sym in self.export_symbols:
+            f.write("%s;\n" % (sym,))
+        f.write("};")
+        f.close()
+        d = self._copy_attributes()
+        d['link_extra'] += ("-Wl,--dynamic-list=" + str(file_name), )
+        d['export_symbols'] = ()
+        return ExternalCompilationInfo(**d)
+
+
     def get_module_files(self):
         d = self._copy_attributes()
         files = d['separate_module_files']
         d['separate_module_files'] = ()
         return files, ExternalCompilationInfo(**d)
 
-    def compile_shared_lib(self):
+    def compile_shared_lib(self, outputfilename=None):
         self = self.convert_sources_to_files()
         if not self.separate_module_files:
             return self
-        # find more or less unique name there
-        basepath = py.path.local(self.separate_module_files[0]).dirpath()
-        pth = basepath.join('externmod').new(ext=host.so_ext)
-        num = 0
-        while pth.check():
-            pth = basepath.join('externmod_%d' % (num,)).new(ext=host.so_ext)
-            num += 1
-        lib = str(host.compile([], self, outputfilename=pth.purebasename,
+        if outputfilename is None:
+            # find more or less unique name there
+            basepath = py.path.local(self.separate_module_files[0]).dirpath()
+            pth = basepath.join('externmod').new(ext=host.so_ext)
+            num = 0
+            while pth.check():
+                pth = basepath.join(
+                    'externmod_%d' % (num,)).new(ext=host.so_ext)
+                num += 1
+            outputfilename=pth.purebasename
+        lib = str(host.compile([], self, outputfilename=outputfilename,
                                standalone=False))
         d = self._copy_attributes()
         d['libraries'] += (lib,)

Modified: pypy/branch/py12/pypy/translator/tool/test/test_cbuild.py
==============================================================================
--- pypy/branch/py12/pypy/translator/tool/test/test_cbuild.py	(original)
+++ pypy/branch/py12/pypy/translator/tool/test/test_cbuild.py	Sun May  2 18:05:10 2010
@@ -71,6 +71,17 @@
         e = ExternalCompilationInfo()
         assert e.convert_sources_to_files() is e
 
+    def test_convert_sources_to_c_files(self):
+        eci = ExternalCompilationInfo(
+                export_symbols=("foo", )
+        )
+        neweci = eci.convert_exportsymbols_to_file()
+        le = neweci.link_extra[-1]
+        assert "foo;" in file(le.rsplit("=", 1)[1]).read()
+        e = ExternalCompilationInfo()
+        assert e.convert_exportsymbols_to_file() is e
+
+
     def test_make_shared_lib(self):
         eci = ExternalCompilationInfo(
             separate_module_sources = ['''

Modified: pypy/branch/py12/pypy/translator/unsimplify.py
==============================================================================
--- pypy/branch/py12/pypy/translator/unsimplify.py	(original)
+++ pypy/branch/py12/pypy/translator/unsimplify.py	Sun May  2 18:05:10 2010
@@ -168,7 +168,7 @@
     if own_annhelper:
         annhelper.finish()
 
-    entry_point = translator.graphs[0]
+    entry_point = translator.entry_point_graph
     v = copyvar(translator.annotator, entry_point.getreturnvar())
     extrablock = Block([v])
     v_none = varoftype(lltype.Void)



More information about the Pypy-commit mailing list