Author: Armin Rigo <[email protected]>
Branch: cffi-stdcall
Changeset: r80012:348cafc5db08
Date: 2015-10-07 09:59 +0200
http://bitbucket.org/pypy/pypy/changeset/348cafc5db08/

Log:    Port the rest of the win32-stdcall branch

diff --git a/pypy/module/_cffi_backend/realize_c_type.py 
b/pypy/module/_cffi_backend/realize_c_type.py
--- a/pypy/module/_cffi_backend/realize_c_type.py
+++ b/pypy/module/_cffi_backend/realize_c_type.py
@@ -5,6 +5,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 from pypy.interpreter.error import oefmt
 from pypy.interpreter.baseobjspace import W_Root
+from pypy.module import _cffi_backend
 from pypy.module._cffi_backend.ctypeobj import W_CType
 from pypy.module._cffi_backend import cffi_opcode, newtype, ctypestruct
 from pypy.module._cffi_backend import parse_c_type
@@ -164,16 +165,28 @@
         OP_FUNCTION_END = cffi_opcode.OP_FUNCTION_END
         while getop(opcodes[base_index + num_args]) != OP_FUNCTION_END:
             num_args += 1
-        ellipsis = (getarg(opcodes[base_index + num_args]) & 1) != 0
+        #
+        ellipsis = (getarg(opcodes[base_index + num_args]) & 0x01) != 0
+        abi      = (getarg(opcodes[base_index + num_args]) & 0xFE)
+        if abi == 0:
+            abi = _cffi_backend.FFI_DEFAULT_ABI
+        elif abi == 2:
+            if _cffi_backend.has_stdcall:
+                abi = _cffi_backend.FFI_STDCALL
+            else:
+                abi = _cffi_backend.FFI_DEFAULT_ABI
+        else:
+            raise oefmt(ffi.w_FFIError, "abi number %d not supported", abi)
+        #
         fargs = [realize_c_type(ffi, opcodes, base_index + i)
                  for i in range(num_args)]
-        return fargs, fret, ellipsis
+        return fargs, fret, ellipsis, abi
 
     def unwrap_as_fnptr(self, ffi):
         if self._ctfuncptr is None:
-            fargs, fret, ellipsis = self._unpack(ffi)
+            fargs, fret, ellipsis, abi = self._unpack(ffi)
             self._ctfuncptr = newtype._new_function_type(
-                ffi.space, fargs, fret, ellipsis)
+                ffi.space, fargs, fret, ellipsis, abi)
         return self._ctfuncptr
 
     def unwrap_as_fnptr_in_elidable(self):
@@ -190,7 +203,7 @@
         # type ptr-to-struct.  This is how recompiler.py produces
         # trampoline functions for PyPy.
         if self.nostruct_ctype is None:
-            fargs, fret, ellipsis = self._unpack(ffi)
+            fargs, fret, ellipsis, abi = self._unpack(ffi)
             # 'locs' will be a string of the same length as the final fargs,
             # containing 'A' where a struct argument was detected, and 'R'
             # in first position if a struct return value was detected
@@ -207,7 +220,7 @@
                 locs = ['R'] + locs
                 fret = newtype.new_void_type(ffi.space)
             ctfuncptr = newtype._new_function_type(
-                ffi.space, fargs, fret, ellipsis)
+                ffi.space, fargs, fret, ellipsis, abi)
             if locs == ['\x00'] * len(locs):
                 locs = None
             else:
@@ -218,7 +231,7 @@
                                                           locs[0] == 'R')
 
     def unexpected_fn_type(self, ffi):
-        fargs, fret, ellipsis = self._unpack(ffi)
+        fargs, fret, ellipsis, abi = self._unpack(ffi)
         argnames = [farg.name for farg in fargs]
         if ellipsis:
             argnames.append('...')
diff --git a/pypy/module/_cffi_backend/src/parse_c_type.c 
b/pypy/module/_cffi_backend/src/parse_c_type.c
--- a/pypy/module/_cffi_backend/src/parse_c_type.c
+++ b/pypy/module/_cffi_backend/src/parse_c_type.c
@@ -51,6 +51,9 @@
     TOK_UNSIGNED,
     TOK_VOID,
     TOK_VOLATILE,
