[pypy-svn] r45656 - in pypy/branch/pypy-more-rtti-inprogress: . module/posix rlib rpython rpython/lltypesystem rpython/lltypesystem/module rpython/module rpython/module/test rpython/ootypesystem/module rpython/test translator translator/c translator/c/src translator/c/test translator/sandbox translator/sandbox/test

arigo at codespeak.net arigo at codespeak.net
Tue Aug 14 18:10:46 CEST 2007


Author: arigo
Date: Tue Aug 14 18:10:44 2007
New Revision: 45656

Added:
   pypy/branch/pypy-more-rtti-inprogress/
      - copied from r45507, pypy/dist/pypy/
Modified:
   pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py
   pypy/branch/pypy-more-rtti-inprogress/rlib/ros.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_math.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_os.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_path.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/module/support.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os_path.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/rbuiltin.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rptr.py
   pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py
   pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py
   pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_math.h
   pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h
   pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py
   pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/interact.py
   pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py
   pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py
   pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py
   pypy/branch/pypy-more-rtti-inprogress/translator/translator.py
Log:
For backup purposes, in-progress: convert more of the os module to rtti
and try to get rid of the rllib.ros module by making the native
interfaces RPythonic.  This looks quite good in my opinion - seems that
we've finally learned a reasonable way to do external functions.



