Ejemplo n.º 1
0
    def test_list_of_str0_unchecked(self):
        str0 = SomeString(no_nul=True)

        def os_execve(l):
            pass

        register_external(os_execve, [[str0]], None)

        def f(l):
            return os_execve(l)

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        assert a.translator.config.translation.check_str_without_nul == False
        a.build_types(f, [[str]])  # Does not raise
        # Now enable the str0 check, and try again with a similar function
        a.translator.config.translation.check_str_without_nul=True

        def g(l):
            return os_execve(l)

        with py.test.raises(AnnotatorError):
            # fails with TooLateForChange
            a.build_types(g, [[str]])
        a.build_types(g, [[str0]])  # Does not raise
Ejemplo n.º 2
0
    def test_list_of_str0_unchecked(self):
        str0 = SomeString(no_nul=True)

        def os_execve(l):
            pass

        register_external(os_execve, [[str0]], None)

        def f(l):
            return os_execve(l)

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        assert a.translator.config.translation.check_str_without_nul == False
        a.build_types(f, [[str]])  # Does not raise
        # Now enable the str0 check, and try again with a similar function
        a.translator.config.translation.check_str_without_nul=True

        def g(l):
            return os_execve(l)

        with py.test.raises(AnnotatorError):
            # fails with TooLateForChange
            a.build_types(g, [[str]])
        a.build_types(g, [[str0]])  # Does not raise
Ejemplo n.º 3
0
    def test_register_external_signature(self):
        """
        Test the standard interface for external functions.
        """
        def dd():
            pass
        register_external(dd, [int], int)

        def f():
            return dd(3)

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])
        assert isinstance(s, annmodel.SomeInteger)
Ejemplo n.º 4
0
    def test_register_external_signature(self):
        """
        Test the standard interface for external functions.
        """
        def dd():
            pass
        register_external(dd, [int], int)

        def f():
            return dd(3)

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])
        assert isinstance(s, SomeInteger)
Ejemplo n.º 5
0
    def test_register_external_specialcase(self):
        """
        When args=None, the external function accepts any arguments unmodified.
        """
        def function_withspecialcase(arg):
            return repr(arg)
        register_external(function_withspecialcase, args=None, result=str)

        def f():
            x = function_withspecialcase
            return x(33) + x("aaa") + x([]) + "\n"

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])
        assert isinstance(s, SomeString)
Ejemplo n.º 6
0
    def test_register_external_specialcase(self):
        """
        When args=None, the external function accepts any arguments unmodified.
        """
        def function_withspecialcase(arg):
            return repr(arg)
        register_external(function_withspecialcase, args=None, result=str)

        def f():
            x = function_withspecialcase
            return x(33) + x("aaa") + x([]) + "\n"

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])
        assert isinstance(s, annmodel.SomeString)
Ejemplo n.º 7
0
 def test_list_of_str0(self):
     str0 = annmodel.SomeString(no_nul=True)
     def os_execve(l):
         pass
     register_external(os_execve, [[str0]], None)
     def f(l):
         return os_execve(l)
     policy = AnnotatorPolicy()
     a = RPythonAnnotator(policy=policy)
     a.build_types(f, [[str]])  # Does not raise
     assert a.translator.config.translation.check_str_without_nul == False
     # Now enable the str0 check, and try again with a similar function
     a.translator.config.translation.check_str_without_nul=True
     def g(l):
         return os_execve(l)
     py.test.raises(Exception, a.build_types, g, [[str]])
     a.build_types(g, [[str0]])  # Does not raise
Ejemplo n.º 8
0
 def test_str0(self):
     str0 = SomeString(no_nul=True)
     def os_open(s):
         pass
     register_external(os_open, [str0], None)
     def f(s):
         return os_open(s)
     policy = AnnotatorPolicy()
     a = RPythonAnnotator(policy=policy)
     a.build_types(f, [str])  # Does not raise
     assert a.translator.config.translation.check_str_without_nul == False
     # Now enable the str0 check, and try again with a similar function
     a.translator.config.translation.check_str_without_nul=True
     def g(s):
         return os_open(s)
     with py.test.raises(SignatureError):
         a.build_types(g, [str])
     a.build_types(g, [str0])  # Does not raise