+
+    TOK_CDECL,
+    TOK_STDCALL,
 };
 
 typedef struct {
@@ -165,6 +168,8 @@
     switch (*p) {
     case '_':
         if (tok->size == 5 && !memcmp(p, "_Bool", 5))  tok->kind = TOK__BOOL;
+        if (tok->size == 7 && !memcmp(p,"__cdecl",7))  tok->kind = TOK_CDECL;
+        if (tok->size == 9 && !memcmp(p,"__stdcall",9))tok->kind = TOK_STDCALL;
         break;
     case 'c':
         if (tok->size == 4 && !memcmp(p, "char", 4))   tok->kind = TOK_CHAR;
@@ -236,7 +241,7 @@
        type).  The 'outer' argument is the index of the opcode outside
        this "sequel".
      */
-    int check_for_grouping;
+    int check_for_grouping, abi=0;
     _cffi_opcode_t result, *p_current;
 
  header:
@@ -253,6 +258,12 @@
         /* ignored for now */
         next_token(tok);
         goto header;
+    case TOK_CDECL:
+    case TOK_STDCALL:
+        /* must be in a function; checked below */
+        abi = tok->kind;
+        next_token(tok);
+        goto header;
     default:
         break;
     }
@@ -269,6 +280,11 @@
     while (tok->kind == TOK_OPEN_PAREN) {
         next_token(tok);
 
+        if (tok->kind == TOK_CDECL || tok->kind == TOK_STDCALL) {
+            abi = tok->kind;
+            next_token(tok);
+        }
+
         if ((check_for_grouping--) == 1 && (tok->kind == TOK_STAR ||
                                             tok->kind == TOK_CONST ||
                                             tok->kind == TOK_VOLATILE ||
@@ -286,7 +302,14 @@
         }
         else {
             /* function type */
-            int arg_total, base_index, arg_next, has_ellipsis=0;
+            int arg_total, base_index, arg_next, flags=0;
+
+            if (abi == TOK_STDCALL) {
+                flags = 2;
+                /* note that an ellipsis below will overwrite this flags,
+                   which is the goal: variadic functions are always cdecl */
+            }
+            abi = 0;
 
             if (tok->kind == TOK_VOID && get_following_char(tok) == ')') {
                 next_token(tok);
@@ -315,7 +338,7 @@
                     _cffi_opcode_t oarg;
 
                     if (tok->kind == TOK_DOTDOTDOT) {
-                        has_ellipsis = 1;
+                        flags = 1;   /* ellipsis */
                         next_token(tok);
                         break;
                     }
@@ -339,8 +362,7 @@
                     next_token(tok);
                 }
             }
-            tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END,
-                                             has_ellipsis);
+            tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END, flags);
         }
 
         if (tok->kind != TOK_CLOSE_PAREN)
@@ -348,6 +370,9 @@
         next_token(tok);
     }
 
+    if (abi != 0)
+        return parse_error(tok, "expected '('");
+
     while (tok->kind == TOK_OPEN_BRACKET) {
         *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index);
         p_current = tok->output + tok->output_index;
diff --git a/pypy/module/_cffi_backend/test/test_parse_c_type.py 
b/pypy/module/_cffi_backend/test/test_parse_c_type.py
--- a/pypy/module/_cffi_backend/test/test_parse_c_type.py
+++ b/pypy/module/_cffi_backend/test/test_parse_c_type.py
@@ -338,3 +338,17 @@
     # not supported (really obscure):
     #    "char[+5]"
     #    "char['A']"
+
+def test_stdcall_cdecl():
+    assert parse("int __stdcall(int)") == [Prim(cffi_opcode.PRIM_INT),
+                                           '->', Func(0), NoOp(4), FuncEnd(2),
+                                           Prim(cffi_opcode.PRIM_INT)]
+    assert parse("int __stdcall func(int)") == parse("int __stdcall(int)")
+    assert parse("int (__stdcall *)()") == [Prim(cffi_opcode.PRIM_INT),
+                                            NoOp(3), '->', Pointer(1),
+                                            Func(0), FuncEnd(2), 0]
+    assert parse("int (__stdcall *p)()") == parse("int (__stdcall*)()")
+    parse_error("__stdcall int", "identifier expected", 0)
+    parse_error("__cdecl int", "identifier expected", 0)
+    parse_error("int __stdcall", "expected '('", 13)
+    parse_error("int __cdecl", "expected '('", 11)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to