Modified: pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py
==============================================================================
--- pypy/dist/pypy/module/posix/interp_posix.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/module/posix/interp_posix.py	Tue Aug 14 18:10:44 2007
@@ -445,7 +445,7 @@
     """
     if space.is_w(w_tuple, space.w_None):
         try:
-            ros.utime_null(path)
+            os.utime(path, None)
             return
         except OSError, e:
             raise wrap_oserror(space, e)
@@ -456,7 +456,7 @@
             raise OperationError(space.w_TypeError, space.wrap(msg))
         actime = space.float_w(args_w[0])
         modtime = space.float_w(args_w[1])
-        ros.utime_tuple(path, (actime, modtime))
+        os.utime(path, (actime, modtime))
     except OSError, e:
         raise wrap_oserror(space, e)
     except OperationError, e:

Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/ros.py
==============================================================================
--- pypy/dist/pypy/rlib/ros.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rlib/ros.py	Tue Aug 14 18:10:44 2007
@@ -54,11 +54,3 @@
 def opendir(dirname):
     return DIR(dirname)
 opendir._annenforceargs_ = (str,)
-
-# probably we can get an annotation support for not having both implementations
-# here, but let's leave it for now
-def utime_null(path):
-    os.utime(path, None)
-
-def utime_tuple(path, tp):
-    os.utime(path, tp)

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunc.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunc.py	Tue Aug 14 18:10:44 2007
@@ -88,31 +88,13 @@
     def compute_result_annotation(self, *args_s):
         if hasattr(self, 'ann_hook'):
             self.ann_hook()
-        if self.signature_args is not None:
-            assert len(args_s) == len(self.signature_args),\
-                   "Argument number mismatch"
-            for i, expected in enumerate(self.signature_args):
-                arg = unionof(args_s[i], expected)
-                if not expected.contains(arg):
-                    name = getattr(self, 'name', None)
-                    if not name:
-                        try:
-                            name = self.instance.__name__
-                        except AttributeError:
-                            name = '?'
-                    raise Exception("In call to external function %r:\n"
-                                    "arg %d must be %s,\n"
-                                    "          got %s" % (
-                        name, i+1, expected, args_s[i]))
+        self.normalize_args(*args_s)   # check arguments
         return self.signature_result
 
     def specialize_call(self, hop):
         rtyper = hop.rtyper
-        if self.signature_args is None:
-            iter_args = hop.args_s
-        else:
-            iter_args = self.signature_args
-        args_r = [rtyper.getrepr(s_arg) for s_arg in iter_args]
+        signature_args = self.normalize_args(*hop.args_s)
+        args_r = [rtyper.getrepr(s_arg) for s_arg in signature_args]
         args_ll = [r_arg.lowleveltype for r_arg in args_r]
         r_result = rtyper.getrepr(hop.s_result)
         ll_result = r_result.lowleveltype
@@ -123,8 +105,12 @@
         fakeimpl = getattr(self, fake_method_name, self.instance)
         if impl:
             obj = rtyper.getannmixlevel().delayedfunction(
-                impl, self.signature_args, hop.s_result)
+                impl, signature_args, hop.s_result)
         else:
+            #if not self.safe_not_sandboxed:
+            #    print '>>>>>>>>>>>>>-----------------------------------'
+            #    print name, self.name
+            #    print '<<<<<<<<<<<<<-----------------------------------'
             obj = rtyper.type_system.getexternalcallable(args_ll, ll_result,
                                  name, _external_name=self.name, _callable=fakeimpl,
                                  _safe_not_sandboxed=self.safe_not_sandboxed)
@@ -151,10 +137,36 @@
     class FunEntry(ExtFuncEntry):
         _about_ = function
         safe_not_sandboxed = sandboxsafe
+
         if args is None:
-            signature_args = None
+            def normalize_args(self, *args_s):
+                return args_s    # accept any argument unmodified
+
+        elif callable(args):
+            # custom annotation normalizer (see e.g. os.utime())
+            normalize_args = staticmethod(args)
+
         else:
-            signature_args = [annotation(arg, None) for arg in args]
+            # common case: args is a list of annotation or types
+            def normalize_args(self, *args_s):
+                signature_args = [annotation(arg, None) for arg in args]
+                assert len(args_s) == len(signature_args),\
+                       "Argument number mismatch"
+                for i, expected in enumerate(signature_args):
+                    arg = unionof(args_s[i], expected)
+                    if not expected.contains(arg):
+                        name = getattr(self, 'name', None)
+                        if not name:
+                            try:
+                                name = self.instance.__name__
+                            except AttributeError:
+                                name = '?'
+                        raise Exception("In call to external function %r:\n"
+                                        "arg %d must be %s,\n"
+                                        "          got %s" % (
+                            name, i+1, expected, args_s[i]))
+                return signature_args
+
         signature_result = annotation(result, None)
         name=export_name
         if llimpl:

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py
==============================================================================
--- pypy/dist/pypy/rpython/extfuncregistry.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfuncregistry.py	Tue Aug 14 18:10:44 2007
@@ -27,35 +27,22 @@
     _register_external(getattr(math, name), [float], float, "ll_math.ll_math_%s" % name,
                        sandboxsafe=True)
 
-def frexp_hook():
-    from pypy.rpython.extfunctable import record_call
-    from pypy.annotation.model import SomeInteger, SomeTuple, SomeFloat
-    from pypy.rpython.lltypesystem.module.ll_math import ll_frexp_result
-    record_call(ll_frexp_result, (SomeFloat(), SomeInteger()), 'MATH_FREXP')
-
-def modf_hook():
-    from pypy.rpython.extfunctable import record_call
-    from pypy.annotation.model import SomeTuple, SomeFloat
-    from pypy.rpython.lltypesystem.module.ll_math import ll_modf_result
-    record_call(ll_modf_result, (SomeFloat(), SomeFloat()), 'MATH_MODF')
-
 complex_math_functions = [
-    ('frexp', [float],        (float, int),   frexp_hook),
-    ('atan2', [float, float], float,          None),
-    ('fmod',  [float, float], float,          None),
-    ('ldexp', [float, int],   float,          None),
-    ('modf',  [float],        (float, float), modf_hook),
-    ('hypot', [float, float], float,          None),
-    ('pow',   [float, float], float,          None),
+    ('frexp', [float],        (float, int)),
+    ('atan2', [float, float], float),
+    ('fmod',  [float, float], float),
+    ('ldexp', [float, int],   float),
+    ('modf',  [float],        (float, float)),
+    ('hypot', [float, float], float),
+    ('pow',   [float, float], float),
     ]
 
-for name, args, res, hook in complex_math_functions:
+for name, args, res in complex_math_functions:
     func = getattr(math, name)
-    llfake = getattr(ll_math, 'll_math_%s' % name, None)
+    llimpl = getattr(ll_math, 'll_math_%s' % name, None)
     oofake = getattr(oo_math, 'll_math_%s' % name, None)
     _register_external(func, args, res, 'll_math.ll_math_%s' % name,
-                       llfakeimpl=llfake, oofakeimpl=oofake,
-                       annotation_hook = hook,
+                       llimpl=llimpl, oofakeimpl=oofake,
                        sandboxsafe=True)
 
 

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/extfunctable.py	Tue Aug 14 18:10:44 2007
@@ -137,16 +137,6 @@
 
 # _____________________________________________________________
 
-def record_call(func, args_s, symbol):
-    from pypy.annotation import bookkeeper
-    bk = bookkeeper.getbookkeeper()
-    # this would be nice!
-    #bk.pbc_call(bk.immutablevalue(func),
-    #            bk.build_args("simple_call", args_s),
-    #            emulated=True)
-    bk.annotator.translator._implicitly_called_by_externals.append(
-        (func, args_s, symbol))
-
 def noneannotation(*args):
     return None
 
@@ -154,25 +144,6 @@
     from pypy.annotation.model import SomeInteger
     return SomeInteger(nonneg=True)
 
-def statannotation(*args):
-    from pypy.rpython.lltypesystem.module.ll_os import Implementation
-    from pypy.annotation.model import SomeInteger, SomeTuple
-    record_call(Implementation.ll_stat_result, [SomeInteger()]*10, 'OS_STAT')
-    return SomeTuple((SomeInteger(),)*10)
-
-def pipeannotation(*args):
-    from pypy.rpython.lltypesystem.module.ll_os import Implementation
-    from pypy.annotation.model import SomeInteger, SomeTuple
-    record_call(Implementation.ll_pipe_result, [SomeInteger()]*2, 'OS_PIPE')
-    return SomeTuple((SomeInteger(),)*2)
-
-def waitpidannotation(*args):
-    from pypy.rpython.lltypesystem.module.ll_os import Implementation
-    from pypy.annotation.model import SomeInteger, SomeTuple
-    record_call(Implementation.ll_waitpid_result, [SomeInteger()]*2,
-                'OS_WAITPID')
-    return SomeTuple((SomeInteger(),)*2)
-
 def strnullannotation(*args):
     from pypy.annotation.model import SomeString
     return SomeString(can_be_None=True)
@@ -183,9 +154,6 @@
 declare(os.isatty   , bool          , 'll_os/isatty')
 if hasattr(posix, 'ftruncate'):
     declare(os.ftruncate, noneannotation, 'll_os/ftruncate')
-declare(os.fstat    , statannotation, 'll_os/fstat')
-declare(os.stat     , statannotation, 'll_os/stat')
-declare(os.lstat    , statannotation, 'll_os/lstat')
 declare(os.system   , int           , 'll_os/system')
 declare(os.strerror , str           , 'll_os/strerror')
 declare(os.unlink   , noneannotation, 'll_os/unlink')
@@ -194,7 +162,6 @@
 declare(os.rmdir    , noneannotation, 'll_os/rmdir')
 if hasattr(posix, 'unsetenv'):   # note: faked in os
     declare(os.unsetenv , noneannotation, 'll_os/unsetenv')
-declare(os.pipe     , pipeannotation, 'll_os/pipe')
 declare(os.chmod    , noneannotation, 'll_os/chmod')
 declare(os.rename   , noneannotation, 'll_os/rename')
 declare(os.umask    , int           , 'll_os/umask')
@@ -205,14 +172,10 @@
     declare(os.link     , noneannotation, 'll_os/link')
 if hasattr(os, 'symlink'):
     declare(os.symlink  , noneannotation, 'll_os/symlink')
-if hasattr(os, 'readlink'):
-    declare(os.readlink , str,            'll_os/readlink')
 if hasattr(os, 'fork'):
     declare(os.fork ,     int,            'll_os/fork')
 if hasattr(os, 'spawnv'):
     declare(os.spawnv,    int,            'll_os/spawnv')
-if hasattr(os, 'waitpid'):
-    declare(os.waitpid ,  waitpidannotation, 'll_os/waitpid')
 #if hasattr(os, 'execv'):
 #    declare(os.execv, noneannotation, 'll_os/execv')
 #    declare(os.execve, noneannotation, 'll_os/execve')

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/llinterp.py	Tue Aug 14 18:10:44 2007
@@ -439,8 +439,12 @@
             return obj._callable(*args)
         except LLException, e:
             raise
-        except Exception:
+        except Exception, e:
             if getattr(obj, '_debugexc', False):
+                log.ERROR('The llinterpreter got an '
+                          'unexpected exception when calling')
+                log.ERROR('the external function %r:' % (fptr,))
+                log.ERROR('%s: %s' % (e.__class__.__name__, e))
                 import sys
                 from pypy.translator.tool.pdbplus import PdbPlusShow
                 PdbPlusShow(None).post_mortem(sys.exc_info()[2])

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/ll2ctypes.py	Tue Aug 14 18:10:44 2007
@@ -449,7 +449,7 @@
     if cfunc is None:
         # function name not found in any of the libraries
         if not libraries:
-            place = 'the standard C library'
+            place = 'the standard C library (missing libraries=...?)'
         elif len(libraries) == 1:
             place = 'library %r' % (libraries[0],)
         else:

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_math.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/module/ll_math.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_math.py	Tue Aug 14 18:10:44 2007
@@ -1,25 +1,21 @@
 import math
-from pypy.rpython.lltypesystem import lltype, rtupletype
+from pypy.rpython.lltypesystem import lltype, rffi
 
-FREXP_RESULT = rtupletype.TUPLE_TYPE([lltype.Float, lltype.Signed]).TO
-MODF_RESULT = rtupletype.TUPLE_TYPE([lltype.Float, lltype.Float]).TO
-
-def ll_frexp_result(mantissa, exponent):
-    tup = lltype.malloc(FREXP_RESULT)
-    tup.item0 = mantissa
-    tup.item1 = exponent
-    return tup
-
-def ll_modf_result(fracpart, intpart):
-    tup = lltype.malloc(MODF_RESULT)
-    tup.item0 = fracpart
-    tup.item1 = intpart
-    return tup
+math_frexp = rffi.llexternal('frexp', [rffi.DOUBLE, rffi.INTP], rffi.DOUBLE,
+                             sandboxsafe=True)
+math_modf  = rffi.llexternal('modf',  [rffi.DOUBLE, rffi.DOUBLEP], rffi.DOUBLE,
+                             sandboxsafe=True)
 
 def ll_math_frexp(x):
-    mantissa, exponent = math.frexp(x)
-    return ll_frexp_result(mantissa, exponent)
+    exp_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+    mantissa = math_frexp(x, exp_p)
+    exponent = rffi.cast(lltype.Signed, exp_p[0])
+    lltype.free(exp_p, flavor='raw')
+    return (mantissa, exponent)
 
 def ll_math_modf(x):
-    fracpart, intpart = math.modf(x)
-    return ll_modf_result(fracpart, intpart)
+    intpart_p = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw')
+    fracpart = math_modf(x, intpart_p)
+    intpart = intpart_p[0]
+    lltype.free(intpart_p, flavor='raw')
+    return (fracpart, intpart)

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/module/ll_os.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/module/ll_os.py	Tue Aug 14 18:10:44 2007
@@ -1,55 +1,7 @@
-import os, errno
+# mostly-deprecated module
+
 from pypy.rpython.module.support import LLSupport
-from pypy.rpython.module.support import ll_strcpy
 from pypy.rpython.module.ll_os import BaseOS
-from pypy.rpython.lltypesystem import lltype, rtupletype
-from pypy.rlib.rarithmetic import intmask
-
-STAT_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*10).TO
-PIPE_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*2).TO
-WAITPID_RESULT = rtupletype.TUPLE_TYPE([lltype.Signed]*2).TO
 
 class Implementation(BaseOS, LLSupport):
-    
-    def ll_stat_result(stat0, stat1, stat2, stat3, stat4,
-                       stat5, stat6, stat7, stat8, stat9):
-        tup = lltype.malloc(STAT_RESULT)
-        tup.item0 = intmask(stat0)
-        tup.item1 = intmask(stat1)
-        tup.item2 = intmask(stat2)
-        tup.item3 = intmask(stat3)
-        tup.item4 = intmask(stat4)
-        tup.item5 = intmask(stat5)
-        tup.item6 = intmask(stat6)
-        tup.item7 = intmask(stat7)
-        tup.item8 = intmask(stat8)
-        tup.item9 = intmask(stat9)
-        return tup
-    ll_stat_result = staticmethod(ll_stat_result)
-
-    def ll_pipe_result(fd1, fd2):
-        tup = lltype.malloc(PIPE_RESULT)
-        tup.item0 = fd1
-        tup.item1 = fd2
-        return tup
-    ll_pipe_result = staticmethod(ll_pipe_result)
-
-    def ll_os_readlink(cls, path):
-        from pypy.rpython.lltypesystem.rstr import mallocstr
-        bufsize = 1023
-        while 1:
-            buffer = mallocstr(bufsize)
-            n = cls.ll_readlink_into(cls, path, buffer)
-            if n < bufsize:
-                break
-            bufsize *= 4     # overflow, try again with a bigger buffer
-        s = mallocstr(n)
-        ll_strcpy(s, buffer, n)
-        return s
-
-    def ll_waitpid_result(fd1, fd2):
-        tup = lltype.malloc(WAITPID_RESULT)
-        tup.item0 = fd1
-        tup.item1 = fd2
-        return tup
-    ll_waitpid_result = staticmethod(ll_waitpid_result)
+    pass

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/lltypesystem/rffi.py	Tue Aug 14 18:10:44 2007
@@ -22,14 +22,16 @@
         return self.TP
 
 def llexternal(name, args, result, _callable=None, sources=[], includes=[],
-               libraries=[], include_dirs=[]):
+               libraries=[], include_dirs=[], sandboxsafe=False):
     ext_type = lltype.FuncType(args, result)
     funcptr = lltype.functionptr(ext_type, name, external='C',
                                  sources=tuple(sources),
                                  includes=tuple(includes),
                                  libraries=tuple(libraries),
                                  include_dirs=tuple(include_dirs),
-                                 _callable=_callable)
+                                 _callable=_callable,
+                                 _safe_not_sandboxed=sandboxsafe,
+                                 _debugexc=True)  # on top of llinterp
     if _callable is None:
         ll2ctypes.make_callable_via_ctypes(funcptr)
     return funcptr
@@ -145,6 +147,9 @@
 # int *
 INTP = lltype.Ptr(lltype.Array(lltype.Signed, hints={'nolength': True}))
 
+# double *
+DOUBLEP = lltype.Ptr(lltype.Array(DOUBLE, hints={'nolength': True}))
+
 # various type mapping
 # str -> char*
 def str2charp(s):

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_os.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os.py	Tue Aug 14 18:10:44 2007
@@ -6,16 +6,16 @@
 # might be found in doc/rffi.txt
 
 import os, sys, errno
-from pypy.rpython.module.support import ll_strcpy, _ll_strfill, OOSupport
+from pypy.rpython.module.support import ll_strcpy, OOSupport
 from pypy.rpython.module.support import to_opaque_object, from_opaque_object
+from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib import ros
 from pypy.rlib.rarithmetic import r_longlong
 from pypy.tool.staticmethods import ClassMethods
 import stat
 from pypy.rpython.extfunc import BaseLazyRegistering, registering
-from pypy.annotation.model import SomeString, SomeInteger
+from pypy.annotation.model import SomeInteger, SomeString, SomeTuple, SomeFloat
 from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool
-from pypy.annotation.listdef import s_list_of_strings
 from pypy.rpython.lltypesystem import rffi
 from pypy.rpython.lltypesystem.rffi import platform
 from pypy.rpython.lltypesystem import lltype
@@ -89,37 +89,57 @@
                                  ('modtime', TIME_T))
 
         # XXX sys/types.h is not portable at all
-        ros_utime = rffi.llexternal('utime', [rffi.CCHARP, UTIMEBUFP],
-                                    rffi.INT,
-                                    includes=['utime.h', 'sys/types.h'])
+        os_utime = rffi.llexternal('utime', [rffi.CCHARP, UTIMEBUFP],
+                                   rffi.INT,
+                                   includes=['utime.h', 'sys/types.h'])
 
-        def utime_null_lltypeimpl(path):
-            l_path = rffi.str2charp(path)
-            error = rffi.cast(lltype.Signed, ros_utime(l_path,
-                              lltype.nullptr(UTIMEBUFP.TO)))
-            rffi.free_charp(l_path)
-            if error == -1:
-                raise OSError(rffi.get_errno(), "utime_null failed")
-            
-        self.register(ros.utime_null, [str], s_None, "ll_os.utime_null",
-                      llimpl=utime_null_lltypeimpl)
-
-        def utime_tuple_lltypeimpl(path, tp):
+        def os_utime_lltypeimpl(path, tp):
             # XXX right now they're all ints, might change in future
             # XXX does not use utimes, even when available
+            # NB. this function is specialized; we get one version where
+            # tp is known to be None, and one version where it is known
+            # to be a tuple of 2 floats.
             l_path = rffi.str2charp(path)
-            l_utimebuf = lltype.malloc(UTIMEBUFP.TO, flavor='raw')
-            actime, modtime = tp
-            l_utimebuf.c_actime, l_utimebuf.c_modtime = int(actime), int(modtime)
-            error = rffi.cast(lltype.Signed, ros_utime(l_path, l_utimebuf))
+            if tp is None:
+                l_utimebuf = lltype.nullptr(UTIMEBUFP.TO)
+            else:
+                l_utimebuf = lltype.malloc(UTIMEBUFP.TO, flavor='raw')
+                actime, modtime = tp
+                l_utimebuf.c_actime  = int(actime)
+                l_utimebuf.c_modtime = int(modtime)
+            error = rffi.cast(lltype.Signed, os_utime(l_path, l_utimebuf))
+            if tp is not None:
+                lltype.free(l_utimebuf, flavor='raw')
             rffi.free_charp(l_path)
-            lltype.free(l_utimebuf, flavor='raw')
             if error == -1:
-                raise OSError(rffi.get_errno(), "utime_tuple failed")
-        
-        self.register(ros.utime_tuple, [str, (float, float)], s_None,
-                      "ll_os.utime_tuple",
-                      llimpl=utime_tuple_lltypeimpl)
+                raise OSError(rffi.get_errno(), "os_utime failed")
+        os_utime_lltypeimpl._annspecialcase_ = 'specialize:argtype(1)'
+
+        s_string = SomeString()
+        s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()])
+
+        def os_utime_normalize_args(s_path, s_times):
+            # special handling of the arguments: they can be either
+            # [str, (float, float)] or [str, s_None], and get normalized
+            # to exactly one of these two.
+            if not s_string.contains(s_path):
+                raise Exception("os.utime() arg 1 must be a string, got %s" % (
+                    s_path,))
+            case1 = s_None.contains(s_times)
+            case2 = s_tuple_of_2_floats.contains(s_times)
+            if case1 and case2:
+                return [s_string, s_ImpossibleValue] #don't know which case yet
+            elif case1:
+                return [s_string, s_None]
+            elif case2:
+                return [s_string, s_tuple_of_2_floats]
+            else:
+                raise Exception("os.utime() arg 2 must be None or a tuple of "
+                                "2 floats, got %s" % (s_times,))
+
+        self.register(os.utime, os_utime_normalize_args, s_None,
+                      "ll_os.ll_os_utime",
+                      llimpl=os_utime_lltypeimpl)
 
     if hasattr(os, 'setsid'):
         @registering(os.setsid)
@@ -353,7 +373,7 @@
         def os_getcwd_oofakeimpl():
             return OOSupport.to_rstr(os.getcwd())
 
-        self.register(os.getcwd, [], SomeString(),
+        self.register(os.getcwd, [], str,
                       "ll_os.ll_os_getcwd", llimpl=os_getcwd_lltypeimpl,
                       oofakeimpl=os_getcwd_oofakeimpl)
 
@@ -417,10 +437,190 @@
                     raise OSError(error, "os_readdir failed")
                 return result
 
-            self.register(os.listdir, [str], s_list_of_strings,
+            self.register(os.listdir,
+                          [str],  # a single argument which is a str
+                          [str],  # returns a list of strings
                           "ll_os.ll_os_listdir",
                           llimpl=os_listdir_lltypeimpl)
 
+    @registering(os.pipe)
+    def register_os_pipe(self):
+        # we need a different approach on Windows and on Posix
+        if sys.platform.startswith('win'):
+            XXX   # CreatePipe, _open_osfhandle
+        else:
+            INT_ARRAY_P = lltype.Ptr(lltype.FixedSizeArray(rffi.INT, 2))
+            os_pipe = rffi.llexternal('pipe', [INT_ARRAY_P], rffi.INT,
+                                      includes=['unistd.h'])
+
+            def os_pipe_lltypeimpl():
+                filedes = lltype.malloc(INT_ARRAY_P.TO, flavor='raw')
+                error = os_pipe(filedes)
+                read_fd = filedes[0]
+                write_fd = filedes[1]
+                lltype.free(filedes, flavor='raw')
+                if error != 0:
+                    raise OSError(rffi.get_errno(), "os_pipe failed")
+                return (read_fd, write_fd)
+
+            self.register(os.pipe, [], (int, int),
+                          "ll_os.ll_os_pipe",
+                          llimpl=os_pipe_lltypeimpl)
+
+    if hasattr(os, 'readlink'):
+        @registering(os.readlink)
+        def register_os_readlink(self):
+            os_readlink = rffi.llexternal('readlink',
+                                       [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T],
+                                       rffi.INT)  # XXX SSIZE_T in POSIX.1-2001
+
+            def os_readlink_lltypeimpl(path):
+                l_path = rffi.str2charp(path)
+                try:
+                    bufsize = 1023
+                    while True:
+                        buf = lltype.malloc(rffi.CCHARP.TO, bufsize,
+                                            flavor='raw')
+                        res = os_readlink(l_path, buf,
+                                          rffi.cast(rffi.SIZE_T, bufsize))
+                        if res < 0:
+                            error = rffi.get_errno()    # failed
+                            lltype.free(buf, flavor='raw')
+                            raise OSError(error, "readlink failed")
+                        elif res < bufsize:
+                            break                       # ok
+                        else:
+                            # buf too small, try again with a larger buffer
+                            lltype.free(buf, flavor='raw')
+                            bufsize *= 4
+                    # convert the result to a string
+                    res = rffi.cast(lltype.Signed, res)
+                    l = [buf[i] for i in range(res)]
+                    result = ''.join(l)
+                    lltype.free(buf, flavor='raw')
+                finally:
+                    rffi.free_charp(l_path)
+                return result
+
+            self.register(os.readlink, [str], str,
+                          "ll_os.ll_os_readlink",
+                          llimpl=os_readlink_lltypeimpl)
+
+    @registering(os.waitpid)
+    def register_os_waitpid(self):
+        if sys.platform.startswith('win'):
+            # emulate waitpid() with the _cwait() of Microsoft's compiler
+            os__cwait = rffi.llexternal('_cwait',
+                                        [rffi.INTP, rffi.PID_T, rffi.INT],
+                                        rffi.PID_T)
+            def os_waitpid(pid, status_p, options):
+                result = os__cwait(status_p, pid, options)
+                # shift the status left a byte so this is more
+                # like the POSIX waitpid
+                status_p[0] <<= 8
+                return result
+        else:
+            # Posix
+            os_waitpid = rffi.llexternal('waitpid',
+                                         [rffi.PID_T, rffi.INTP, rffi.INT],
+                                         rffi.PID_T)
+
+        def os_waitpid_lltypeimpl(pid, options):
+            status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+            status_p[0] = 0
+            result = os_waitpid(rffi.cast(rffi.PID_T, pid),
+                                status_p,
+                                rffi.cast(rffi.INT, options))
+            status = status_p[0]
+            lltype.free(status_p, flavor='raw')
+            if result == -1:
+                raise OSError(rffi.get_errno(), "os_waitpid failed")
+            return (rffi.cast(lltype.Signed, result),
+                    rffi.cast(lltype.Signed, status))
+
+        self.register(os.waitpid, [int, int], (int, int),
+                      "ll_os.ll_os_waitpid",
+                      llimpl=os_waitpid_lltypeimpl)
+
+# --------------------------- os.stat & variants ---------------------------
+
+    def register_stat_variant(self, name):
+        if sys.platform.startswith('win'):
+            struct_stat = '_stati64'
+            functions = {'stat':  '_stati64',
+                         'fstat': '_fstati64',
+                         'lstat': '_stati64'}    # no lstat on Windows
+            c_func_name = functions[name]
+            INCLUDES = []
+        else:
+            struct_stat = 'stat'
+            c_func_name = name
+            INCLUDES = self.UNISTD_INCL + ['sys/stat.h']
+        # XXX all fields are lltype.Signed for now, which is wrong
+        STRUCT_STAT = rffi.CStruct(struct_stat,
+                                   ('st_mode',  lltype.Signed),
+                                   ('st_ino',   lltype.Signed),
+                                   ('st_dev',   lltype.Signed),
+                                   ('st_nlink', lltype.Signed),
+                                   ('st_uid',   lltype.Signed),
+                                   ('st_gid',   lltype.Signed),
+                                   ('st_size',  lltype.Signed),
+                                   ('st_atime', lltype.Signed),
+                                   ('st_mtime', lltype.Signed),
+                                   ('st_ctime', lltype.Signed),
+                                   )
+        arg_is_path = (name != 'fstat')
+        if arg_is_path:
+            ARG1 = rffi.CCHARP
+        else:
+            ARG1 = rffi.INT
+        os_mystat = rffi.llexternal(name, [ARG1, STRUCT_STAT], rffi.INT,
+                                    includes=INCLUDES)
+
+        def os_mystat_lltypeimpl(arg):
+            stresult = lltype.malloc(STRUCT_STAT.TO, flavor='raw')
+            try:
+                if arg_is_path:
+                    arg = rffi.str2charp(arg)
+                error = os_mystat(arg, stresult)
+                if arg_is_path:
+                    rffi.free_charp(arg)
+                if error != 0:
+                    raise OSError(rffi.get_errno(), "os_stat failed")
+                return (stresult.c_st_mode,
+                        stresult.c_st_ino,
+                        stresult.c_st_dev,
+                        stresult.c_st_nlink,
+                        stresult.c_st_uid,
+                        stresult.c_st_gid,
+                        stresult.c_st_size,
+                        stresult.c_st_atime,
+                        stresult.c_st_mtime,
+                        stresult.c_st_ctime)
+            finally:
+                lltype.free(stresult, flavor='raw')
+
+        if arg_is_path:
+            s_arg = str
+        else:
+            s_arg = int
+        self.register(getattr(os, name), [s_arg], (int,) * 10,
+                      "ll_os.ll_os_%s" % (name,),
+                      llimpl=func_with_new_name(os_mystat_lltypeimpl,
+                                                'os_%s_lltypeimpl' % (name,)))
+
+    @registering(os.fstat)
+    def register_os_fstat(self):
+        self.register_stat_variant('fstat')
+
+    @registering(os.stat)
+    def register_os_stat(self):
+        self.register_stat_variant('stat')
+
+    @registering(os.lstat)
+    def register_os_lstat(self):
+        self.register_stat_variant('lstat')
+
     # ------------------------------- os.W* ---------------------------------
 
     w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED',
@@ -472,7 +672,25 @@
             self.register(os.ttyname, [int], str, "ll_os.ttyname",
                           llimpl=ttyname_lltypeimpl)
 
+# ____________________________________________________________
+# Support for os.environ
+
+# XXX only for systems where os.environ is an instance of _Environ,
+# which should cover Unix and Windows at least
+assert type(os.environ) is not dict
+
+from pypy.rpython.controllerentry import ControllerEntryForPrebuilt
+
+class EnvironExtRegistry(ControllerEntryForPrebuilt):
+    _about_ = os.environ
+
+    def getcontroller(self):
+        from pypy.rpython.module.ll_os_environ import OsEnvironController
+        return OsEnvironController()
+
+
 class BaseOS:
+    # XXX deprecated style, this is all waiting to be converted to rffi
     __metaclass__ = ClassMethods
 
     def ll_os_lseek(cls, fd,pos,how):
@@ -487,27 +705,6 @@
         return os.ftruncate(fd,len)
     ll_os_ftruncate.suggested_primitive = True
 
-    def ll_os_fstat(cls, fd):
-        (stat0, stat1, stat2, stat3, stat4,
-         stat5, stat6, stat7, stat8, stat9) = os.fstat(fd)
-        return cls.ll_stat_result(stat0, stat1, stat2, stat3, stat4,
-                                  stat5, stat6, stat7, stat8, stat9)
-    ll_os_fstat.suggested_primitive = True
-
-    def ll_os_stat(cls, path):
-        (stat0, stat1, stat2, stat3, stat4,
-         stat5, stat6, stat7, stat8, stat9) = os.stat(cls.from_rstr(path))
-        return cls.ll_stat_result(stat0, stat1, stat2, stat3, stat4,
-                                  stat5, stat6, stat7, stat8, stat9)
-    ll_os_stat.suggested_primitive = True
-
-    def ll_os_lstat(cls, path):
-        (stat0, stat1, stat2, stat3, stat4,
-         stat5, stat6, stat7, stat8, stat9) = os.lstat(cls.from_rstr(path))
-        return cls.ll_stat_result(stat0, stat1, stat2, stat3, stat4,
-                                  stat5, stat6, stat7, stat8, stat9)
-    ll_os_lstat.suggested_primitive = True
-
     def ll_os_strerror(cls, errnum):
         return cls.to_rstr(os.strerror(errnum))
     ll_os_strerror.suggested_primitive = True
@@ -546,11 +743,6 @@
         return ros.environ(idx)
     ll_os_environ.suggested_primitive = True
 
-    def ll_os_pipe(cls):
-        fd1, fd2 = os.pipe()
-        return cls.ll_pipe_result(fd1, fd2)
-    ll_os_pipe.suggested_primitive = True
-
     def ll_os_chmod(cls, path, mode):
         os.chmod(cls.from_rstr(path), mode)
     ll_os_chmod.suggested_primitive = True
@@ -575,14 +767,6 @@
         os.symlink(cls.from_rstr(path1), cls.from_rstr(path2))
     ll_os_symlink.suggested_primitive = True
 
-    def ll_readlink_into(cls, path, buffer):
-        data = os.readlink(cls.from_rstr(path))
-        if len(data) < len(buffer.chars):   # safely no overflow
-            _ll_strfill(buffer, data, len(data))
-        return len(data)
-    ll_readlink_into.suggested_primitive = True
-    ll_readlink_into = staticmethod(ll_readlink_into)
-
     def ll_os_fork(cls):
         return os.fork()
     ll_os_fork.suggested_primitive = True
@@ -591,11 +775,6 @@
         return os.spawnv(mode, path, args)
     ll_os_spawnv.suggested_primitive = True
 
-    def ll_os_waitpid(cls, pid, options):
-        pid, status = os.waitpid(pid, options)
-        return cls.ll_waitpid_result(pid, status)
-    ll_os_waitpid.suggested_primitive = True
-
     def ll_os__exit(cls, status):
         os._exit(status)
     ll_os__exit.suggested_primitive = True

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_path.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_os_path.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_path.py	Tue Aug 14 18:10:44 2007
@@ -17,16 +17,15 @@
     def ll_os_path_exists(cls, path):
         """Test whether a path exists"""
         try:
-            st = os.stat(cls.from_rstr(path))
+            st = os.stat(cls.from_rstr_nonnull(path))
         except OSError:
             return False
         return True
 
     def ll_os_path_isdir(cls, path):
         try:
-            (stat0, stat1, stat2, stat3, stat4,
-             stat5, stat6, stat7, stat8, stat9) = os.stat(cls.from_rstr(path))
+            st = os.stat(cls.from_rstr_nonnull(path))
         except OSError:
             return False
-        return stat.S_ISDIR(stat0)
+        return stat.S_ISDIR(st[0])
 

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/support.py
==============================================================================
--- pypy/dist/pypy/rpython/module/support.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/support.py	Tue Aug 14 18:10:44 2007
@@ -36,6 +36,11 @@
             return ''.join([rs.chars[i] for i in range(len(rs.chars))])
     from_rstr = staticmethod(from_rstr)
 
+    def from_rstr_nonnull(rs):
+        assert rs
+        return ''.join([rs.chars[i] for i in range(len(rs.chars))])
+    from_rstr_nonnull = staticmethod(from_rstr_nonnull)
+
 class OOSupport:
     _mixin_ = True
 
@@ -50,6 +55,11 @@
             return "".join([rs.ll_stritem_nonneg(i) for i in range(rs.ll_strlen())])
     from_rstr = staticmethod(from_rstr)        
 
+    def from_rstr_nonnull(rs):
+        assert rs
+        return "".join([rs.ll_stritem_nonneg(i) for i in range(rs.ll_strlen())])
+    from_rstr_nonnull = staticmethod(from_rstr_nonnull)
+
 
 def ll_strcpy(dst_s, src_s, n):
     dstchars = dst_s.chars

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os_path.py
==============================================================================
--- pypy/dist/pypy/rpython/module/test/test_ll_os_path.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_ll_os_path.py	Tue Aug 14 18:10:44 2007
@@ -33,6 +33,7 @@
     interpret(f, [])
 
 def test_isdir():
+    import py; py.test.skip("XXX cannot run os.stat() on the llinterp yet")
     s = str(udir.join('test_isdir'))
     def f():
         return os.path.isdir(s)

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py
==============================================================================
--- pypy/dist/pypy/rpython/module/test/test_posix.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/test/test_posix.py	Tue Aug 14 18:10:44 2007
@@ -24,6 +24,7 @@
         assert type(func) == int
 
     def test_fstat(self):
+        import py; py.test.skip("XXX cannot run os.stat() on the llinterp yet")
         def fo(fi):
             g = posix.fstat(fi)
             return g

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/module/ll_os.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/ootypesystem/module/ll_os.py	Tue Aug 14 18:10:44 2007
@@ -1,8 +1,8 @@
-import os
+# mostly-deprecated module
+
 from pypy.rpython.module.support import OOSupport
 from pypy.rpython.module.ll_os import BaseOS
 from pypy.rpython.ootypesystem import ootype
-from pypy.rlib.rarithmetic import intmask
 
 def _make_tuple(FIELDS):
     n = len(FIELDS)
@@ -11,41 +11,6 @@
     return ootype.Record(fields)
 
 STAT_RESULT = _make_tuple([ootype.Signed]*10)
-PIPE_RESULT = _make_tuple([ootype.Signed]*2)
-WAITPID_RESULT = _make_tuple([ootype.Signed]*2)
 
 class Implementation(BaseOS, OOSupport):
-    
-    def ll_stat_result(stat0, stat1, stat2, stat3, stat4,
-                       stat5, stat6, stat7, stat8, stat9):
-        tup = ootype.new(STAT_RESULT)
-        tup.item0 = intmask(stat0)
-        tup.item1 = intmask(stat1)
-        tup.item2 = intmask(stat2)
-        tup.item3 = intmask(stat3)
-        tup.item4 = intmask(stat4)
-        tup.item5 = intmask(stat5)
-        tup.item6 = intmask(stat6)
-        tup.item7 = intmask(stat7)
-        tup.item8 = intmask(stat8)
-        tup.item9 = intmask(stat9)
-        return tup
-    ll_stat_result = staticmethod(ll_stat_result)
-
-    def ll_pipe_result(fd1, fd2):
-        tup = ootype.new(PIPE_RESULT)
-        tup.item0 = fd1
-        tup.item1 = fd2
-        return tup
-    ll_pipe_result = staticmethod(ll_pipe_result)
-
-    def ll_os_readlink(cls, path):
-        return cls.to_rstr(os.readlink(path))
-    ll_os_readlink.suggested_primitive = True
-
-    def ll_waitpid_result(fd1, fd2):
-        tup = ootype.new(WAITPID_RESULT)
-        tup.item0 = fd1
-        tup.item1 = fd2
-        return tup
-    ll_waitpid_result = staticmethod(ll_waitpid_result)
+    pass

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/rbuiltin.py	Tue Aug 14 18:10:44 2007
@@ -352,6 +352,8 @@
             v = r_tup.getitem(hop.llops, v_extra_args, n)
             vlist.append(v)
 
+    hop.has_implicit_exception(MemoryError)   # record that we know about it
+    hop.exception_is_here()
     return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype)
 
 def rtype_free(hop, i_flavor):

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rptr.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rptr.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/test/test_rptr.py	Tue Aug 14 18:10:44 2007
@@ -1,4 +1,4 @@
-import py
+import py, sys
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.rpython.annlowlevel import annotate_lowlevel_helper, LowLevelAnnotatorPolicy
 from pypy.rpython.lltypesystem.lltype import *
@@ -183,6 +183,24 @@
     res = interpret(fn, [23])
     assert res == 23
 
+def test_memoryerror():
+    A = Array(Signed)
+    def fn(n):
+        try:
+            a = malloc(A, n, flavor='raw')
+        except MemoryError:
+            return -42
+        else:
+            res = len(a)
+            free(a, flavor='raw')
+            return res
+
+    res = interpret(fn, [123])
+    assert res == 123
+
+    res = interpret(fn, [sys.maxint])
+    assert res == -42
+
 
 def test_call_ptr():
     def f(x,y,z):

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/extfunc.py	Tue Aug 14 18:10:44 2007
@@ -7,9 +7,7 @@
 from pypy.rpython.lltypesystem import rlist
 from pypy.rpython.module import ll_time, ll_os
 from pypy.rpython.module import ll_stackless, ll_stack
-from pypy.rpython.lltypesystem.module.ll_os import STAT_RESULT, PIPE_RESULT
-from pypy.rpython.lltypesystem.module.ll_os import WAITPID_RESULT
-from pypy.rpython.lltypesystem.module.ll_os import Implementation as impl
+from pypy.rpython.module.ll_os import BaseOS as impl
 from pypy.rpython.lltypesystem.module import ll_strtod
 from pypy.rlib import ros
 
@@ -23,9 +21,6 @@
 # references to functions, so we cannot insert classmethods here.
 
 EXTERNALS = {
-    impl.ll_os_stat.im_func:    'LL_os_stat',
-    impl.ll_os_fstat.im_func:   'LL_os_fstat',
-    impl.ll_os_lstat.im_func:   'LL_os_lstat',
     impl.ll_os_lseek.im_func:   'LL_os_lseek',
     impl.ll_os_isatty.im_func:  'LL_os_isatty',
     impl.ll_os_ftruncate.im_func:'LL_os_ftruncate',
@@ -41,17 +36,14 @@
     impl.ll_os_opendir.im_func: 'LL_os_opendir',
     impl.ll_os_readdir.im_func: 'LL_os_readdir',
     impl.ll_os_closedir.im_func:'LL_os_closedir',
-    impl.ll_os_pipe.im_func:    'LL_os_pipe',
     impl.ll_os_chmod.im_func:   'LL_os_chmod',
     impl.ll_os_rename.im_func:  'LL_os_rename',
     impl.ll_os_umask.im_func:   'LL_os_umask',
     impl.ll_os_kill.im_func:    'LL_os_kill',
     impl.ll_os_link.im_func:    'LL_os_link',
     impl.ll_os_symlink.im_func: 'LL_os_symlink',
-    impl.ll_readlink_into:      'LL_readlink_into',
     impl.ll_os_fork.im_func:    'LL_os_fork',
     impl.ll_os_spawnv.im_func:  'LL_os_spawnv',
-    impl.ll_os_waitpid.im_func: 'LL_os_waitpid',
     impl.ll_os__exit.im_func:   'LL_os__exit',
     ll_time.ll_time_clock: 'LL_time_clock',
     ll_time.ll_time_sleep: 'LL_time_sleep',
@@ -85,8 +77,9 @@
 math_functions = [
     'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs',
     'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh',
-    'frexp', 'pow', 'atan2', 'fmod', 'ldexp', 'modf', 'hypot'
+    'pow', 'atan2', 'fmod', 'ldexp', 'hypot'
     ]
+# frexp and modf have been ported to the new rffi style already
 
 import math
 for name in math_functions:
@@ -109,11 +102,6 @@
     LIST_OF_STR = find_list_of_str(rtyper)
     if LIST_OF_STR is not None:
         yield ('RPyListOfString', LIST_OF_STR)
-    yield ('RPyFREXP_RESULT', ll_math.FREXP_RESULT)
-    yield ('RPyMODF_RESULT', ll_math.MODF_RESULT)
-    yield ('RPySTAT_RESULT', STAT_RESULT)
-    yield ('RPyPIPE_RESULT', PIPE_RESULT)
-    yield ('RPyWAITPID_RESULT', WAITPID_RESULT)
 
 def predeclare_utility_functions(db, rtyper):
     # Common utility functions
@@ -161,24 +149,6 @@
                 yield (fname, graph)
 
 
-def get_extfunc_helper_ptrs(db, rtyper):
-
-    def annotate(func, args):
-        fptr = rtyper.annotate_helper(func, args)
-        db.helper2ptr[func] = fptr
-        return (func.__name__, fptr)
-
-    for func, args, symb in db.translator._implicitly_called_by_externals:
-        yield annotate(func, args)
-
-def predeclare_extfunc_helpers(db, rtyper):
-    def decl(func):
-        return (func.__name__, db.helper2ptr[func])
-
-    for func, args, symb in db.translator._implicitly_called_by_externals:
-        yield decl(func)
-        yield ('LL_NEED_' + symb, 1)
-
 def predeclare_extfuncs(db, rtyper):
     modules = {}
     def module_name(c_name):
@@ -234,7 +204,6 @@
     for fn in [predeclare_common_types,
                predeclare_utility_functions,
                predeclare_exception_data,
-               predeclare_extfunc_helpers,
                predeclare_extfuncs,
                ]:
         for t in fn(db, rtyper):
@@ -245,7 +214,6 @@
     for fn in [predeclare_common_types,
                predeclare_utility_functions,
                predeclare_exception_data,
-               get_extfunc_helper_ptrs,
                predeclare_extfuncs,
                ]:
         for t in fn(db, rtyper):

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py	Tue Aug 14 18:10:44 2007
@@ -705,11 +705,19 @@
         # 'fnobj' is one of the ll_xyz() functions with the suggested_primitive
         # flag in pypy.rpython.module.*.  The corresponding C wrappers are
         # written by hand in src/ll_*.h, and declared in extfunc.EXTERNALS.
-        assert (not sandbox
-                or fnobj._name.startswith('ll_strtod_')   # XXX!! TEMPORARY!
+        if sandbox and not (
+                   fnobj._name.startswith('ll_strtod_')   # XXX!! TEMPORARY!
                 or fnobj._name.startswith('ll_time_')   # XXX!! TEMPORARY!
                 or fnobj._name.startswith('ll_stack_')   # XXX!! TEMPORARY!
-                )
+                ):
+            # deprecated case: apply the sandbox transformation but don't
+            # try to support these extfuncs properly (we just build a
+            # "Not Implemented" stub).  To support these functions, port them
+            # to the new style registry (e.g. rpython.module.ll_os.RegisterOs).
+            from pypy.translator.sandbox import rsandbox
+            graph = rsandbox.get_external_function_sandbox_graph(fnobj, db,
+                                                              force_stub=True)
+            return [FunctionCodeGenerator(graph, db)]
         db.externalfuncs[fnobj._callable] = fnobj
         return []
     elif getattr(fnobj._callable, 'suggested_primitive', False):

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_math.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/ll_math.h	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_math.h	Tue Aug 14 18:10:44 2007
@@ -25,12 +25,10 @@
 
 int ll_math_is_error(double x);
 double LL_math_pow(double x, double y);
-RPyFREXP_RESULT* LL_math_frexp(double x);
 double LL_math_atan2(double x, double y);
 double LL_math_fmod(double x, double y);
 double LL_math_ldexp(double x, long y);
 double LL_math_hypot(double x, double y);
-RPyMODF_RESULT* LL_math_modf(double x);
 double LL_math_acos(double x);
 double LL_math_asin(double x);
 double LL_math_atan(double x);
@@ -72,19 +70,6 @@
 	return r;
 }
 
-#ifdef LL_NEED_MATH_FREXP
-
-RPyFREXP_RESULT* LL_math_frexp(double x) {
-	int expo;
-	double m;
-	LL_MATH_ERROR_RESET;
-	m= frexp(x, &expo);
-	LL_MATH_CHECK_ERROR(m, NULL);
-	return ll_frexp_result(m, expo);
-}
-
-#endif
-
 double LL_math_atan2(double x, double y) {
 	double r;
 	LL_MATH_ERROR_RESET;
@@ -118,18 +103,6 @@
 }
 
 
-#ifdef LL_NEED_MATH_MODF
-
-RPyMODF_RESULT* LL_math_modf(double x) {
-	double intpart, fracpart;
-	LL_MATH_ERROR_RESET;
-	fracpart = modf(x, &intpart);
-	LL_MATH_CHECK_ERROR(fracpart, NULL);
-	return ll_modf_result(fracpart, intpart);
-}
-
-#endif
-
 /* simple math function */
 
 double LL_math_acos(double x) {

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/ll_os.h	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/ll_os.h	Tue Aug 14 18:10:44 2007
@@ -4,7 +4,6 @@
 #if !(defined(MS_WIN64) || defined(MS_WINDOWS))
 #  include <unistd.h>
 #  include <sys/types.h>
-#  include <sys/stat.h>
 #endif
 
 #include <errno.h>
@@ -32,30 +31,13 @@
 */
 
 
-/* just do what CPython is doing... */
-
-#if defined(MS_WIN64) || defined(MS_WINDOWS)
-#       define STAT _stati64
-#       define FSTAT _fstati64
-#       define STRUCT_STAT struct _stati64
-#       define LSTAT STAT
-#else
-#       define STAT stat
-#       define FSTAT fstat
-#       define STRUCT_STAT struct stat
-/* plus some approximate guesses */
-#       define LSTAT lstat
+#if !(defined(MS_WIN64) || defined(MS_WINDOWS))
 #       define HAVE_FILESYSTEM_WITH_LINKS
 #endif
 
 
 /* prototypes */
 
-RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st);
-RPySTAT_RESULT* LL_os_stat(RPyString * fname);
-RPySTAT_RESULT* LL_os_lstat(RPyString * fname);
-RPySTAT_RESULT* LL_os_fstat(long fd);
-RPyPIPE_RESULT* LL_os_pipe(void);
 long LL_os_lseek(long fd, long pos, long how);
 int LL_os_isatty(long fd);
 RPyString *LL_os_strerror(int errnum);
@@ -70,12 +52,10 @@
 void LL_os_kill(int pid, int sig);
 void LL_os_link(RPyString * path1, RPyString * path2);
 void LL_os_symlink(RPyString * path1, RPyString * path2);
-long LL_readlink_into(RPyString *path, RPyString *buffer);
 long LL_os_fork(void);
 #if defined(HAVE_SPAWNV) && defined(HAVE_RPY_LIST_OF_STRING) /* argh */
 long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args);
 #endif
-RPyWAITPID_RESULT* LL_os_waitpid(long pid, long options);
 void LL_os__exit(long status);
 void LL_os_putenv(RPyString * name_eq_value);
 void LL_os_unsetenv(RPyString * name);
@@ -96,86 +76,6 @@
 
 #include "ll_osdefs.h"
 
-#ifdef LL_NEED_OS_STAT
-
-RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st) {
-  long res0, res1, res2, res3, res4, res5, res6, res7, res8, res9;
-  res0 = (long)st.st_mode;
-  res1 = (long)st.st_ino; /*XXX HAVE_LARGEFILE_SUPPORT!*/
-  res2 = (long)st.st_dev; /*XXX HAVE_LONG_LONG!*/
-  res3 = (long)st.st_nlink;
-  res4 = (long)st.st_uid;
-  res5 = (long)st.st_gid;
-  res6 = (long)st.st_size; /*XXX HAVE_LARGEFILE_SUPPORT!*/
-  res7 = (long)st.st_atime; /*XXX ignoring quite a lot of things for time here */
-  res8 = (long)st.st_mtime; /*XXX ignoring quite a lot of things for time here */
-  res9 = (long)st.st_ctime; /*XXX ignoring quite a lot of things for time here */
-  /*XXX ignoring BLOCK info here*/
-
-  return ll_stat_result(res0, res1, res2, res3, res4,
-			res5, res6, res7, res8, res9);
-}
-
-
-RPySTAT_RESULT* LL_os_stat(RPyString * fname) {
-  STRUCT_STAT st;
-  int error = STAT(RPyString_AsString(fname), &st);
-  if (error != 0) {
-    RPYTHON_RAISE_OSERROR(errno);
-    return NULL;
-  }
-  return _stat_construct_result_helper(st);
-}
-
-RPySTAT_RESULT* LL_os_lstat(RPyString * fname) {
-  STRUCT_STAT st;
-  int error = LSTAT(RPyString_AsString(fname), &st);
-  if (error != 0) {
-    RPYTHON_RAISE_OSERROR(errno);
-    return NULL;
-  }
-  return _stat_construct_result_helper(st);
-}
-
-RPySTAT_RESULT* LL_os_fstat(long fd) {
-  STRUCT_STAT st;
-  int error = FSTAT(fd, &st);
-  if (error != 0) {
-    RPYTHON_RAISE_OSERROR(errno);
-    return NULL;
-  }
-  return _stat_construct_result_helper(st);
-}
-
-#endif
-
-#ifdef LL_NEED_OS_PIPE
-
-RPyPIPE_RESULT* LL_os_pipe(void) {
-#if !defined(MS_WINDOWS)
-	int filedes[2];
-	int error = pipe(filedes);
-	if (error != 0) {
-		RPYTHON_RAISE_OSERROR(errno);
-		return NULL;
-	}
-	return ll_pipe_result(filedes[0], filedes[1]);
-#else
-	HANDLE read, write;
-	int read_fd, write_fd;
-	BOOL ok = CreatePipe(&read, &write, NULL, 0);
-	if (!ok) {
-		RPYTHON_RAISE_OSERROR(errno);
-		return NULL;
-	}
-	read_fd = _open_osfhandle((long)read, 0);
-	write_fd = _open_osfhandle((long)write, 1);
-	return ll_pipe_result(read_fd, write_fd);
-#endif
-}
-
-#endif
-
 long LL_os_lseek(long fd, long pos, long how) {
 #if defined(MS_WIN64) || defined(MS_WINDOWS)
     PY_LONG_LONG res;
@@ -304,16 +204,6 @@
 	RPYTHON_RAISE_OSERROR(errno);
     }
 }
-
-long LL_readlink_into(RPyString *path, RPyString *buffer)
-{
-	long n = readlink(RPyString_AsString(path),
-			  RPyString_AsString(buffer), RPyString_Size(buffer));
-	if (n < 0)
-		RPYTHON_RAISE_OSERROR(errno);
-	return n;
-}
-
 #endif
 
 #ifdef HAVE_FORK
@@ -352,36 +242,6 @@
 }
 #endif
 
-#ifdef LL_NEED_OS_WAITPID
-/* note: LL_NEED_ is computed in extfunc.py, can't grep */
-
-#ifdef HAVE_WAITPID
-RPyWAITPID_RESULT* LL_os_waitpid(long pid, long options) {
-	int status;
-	pid = waitpid(pid, &status, options);
-	if (pid == -1) {
-		RPYTHON_RAISE_OSERROR(errno);
-		return NULL;
-	}
-	return ll_waitpid_result(pid, status);
-}
-
-#elif defined(HAVE_CWAIT)
-
-RPyWAITPID_RESULT* LL_os_waitpid(long pid, long options) {
-	int status;
-	pid = _cwait(&status, pid, options);
-	if (pid == -1) {
-		RPYTHON_RAISE_OSERROR(errno);
-		return NULL;
-	}
-		/* shift the status left a byte so this is more like the
-		   POSIX waitpid */
-	return ll_waitpid_result(pid, status << 8);
-}
-#endif /* HAVE_WAITPID || HAVE_CWAIT */
-#endif
-
 void LL_os__exit(long status) {
 	_exit((int)status);
 }

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_extfunc.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py	Tue Aug 14 18:10:44 2007
@@ -659,11 +659,13 @@
         s = func(len(keys))
         if not s:
             break
-        keys.append(s)
+        name, value = s.split('=', 1)
+        keys.append(name)
     expected = _real_envkeys()
     keys.sort()
     expected.sort()
-    return keys == expected
+    py.test.skip("XXX fails for me, $OLDPWD doesn't show up in the subprocess")
+    assert keys == expected
 
 posix = __import__(os.name)
 if hasattr(posix, "unsetenv"):
@@ -678,7 +680,28 @@
         f()
         assert _real_getenv('ABCDEF') is None
 
+
+def test_dictlike_environ_getitem():
+    def fn(s):
+        res = os.environ[s]
+        if res is None:
+            res = '--missing--'
+        return res
+    func = compile(fn, [str])
+    os.environ.setdefault('USER', 'UNNAMED_USER')
+    result = func('USER')
+    assert result == os.environ['USER']
+
+def test_dictlike_environ_setitem():
+    def fn(s, t):
+        os.environ[s] = t
+    func = compile(fn, [str, str])
+    func('PYPY_TEST_DICTLIKE_ENVIRON', '42')
+    assert os.environ['PYPY_TEST_DICTLIKE_ENVIRON'] == '42'
+
+
 def test_opendir_readdir():
+    py.test.skip("deprecated")
     def mylistdir(s):
         result = []
         dir = ros.opendir(s)
@@ -775,16 +798,14 @@
     t0 = time()
     sleep(1)
 
-    def does_stuff():
-        ros.utime_null(path)
+    def does_stuff(flag):
+        if flag:
+            os.utime(path, None)
+        else:
+            os.utime(path, (int(t0), int(t0)))
 
-    func = compile(does_stuff, [])
-    func()
+    func = compile(does_stuff, [int])
+    func(1)
     assert os.stat(path).st_atime > t0
-
-    def utime_tuple():
-        ros.utime_tuple(path, (int(t0), int(t0)))
-
-    func = compile(utime_tuple, [])
-    func()
+    func(0)
     assert int(os.stat(path).st_atime) == int(t0)

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/interact.py
==============================================================================
--- pypy/dist/pypy/translator/sandbox/interact.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/interact.py	Tue Aug 14 18:10:44 2007
@@ -12,6 +12,6 @@
 
 if __name__ == '__main__':
     if len(sys.argv) < 2:
-        print >> sys.stderr, __doc_
+        print >> sys.stderr, __doc__
         sys.exit(2)
     SimpleIOSandboxedProc(sys.argv[1:]).interact()

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py
==============================================================================
--- pypy/dist/pypy/translator/sandbox/rsandbox.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/rsandbox.py	Tue Aug 14 18:10:44 2007
@@ -97,9 +97,9 @@
     cache[FUNCTYPE] = marshal_input
     return marshal_input
 
-def unmarshal_int(msg, *args):    return msg.nextnum()
-def unmarshal_size_t(msg, *args): return msg.nextsize_t()
-def unmarshal_void(msg, *args):   pass
+def unmarshal_int(msg):    return msg.nextnum()
+def unmarshal_size_t(msg): return msg.nextsize_t()
+def unmarshal_void(msg):   pass
 
 def build_default_unmarshal_output(FUNCTYPE, namehint,
                                    cache={rffi.INT   : unmarshal_int,
@@ -150,7 +150,7 @@
     raise RuntimeError(msg)  # XXX in RPython, the msg is ignored at the moment
 not_implemented_stub._annenforceargs_ = [str]
 
-def get_external_function_sandbox_graph(fnobj, db):
+def get_external_function_sandbox_graph(fnobj, db, force_stub=False):
     """Build the graph of a helper trampoline function to be used
     in place of real calls to the external function 'fnobj'.  The
     trampoline marshals its input arguments, dumps them to STDOUT,