Ejemplo n.º 9
0
 def test_str0(self):
     str0 = SomeString(no_nul=True)
     def os_open(s):
         pass
     register_external(os_open, [str0], None)
     def f(s):
         return os_open(s)
     policy = AnnotatorPolicy()
     a = RPythonAnnotator(policy=policy)
     a.build_types(f, [str])  # Does not raise
     assert a.translator.config.translation.check_str_without_nul == False
     # Now enable the str0 check, and try again with a similar function
     a.translator.config.translation.check_str_without_nul=True
     def g(s):
         return os_open(s)
     with py.test.raises(SignatureError):
         a.build_types(g, [str])
     a.build_types(g, [str0])  # Does not raise
Ejemplo n.º 10
0
    def test_lltypeimpl(self):
        """
        interpret() calls lltypeimpl instead of of the function/
        """
        def c(y, x):
            yyy

        def llimpl(y, x):
            return y + x

        register_external(c, [int, int], result=int, llimpl=llimpl,
                          export_name='ccc')

        def f():
            return c(3, 4)

        res = interpret(f, [])
        assert res == 7
Ejemplo n.º 11
0
    def test_register_external_llfakeimpl(self):
        def a(i):
            return i
        def a_llimpl(i):
            return i * 2
        def a_llfakeimpl(i):
            return i * 3
        register_external(a, [int], int, llimpl=a_llimpl,
                          llfakeimpl=a_llfakeimpl)
        def f(i):
            return a(i)

        res = interpret(f, [7])
        assert res == 21

        from rpython.translator.c.test.test_genc import compile
        fc = compile(f, [int])
        assert fc(7) == 14
Ejemplo n.º 12
0
    def test_register_external_return_goes_back(self):
        """
        Check whether it works to pass the same list from one external
        fun to another
        [bookkeeper and list joining issues]
        """
        def function_with_list():
            pass
        register_external(function_with_list, [[int]], int)

        def function_returning_list():
            pass
        register_external(function_returning_list, [], [int])

        def f():
            return function_with_list(function_returning_list())

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])
        assert isinstance(s, SomeInteger)
Ejemplo n.º 13
0
    def test_register_external_return_goes_back(self):
        """
        Check whether it works to pass the same list from one external
        fun to another
        [bookkeeper and list joining issues]
        """
        def function_with_list():
            pass
        register_external(function_with_list, [[int]], int)

        def function_returning_list():
            pass
        register_external(function_returning_list, [], [int])

        def f():
            return function_with_list(function_returning_list())

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])
        assert isinstance(s, SomeInteger)
Ejemplo n.º 14
0
    def test_basic(self):
        """
        A ExtFuncEntry provides an annotation for a function, no need to flow
        its graph.
        """
        def b(x):
            "NOT_RPYTHON"
            return eval("x+40")

        register_external(b, [int], result=int)

        def f():
            return b(2)

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])
        assert isinstance(s, SomeInteger)

        res = interpret(f, [])
        assert res == 42
Ejemplo n.º 15
0
    def test_register_external_tuple_args(self):
        """
        Verify the annotation of a registered external function which takes a
        tuple argument.
        """

        def function_with_tuple_arg():
            """
            Dummy function which is declared via register_external to take a
            tuple as an argument so that register_external's behavior for
            tuple-taking functions can be verified.
            """
        register_external(function_with_tuple_arg, [(int,)], int)

        def f():
            return function_with_tuple_arg((1,))

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])

        # Not a very good assertion, but at least it means _something_ happened.
        assert isinstance(s, SomeInteger)
Ejemplo n.º 16
0
    def test_register_external_tuple_args(self):
        """
        Verify the annotation of a registered external function which takes a
        tuple argument.
        """

        def function_with_tuple_arg():
            """
            Dummy function which is declared via register_external to take a
            tuple as an argument so that register_external's behavior for
            tuple-taking functions can be verified.
            """
        register_external(function_with_tuple_arg, [(int,)], int)

        def f():
            return function_with_tuple_arg((1,))

        policy = AnnotatorPolicy()
        a = RPythonAnnotator(policy=policy)
        s = a.build_types(f, [])

        # Not a very good assertion, but at least it means _something_ happened.
        assert isinstance(s, SomeInteger)
Ejemplo n.º 17
0
def test_raising_llimpl():
    from rpython.rtyper.extfunc import register_external

    def external():
        pass

    def raising():
        raise OSError(15, "abcd")

    ext = register_external(external, [], llimpl=raising, llfakeimpl=raising)

    def f():
        # this is a useful llfakeimpl that raises an exception
        try:
            external()
            return True
        except OSError:
            return False

    res = interpret(f, [])
    assert not res
Ejemplo n.º 18
0
def test_raising_llimpl():
    from rpython.rtyper.extfunc import register_external

    def external():
        pass

    def raising():
        raise OSError(15, "abcd")

    ext = register_external(external, [], llimpl=raising, llfakeimpl=raising)

    def f():
        # this is a useful llfakeimpl that raises an exception
        try:
            external()
            return True
        except OSError:
            return False

    res = interpret(f, [])
    assert not res
Ejemplo n.º 19
0
from rpython.rtyper.lltypesystem.module import ll_math
from rpython.rtyper.module import ll_os
from rpython.rtyper.module import ll_time
from rpython.rtyper.module import ll_pdb
from rpython.rlib import rfloat

# the following functions all take one float, return one float
# and are part of math.h
for name in ll_math.unary_math_functions:
    llimpl = getattr(ll_math, 'll_math_%s' % name, None)
    try:
        f = getattr(math, name)
    except AttributeError:
        f = getattr(rfloat, name)
    register_external(f, [float], float,
                      export_name="ll_math.ll_math_%s" % name,
                       sandboxsafe=True, llimpl=llimpl)