@@ -162,14 +162,27 @@
     FUNCTYPE = lltype.typeOf(fnobj)
     fnname = fnobj._name
     try:
+        if force_stub:   # old case - don't try to support suggested_primitive
+            raise NotImplementedError("external function '%s' using "
+                                      "deprecated 'suggested_primitive'" % (
+                fnname,))
         if hasattr(fnobj, '_marshal_input'):
             marshal_input = fnobj._marshal_input
         else:
             marshal_input = build_default_marshal_input(FUNCTYPE, fnname)
         if hasattr(fnobj, '_unmarshal_output'):
+            # _unmarshal_output() also receives the input arguments of the
+            # original call because some functions need them to decode the
+            # result properly.
             unmarshal_output = fnobj._unmarshal_output
+            unmarshal_takes_input_args = True
         else:
+            # The default unmarshal_output do not receive the original input
+            # arguments because they would cause annotation troubles
+            # (see e.g. test_sandbox_3).
             unmarshal_output = build_default_unmarshal_output(FUNCTYPE, fnname)
+            unmarshal_takes_input_args = False
+
     except NotImplementedError, e:
         msg = 'Not Implemented: %s' % (e,)
         log.WARNING(msg)
@@ -189,7 +202,10 @@
                 errcode = msg.nextnum()
                 if errcode != 0:
                     raise IOError