_register = [  # (module, [(method name, arg types, return type), ...], ...)
    (rfloat, [
        ('isinf', [float], bool),
        ('isnan', [float], bool),
        ('isfinite', [float], bool),
        ('copysign', [float, float], float),
    ]),
    (math, [
       ('floor', [float], float),
       ('sqrt', [float], float),
       ('log', [float], float),
       ('log10', [float], float),
       ('log1p', [float], float),
Ejemplo n.º 20
0
    try:
        if c_tcgetattr(fd, c_struct) < 0:
            raise OSError(rposix.get_errno(), 'tcgetattr failed')
        cc = [chr(c_struct.c_c_cc[i]) for i in range(NCCS)]
        ispeed = c_cfgetispeed(c_struct)
        ospeed = c_cfgetospeed(c_struct)
        result = (intmask(c_struct.c_c_iflag), intmask(c_struct.c_c_oflag),
                  intmask(c_struct.c_c_cflag), intmask(c_struct.c_c_lflag),
                  intmask(ispeed), intmask(ospeed), cc)
        return result
    finally:
        lltype.free(c_struct, flavor='raw')


register_external(rtermios.tcgetattr, [int],
                  (int, int, int, int, int, int, [str]),
                  llimpl=tcgetattr_llimpl,
                  export_name='termios.tcgetattr')


def tcsetattr_llimpl(fd, when, attributes):
    c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw')
    try:
        c_struct.c_c_iflag = r_uint(attributes[0])
        c_struct.c_c_oflag = r_uint(attributes[1])
        c_struct.c_c_cflag = r_uint(attributes[2])
        c_struct.c_c_lflag = r_uint(attributes[3])
        ispeed = r_uint(attributes[4])
        ospeed = r_uint(attributes[5])
        cc = attributes[6]
        for i in range(NCCS):
            c_struct.c_c_cc[i] = rffi.r_uchar(ord(cc[i][0]))
Ejemplo n.º 21
0
    c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw')

    try:
        if c_tcgetattr(fd, c_struct) < 0:
            raise OSError(rposix.get_errno(), 'tcgetattr failed')
        cc = [chr(c_struct.c_c_cc[i]) for i in range(NCCS)]
        ispeed = c_cfgetispeed(c_struct)
        ospeed = c_cfgetospeed(c_struct)
        result = (intmask(c_struct.c_c_iflag), intmask(c_struct.c_c_oflag),
                  intmask(c_struct.c_c_cflag), intmask(c_struct.c_c_lflag),
                  intmask(ispeed), intmask(ospeed), cc)
        return result
    finally:
        lltype.free(c_struct, flavor='raw')

register_external(rtermios.tcgetattr, [int], (int, int, int, int, int, int, [str]),
                   llimpl=tcgetattr_llimpl, export_name='termios.tcgetattr')

def tcsetattr_llimpl(fd, when, attributes):
    c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw')
    try:
        c_struct.c_c_iflag = r_uint(attributes[0])
        c_struct.c_c_oflag = r_uint(attributes[1])
        c_struct.c_c_cflag = r_uint(attributes[2])
        c_struct.c_c_lflag = r_uint(attributes[3])
        ispeed = r_uint(attributes[4])
        ospeed = r_uint(attributes[5])
        cc = attributes[6]
        for i in range(NCCS):
            c_struct.c_c_cc[i] = rffi.r_uchar(ord(cc[i][0]))
        if c_cfsetispeed(c_struct, ispeed) < 0:
            raise OSError(rposix.get_errno(), 'tcsetattr failed')
Ejemplo n.º 22
0
import math
from rpython.rtyper.lltypesystem.module import ll_math
from rpython.rtyper.module import ll_os
from rpython.rtyper.module import ll_time
from rpython.rlib import rfloat

# the following functions all take one float, return one float
# and are part of math.h
for name in ll_math.unary_math_functions:
    llimpl = getattr(ll_math, 'll_math_%s' % name, None)
    try:
        f = getattr(math, name)
    except AttributeError:
        f = getattr(rfloat, name)
    register_external(f, [float], float,
                      export_name="ll_math.ll_math_%s" % name,
                       sandboxsafe=True, llimpl=llimpl)

_register = [  # (module, [(method name, arg types, return type), ...], ...)
    (rfloat, [
        ('isinf', [float], bool),
        ('isnan', [float], bool),
        ('isfinite', [float], bool),
        ('copysign', [float, float], float),
    ]),
    (math, [
       ('floor', [float], float),
       ('sqrt', [float], float),
       ('log', [float], float),
       ('log10', [float], float),
       ('log1p', [float], float),
Ejemplo n.º 23
0
_lconv = lltype.Ptr(cConfig.lconv)
localeconv = external('localeconv', [], _lconv)

def numeric_formatting():
    """Specialized function to get formatting for numbers"""
    return numeric_formatting_impl()

def numeric_formatting_impl():
    conv = localeconv()
    decimal_point = rffi.charp2str(conv.c_decimal_point)
    thousands_sep = rffi.charp2str(conv.c_thousands_sep)
    grouping = rffi.charp2str(conv.c_grouping)
    return decimal_point, thousands_sep, grouping

register_external(numeric_formatting, [], (str, str, str),
                  llimpl=numeric_formatting_impl,
                  sandboxsafe=True)


_setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP)

def setlocale(category, locale):
    if cConfig.LC_MAX is not None:
        if not cConfig.LC_MIN <= category <= cConfig.LC_MAX:
            raise LocaleError("invalid locale category")
    ll_result = _setlocale(rffi.cast(rffi.INT, category), locale)
    if not ll_result:
        raise LocaleError("unsupported locale setting")
    return rffi.charp2str(ll_result)

isalpha = external('isalpha', [rffi.INT], rffi.INT, oo_primitive='locale_isalpha')
Ejemplo n.º 24
0
def envkeys_llimpl():
    environ = os_get_environ()
    result = []
    i = 0
    while environ[i]:
        name_value = rffi.charp2str(environ[i])
        p = name_value.find("=")
        if p >= 0:
            result.append(name_value[:p])
        i += 1
    return result


register_external(
    r_envkeys, [], [str0], export_name="ll_os.ll_os_envkeys", llimpl=envkeys_llimpl  # returns a list of strings
)

# ____________________________________________________________


def r_envitems():
    just_a_placeholder


def r_getenv(name):
    just_a_placeholder  # should return None if name not found


def r_putenv(name, value):
    just_a_placeholder
Ejemplo n.º 25
0
                              sandboxsafe=True,
                              _nowrapper=True)


def llimpl_arena_malloc(nbytes, zero):
    if zero:
        addr = llimpl_calloc(nbytes, 1)
    else:
        addr = llimpl_malloc(nbytes)
    return addr


llimpl_arena_malloc._always_inline_ = True
register_external(arena_malloc, [int, int],
                  llmemory.Address,
                  'll_arena.arena_malloc',
                  llimpl=llimpl_arena_malloc,
                  llfakeimpl=arena_malloc,
                  sandboxsafe=True)

register_external(arena_free, [llmemory.Address],
                  None,
                  'll_arena.arena_free',
                  llimpl=llimpl_free,
                  llfakeimpl=arena_free,
                  sandboxsafe=True)


def llimpl_arena_reset(arena_addr, size, zero):
    if zero:
        if zero == 1:
            clear_large_memory_chunk(arena_addr, size)
Ejemplo n.º 26
0
        def allow_attach():
            pass

    def impl_attach_gdb():
        import os
        allow_attach()
        pid = os.getpid()
        gdbpid = os.fork()
        if gdbpid == 0:
            shell = os.environ.get("SHELL") or "/bin/sh"
            sepidx = shell.rfind(os.sep) + 1
            if sepidx > 0:
                argv0 = shell[sepidx:]
            else:
                argv0 = shell
            try:
                os.execv(shell, [argv0, "-c", "gdb -p %d" % pid])
            except OSError as e:
                os.write(2, "Could not start GDB: %s" % (
                    os.strerror(e.errno)))
                raise SystemExit
        else:
            time.sleep(1)  # give the GDB time to attach

else:
    def impl_attach_gdb():
        print "Don't know how to attach GDB on Windows"

register_external(attach_gdb, [], result=None,
                  export_name="impl_attach_gdb", llimpl=impl_attach_gdb)
Ejemplo n.º 27
0
        interp_curses.module_info.setupterm_called = True
    finally:
        lltype.free(intp, flavor='raw')

def curses_setupterm_null_llimpl(fd):
    curses_setupterm(lltype.nullptr(rffi.CCHARP.TO), fd)

def curses_setupterm_llimpl(term, fd):
    ll_s = rffi.str2charp(term)
    try:
        curses_setupterm(ll_s, fd)
    finally:
        rffi.free_charp(ll_s)

register_external(interp_curses._curses_setupterm_null,
                  [int], llimpl=curses_setupterm_null_llimpl,
                  export_name='_curses.setupterm_null')
register_external(interp_curses._curses_setupterm,
                  [str, int], llimpl=curses_setupterm_llimpl,
                  export_name='_curses.setupterm')

def check_setup_invoked():
    if not interp_curses.module_info.setupterm_called:
        raise interp_curses.curses_error("must call (at least) setupterm() first")

def tigetstr_llimpl(cap):
    check_setup_invoked()
    ll_cap = rffi.str2charp(cap)
    try:
        ll_res = c_tigetstr(ll_cap)
        num = lltype.cast_ptr_to_int(ll_res)
Ejemplo n.º 28
0
    just_a_placeholder

def envkeys_llimpl():
    environ = os_get_environ()
    result = []
    i = 0
    while environ[i]:
        name_value = rffi.charp2str(environ[i])
        p = name_value.find('=')
        if p >= 0:
            result.append(name_value[:p])
        i += 1
    return result

register_external(r_envkeys, [], [str0],   # returns a list of strings
                  export_name='ll_os.ll_os_envkeys',
                  llimpl=envkeys_llimpl)

# ____________________________________________________________

def r_envitems():
    just_a_placeholder

def r_getenv(name):
    just_a_placeholder     # should return None if name not found

def r_putenv(name, value):
    just_a_placeholder

os_getenv = llexternal('getenv', [rffi.CCHARP], rffi.CCHARP)
os_putenv = llexternal(prefix + 'putenv', [rffi.CCHARP], rffi.INT,
Ejemplo n.º 29
0

def curses_setupterm_null_llimpl(fd):
    curses_setupterm(lltype.nullptr(rffi.CCHARP.TO), fd)


def curses_setupterm_llimpl(term, fd):
    ll_s = rffi.str2charp(term)
    try:
        curses_setupterm(ll_s, fd)
    finally:
        rffi.free_charp(ll_s)


register_external(interp_curses._curses_setupterm_null, [int],
                  llimpl=curses_setupterm_null_llimpl,
                  export_name='_curses.setupterm_null')
register_external(interp_curses._curses_setupterm, [str, int],
                  llimpl=curses_setupterm_llimpl,
                  export_name='_curses.setupterm')


def check_setup_invoked():
    if not interp_curses.module_info.setupterm_called:
        raise interp_curses.curses_error(
            "must call (at least) setupterm() first")


def tigetstr_llimpl(cap):
    check_setup_invoked()
    ll_cap = rffi.str2charp(cap)
Ejemplo n.º 30
0
llimpl_calloc = rffi.llexternal('calloc', [lltype.Signed, lltype.Signed],
                                llmemory.Address,
                                sandboxsafe=True, _nowrapper=True)
llimpl_free = rffi.llexternal('free', [llmemory.Address], lltype.Void,
                              sandboxsafe=True, _nowrapper=True)

def llimpl_arena_malloc(nbytes, zero):
    if zero:
        addr = llimpl_calloc(nbytes, 1)
    else:
        addr = llimpl_malloc(nbytes)
    return addr
llimpl_arena_malloc._always_inline_ = True
register_external(arena_malloc, [int, int], llmemory.Address,
                  'll_arena.arena_malloc',
                  llimpl=llimpl_arena_malloc,
                  llfakeimpl=arena_malloc,
                  sandboxsafe=True)

register_external(arena_free, [llmemory.Address], None, 'll_arena.arena_free',
                  llimpl=llimpl_free,
                  llfakeimpl=arena_free,
                  sandboxsafe=True)

def llimpl_arena_reset(arena_addr, size, zero):
    if zero:
        if zero == 1:
            clear_large_memory_chunk(arena_addr, size)
        elif zero == 3:
            llop.raw_memset(lltype.Void, arena_addr, ord('#'), size)
        elif zero == 4:
Ejemplo n.º 31
0
    def impl_attach_gdb():
        import os
        allow_attach()
        pid = os.getpid()
        gdbpid = os.fork()
        if gdbpid == 0:
            shell = os.environ.get("SHELL") or "/bin/sh"
            sepidx = shell.rfind(os.sep) + 1
            if sepidx > 0:
                argv0 = shell[sepidx:]
            else:
                argv0 = shell
            try:
                os.execv(shell, [argv0, "-c", "gdb -p %d" % pid])
            except OSError as e:
                os.write(2, "Could not start GDB: %s" % (os.strerror(e.errno)))
                raise SystemExit
        else:
            time.sleep(1)  # give the GDB time to attach

else:

    def impl_attach_gdb():
        print "Don't know how to attach GDB on Windows"


register_external(attach_gdb, [],
                  result=None,
                  export_name="impl_attach_gdb",
                  llimpl=impl_attach_gdb)
Ejemplo n.º 32
0
def numeric_formatting():
    """Specialized function to get formatting for numbers"""
    return numeric_formatting_impl()


def numeric_formatting_impl():
    conv = localeconv()
    decimal_point = rffi.charp2str(conv.c_decimal_point)
    thousands_sep = rffi.charp2str(conv.c_thousands_sep)
    grouping = rffi.charp2str(conv.c_grouping)
    return decimal_point, thousands_sep, grouping


register_external(numeric_formatting, [], (str, str, str),
                  llimpl=numeric_formatting_impl,
                  sandboxsafe=True)

_setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP)


def setlocale(category, locale):
    if cConfig.LC_MAX is not None:
        if not cConfig.LC_MIN <= category <= cConfig.LC_MAX:
            raise LocaleError("invalid locale category")
    ll_result = _setlocale(rffi.cast(rffi.INT, category), locale)
    if not ll_result:
        raise LocaleError("unsupported locale setting")
    return rffi.charp2str(ll_result)