-                result = unmarshal_output(msg, *args)
+                if unmarshal_takes_input_args:
+                    result = unmarshal_output(msg, *args)
+                else:
+                    result = unmarshal_output(msg)
             finally:
                 lltype.free(msg.value, flavor='raw')
             return result

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py
==============================================================================
--- pypy/dist/pypy/translator/sandbox/sandlib.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/sandlib.py	Tue Aug 14 18:10:44 2007
@@ -28,6 +28,12 @@
         return self.popen.wait()
 
     def handle_forever(self):
+        returncode = self.handle_until_return()
+        if returncode != 0:
+            raise OSError("the sandboxed subprocess exited with code %d" % (
+                returncode,))
+
+    def handle_until_return(self):
         while True:
             try:
                 msg = read_message(self.popen.stdout)
@@ -36,9 +42,7 @@
             answer = self.handle_message(msg)
             self.popen.stdin.write(answer)
         returncode = self.popen.wait()
-        if returncode != 0:
-            raise OSError("the sandboxed subprocess exited with code %d" % (
-                returncode,))
+        return returncode
 
     def handle_message(self, msg):
         fn = msg.nextstring()
@@ -99,7 +103,10 @@
         self._input  = stdin  or sys.stdin
         self._output = stdout or sys.stdout
         self._error  = stderr or sys.stderr
-        self.handle_forever()
+        returncode = self.handle_until_return()
+        if returncode != 0:
+            print >> self._error, "[Subprocess exit code: %d]" % (
+                returncode,)
         self._input = None
         self._output = None
         self._error = None

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py
==============================================================================
--- pypy/dist/pypy/translator/sandbox/test/test_sandbox.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/sandbox/test/test_sandbox.py	Tue Aug 14 18:10:44 2007
@@ -131,6 +131,43 @@
     f.close()
     assert tail == ""
 
+def test_sandbox_3():
+    def entry_point(argv):
+        os.dup2(34, 56)
+        y = os.access("spam", 77)
+        return 1 - y
+
+    t = Translation(entry_point, backend='c', standalone=True, sandbox=True)
+    exe = t.compile()
+    g, f = os.popen2(exe, "t", 0)
+
+    msg = read_message(f, timeout=10.0)
+    m1 = msg.nextstring()
+    assert m1 == "dup2"
+    m2 = msg.nextnum()
+    assert m2 == 34
+    m3 = msg.nextnum()
+    assert m3 == 56
+    assert msg.end()
+
+    g.write(MessageBuilder().packnum(0).packnum(0).getvalue())
+
+    msg = read_message(f, timeout=10.0)
+    m1 = msg.nextstring()
+    assert m1 == "access"
+    m2 = msg.nextstring()
+    assert m2 == "spam"
+    m3 = msg.nextnum()
+    assert m3 == 77
+    assert msg.end()
+
+    g.write(MessageBuilder().packnum(0).packnum(0).getvalue())
+
+    g.close()
+    tail = f.read()
+    f.close()
+    assert tail == ""
+
 class TestPrintedResults:
 
     def run(self, entry_point, args, expected):
@@ -150,6 +187,10 @@
             print int(math.floor(a - 0.2)),
             print int(math.ceil(a)),
             print int(100.0 * math.sin(a)),
+            mantissa, exponent = math.frexp(a)
+            print int(100.0 * mantissa), exponent,
+            fracpart, intpart = math.modf(a)
+            print int(100.0 * fracpart), int(intpart),
             print
             return 0
-        self.run(entry_point, ["3.011"], "2 4 13\n")
+        self.run(entry_point, ["3.011"], "2 4 13 75 2 1 3\n")

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/translator.py
==============================================================================
--- pypy/dist/pypy/translator/translator.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/translator.py	Tue Aug 14 18:10:44 2007
@@ -44,8 +44,6 @@
         self.callgraph = {}   # {opaque_tag: (caller-graph, callee-graph)}
         self._prebuilt_graphs = {}   # only used by the pygame viewer
 
-        self._implicitly_called_by_externals = []
-
     def create_flowspace_config(self):
         # XXX this is a hack: we create a new config, which is only used
         # for the flow object space. The problem is that the flow obj space



More information about the Pypy-commit mailing list