]> granicus.if.org Git - python/commitdiff
Merged revisions 82126-82127 via svnmerge from
authorThomas Heller <theller@ctypes.org>
Mon, 21 Jun 2010 16:00:31 +0000 (16:00 +0000)
committerThomas Heller <theller@ctypes.org>
Mon, 21 Jun 2010 16:00:31 +0000 (16:00 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r82126 | thomas.heller | 2010-06-21 16:00:24 +0200 (Mo, 21 Jun 2010) | 1 line

  Fix #8959 by reverting revision 80761.
........
  r82127 | thomas.heller | 2010-06-21 17:01:18 +0200 (Mo, 21 Jun 2010) | 2 lines

  Add tests for problems reported in issue 8959.
........

16 files changed:
Lib/ctypes/test/test_callbacks.py
Lib/ctypes/test/test_win32.py
Modules/_ctypes/callproc.c
Modules/_ctypes/libffi_msvc/LICENSE [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/README [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/README.ctypes [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/ffi.c [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/ffi.h
Modules/_ctypes/libffi_msvc/ffi_common.h [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/fficonfig.h
Modules/_ctypes/libffi_msvc/ffitarget.h [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/prep_cif.c [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/types.c [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/win32.c [new file with mode: 0644]
Modules/_ctypes/libffi_msvc/win64.asm [new file with mode: 0644]
PCbuild/_ctypes.vcproj

index 1466f26ecc9fdfd0e20aae84f256b6939cd3362d..ea51c336106ca559f5c17823bbf5a27b1d14553e 100644 (file)
@@ -166,6 +166,41 @@ class SampleCallbacksTestCase(unittest.TestCase):
 
         self.assertTrue(diff < 0.01, "%s not less than 0.01" % diff)
 
+    def test_issue_8959_a(self):
+        from ctypes.util import find_library
+        libc_path = find_library("c")
+        if not libc_path:
+            return # cannot test
+        libc = CDLL(libc_path)
+
+        @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
+        def cmp_func(a, b):
+            return a[0] - b[0]
+
+        array = (c_int * 5)(5, 1, 99, 7, 33)
+
+        libc.qsort(array, len(array), sizeof(c_int), cmp_func)
+        self.assertEqual(array[:], [1, 5, 7, 33, 99])
+
+    try:
+        WINFUNCTYPE
+    except NameError:
+        pass
+    else:
+        def test_issue_8959_b(self):
+            from ctypes.wintypes import BOOL, HWND, LPARAM
+            global windowCount
+            windowCount = 0
+
+            @WINFUNCTYPE(BOOL, HWND, LPARAM)
+            def EnumWindowsCallbackFunc(hwnd, lParam):
+                global windowCount
+                windowCount += 1
+                return True #Allow windows to keep enumerating
+
+            windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0)
+            self.assertFalse(windowCount == 0)
+
 ################################################################
 
 if __name__ == '__main__':
index 3c0500d4429445fee85b1336aa2b458994f21dde..5dedd9f1f620f0110e185a7c9d10ecfb2a503c5c 100644 (file)
@@ -6,6 +6,32 @@ import unittest, sys
 
 import _ctypes_test
 
+if sys.platform == "win32" and sizeof(c_void_p) == sizeof(c_int):
+    # Only windows 32-bit has different calling conventions.
+
+    class WindowsTestCase(unittest.TestCase):
+        def test_callconv_1(self):
+            # Testing stdcall function
+
+            IsWindow = windll.user32.IsWindow
+            # ValueError: Procedure probably called with not enough arguments (4 bytes missing)
+            self.assertRaises(ValueError, IsWindow)
+
+            # This one should succeeed...
+            self.assertEqual(0, IsWindow(0))
+
+            # ValueError: Procedure probably called with too many arguments (8 bytes in excess)
+            self.assertRaises(ValueError, IsWindow, 0, 0, 0)
+
+        def test_callconv_2(self):
+            # Calling stdcall function as cdecl
+
+            IsWindow = cdll.user32.IsWindow
+
+            # ValueError: Procedure called with not enough arguments (4 bytes missing)
+            # or wrong calling convention
+            self.assertRaises(ValueError, IsWindow, None)
+
 if sys.platform == "win32":
     class FunctionCallTestCase(unittest.TestCase):
 
index 6e0e22438f0d3fe8c2ffadccf3a6f9702979e075..bec9eb3482b51c7fb256b4f17e97dde56ba46ffd 100644 (file)
@@ -761,6 +761,7 @@ static int _call_function_pointer(int flags,
     ffi_cif cif;
     int cc;
 #ifdef MS_WIN32
+    int delta;
 #ifndef DONT_USE_SEH
     DWORD dwExceptionCode = 0;
     EXCEPTION_RECORD record;
@@ -811,8 +812,9 @@ static int _call_function_pointer(int flags,
 #ifndef DONT_USE_SEH
     __try {
 #endif
+        delta =
 #endif
-        ffi_call(&cif, (void *)pProc, resmem, avalues);
+                ffi_call(&cif, (void *)pProc, resmem, avalues);
 #ifdef MS_WIN32
 #ifndef DONT_USE_SEH
     }
@@ -844,6 +846,35 @@ static int _call_function_pointer(int flags,
         return -1;
     }
 #endif
+#ifdef MS_WIN64
+    if (delta != 0) {
+        PyErr_Format(PyExc_RuntimeError,
+                 "ffi_call failed with code %d",
+                 delta);
+        return -1;
+    }
+#else
+    if (delta < 0) {
+        if (flags & FUNCFLAG_CDECL)
+            PyErr_Format(PyExc_ValueError,
+                     "Procedure called with not enough "
+                     "arguments (%d bytes missing) "
+                     "or wrong calling convention",
+                     -delta);
+        else
+            PyErr_Format(PyExc_ValueError,
+                     "Procedure probably called with not enough "
+                     "arguments (%d bytes missing)",
+                     -delta);
+        return -1;
+    } else if (delta > 0) {
+        PyErr_Format(PyExc_ValueError,
+                 "Procedure probably called with too many "
+                 "arguments (%d bytes in excess)",
+                 delta);
+        return -1;
+    }
+#endif
 #endif
     if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred())
         return -1;
@@ -1116,7 +1147,11 @@ PyObject *_ctypes_callproc(PPROC pProc,
     }
     for (i = 0; i < argcount; ++i) {
         atypes[i] = args[i].ffi_type;
-        if (atypes[i]->type == FFI_TYPE_STRUCT)
+        if (atypes[i]->type == FFI_TYPE_STRUCT 
+#ifdef _WIN64
+            && atypes[i]->size <= sizeof(void *)
+#endif
+            )
             avalues[i] = (void *)args[i].value.p;
         else
             avalues[i] = (void *)&args[i].value;
diff --git a/Modules/_ctypes/libffi_msvc/LICENSE b/Modules/_ctypes/libffi_msvc/LICENSE
new file mode 100644 (file)
index 0000000..f591795
--- /dev/null
@@ -0,0 +1,20 @@
+libffi - Copyright (c) 1996-2003  Red Hat, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+``Software''), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Modules/_ctypes/libffi_msvc/README b/Modules/_ctypes/libffi_msvc/README
new file mode 100644 (file)
index 0000000..1fc2747
--- /dev/null
@@ -0,0 +1,500 @@
+This directory contains the libffi package, which is not part of GCC but
+shipped with GCC as convenience.
+
+Status
+======
+
+libffi-2.00 has not been released yet! This is a development snapshot!
+
+libffi-1.20 was released on October 5, 1998. Check the libffi web
+page for updates: <URL:http://sources.redhat.com/libffi/>.
+
+
+What is libffi?
+===============
+
+Compilers for high level languages generate code that follow certain
+conventions. These conventions are necessary, in part, for separate
+compilation to work. One such convention is the "calling
+convention". The "calling convention" is essentially a set of
+assumptions made by the compiler about where function arguments will
+be found on entry to a function. A "calling convention" also specifies
+where the return value for a function is found.
+
+Some programs may not know at the time of compilation what arguments
+are to be passed to a function. For instance, an interpreter may be
+told at run-time about the number and types of arguments used to call
+a given function. Libffi can be used in such programs to provide a
+bridge from the interpreter program to compiled code.
+
+The libffi library provides a portable, high level programming
+interface to various calling conventions. This allows a programmer to
+call any function specified by a call interface description at run
+time.  
+
+Ffi stands for Foreign Function Interface. A foreign function
+interface is the popular name for the interface that allows code
+written in one language to call code written in another language. The
+libffi library really only provides the lowest, machine dependent
+layer of a fully featured foreign function interface. A layer must
+exist above libffi that handles type conversions for values passed
+between the two languages.
+
+
+Supported Platforms and Prerequisites
+=====================================
+
+Libffi has been ported to:
+
+       SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
+
+       Irix 5.3 & 6.2 (System V/o32 & n32)
+
+       Intel x86 - Linux (System V ABI)
+
+       Alpha - Linux and OSF/1
+
+       m68k - Linux (System V ABI)
+
+       PowerPC - Linux (System V ABI, Darwin, AIX)
+
+       ARM - Linux (System V ABI)
+
+Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
+that other versions will work.  Libffi has also been built and tested
+with the SGI compiler tools.
+
+On PowerPC, the tests failed (see the note below).
+
+You must use GNU make to build libffi. SGI's make will not work.
+Sun's probably won't either.
+       
+If you port libffi to another platform, please let me know! I assume
+that some will be easy (x86 NetBSD), and others will be more difficult
+(HP).
+
+
+Installing libffi
+=================
+
+[Note: before actually performing any of these installation steps,
+ you may wish to read the "Platform Specific Notes" below.]
+
+First you must configure the distribution for your particular
+system. Go to the directory you wish to build libffi in and run the
+"configure" program found in the root directory of the libffi source
+distribution.
+
+You may want to tell configure where to install the libffi library and
+header files. To do that, use the --prefix configure switch.  Libffi
+will install under /usr/local by default. 
+
+If you want to enable extra run-time debugging checks use the the
+--enable-debug configure switch. This is useful when your program dies
+mysteriously while using libffi. 
+
+Another useful configure switch is --enable-purify-safety. Using this
+will add some extra code which will suppress certain warnings when you
+are using Purify with libffi. Only use this switch when using 
+Purify, as it will slow down the library.
+
+Configure has many other options. Use "configure --help" to see them all.
+
+Once configure has finished, type "make". Note that you must be using
+GNU make. SGI's make will not work.  Sun's probably won't either.
+You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
+
+To ensure that libffi is working as advertised, type "make test".
+
+To install the library and header files, type "make install".
+
+
+Using libffi
+============
+
+       The Basics
+       ----------
+
+Libffi assumes that you have a pointer to the function you wish to
+call and that you know the number and types of arguments to pass it,
+as well as the return type of the function.
+
+The first thing you must do is create an ffi_cif object that matches
+the signature of the function you wish to call. The cif in ffi_cif
+stands for Call InterFace. To prepare a call interface object, use the
+following function:
+
+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
+                       unsigned int nargs, 
+                       ffi_type *rtype, ffi_type **atypes);
+
+       CIF is a pointer to the call interface object you wish
+               to initialize.
+
+       ABI is an enum that specifies the calling convention 
+               to use for the call. FFI_DEFAULT_ABI defaults
+               to the system's native calling convention. Other
+               ABI's may be used with care. They are system
+               specific.
+
+       NARGS is the number of arguments this function accepts. 
+               libffi does not yet support vararg functions.
+
+       RTYPE is a pointer to an ffi_type structure that represents
+               the return type of the function. Ffi_type objects
+               describe the types of values. libffi provides
+               ffi_type objects for many of the native C types:
+               signed int, unsigned int, signed char, unsigned char,
+               etc. There is also a pointer ffi_type object and
+               a void ffi_type. Use &ffi_type_void for functions that 
+               don't return values.
+
+       ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
+               If NARGS is 0, this is ignored.
+
+
+ffi_prep_cif will return a status code that you are responsible 
+for checking. It will be one of the following:
+
+       FFI_OK - All is good.
+
+       FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
+               came across is bad.
+
+
+Before making the call, the VALUES vector should be initialized 
+with pointers to the appropriate argument values.
+
+To call the the function using the initialized ffi_cif, use the
+ffi_call function:
+
+void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
+
+       CIF is a pointer to the ffi_cif initialized specifically
+               for this function.
+
+       FN is a pointer to the function you want to call.
+
+       RVALUE is a pointer to a chunk of memory that is to hold the
+               result of the function call. Currently, it must be
+               at least one word in size (except for the n32 version
+               under Irix 6.x, which must be a pointer to an 8 byte 
+               aligned value (a long long). It must also be at least 
+               word aligned (depending on the return type, and the
+               system's alignment requirements). If RTYPE is 
+               &ffi_type_void, this is ignored. If RVALUE is NULL, 
+               the return value is discarded.
+
+       AVALUES is a vector of void* that point to the memory locations
+               holding the argument values for a call.
+               If NARGS is 0, this is ignored.
+
+
+If you are expecting a return value from FN it will have been stored
+at RVALUE.
+
+
+
+       An Example
+       ----------
+
+Here is a trivial example that calls puts() a few times.
+
+    #include <stdio.h>
+    #include <ffi.h>
+    
+    int main()
+    {
+      ffi_cif cif;
+      ffi_type *args[1];
+      void *values[1];
+      char *s;
+      int rc;
+      
+      /* Initialize the argument info vectors */    
+      args[0] = &ffi_type_uint;
+      values[0] = &s;
+      
+      /* Initialize the cif */
+      if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_uint, args) == FFI_OK)
+        {
+          s = "Hello World!";
+          ffi_call(&cif, puts, &rc, values);
+          /* rc now holds the result of the call to puts */
+          
+          /* values holds a pointer to the function's arg, so to 
+            call puts() again all we need to do is change the 
+             value of s */
+          s = "This is cool!";
+          ffi_call(&cif, puts, &rc, values);
+        }
+      
+      return 0;
+    }
+
+
+
+       Aggregate Types
+       ---------------
+
+Although libffi has no special support for unions or bit-fields, it is
+perfectly happy passing structures back and forth. You must first
+describe the structure to libffi by creating a new ffi_type object
+for it. Here is the definition of ffi_type:
+
+    typedef struct _ffi_type
+    {
+      unsigned size;
+      short alignment;
+      short type;
+      struct _ffi_type **elements;
+    } ffi_type;
+    
+All structures must have type set to FFI_TYPE_STRUCT.  You may set
+size and alignment to 0. These will be calculated and reset to the
+appropriate values by ffi_prep_cif().
+
+elements is a NULL terminated array of pointers to ffi_type objects
+that describe the type of the structure elements. These may, in turn,
+be structure elements.
+
+The following example initializes a ffi_type object representing the
+tm struct from Linux's time.h:
+
+                                   struct tm {
+                                       int tm_sec;
+                                       int tm_min;
+                                       int tm_hour;
+                                       int tm_mday;
+                                       int tm_mon;
+                                       int tm_year;
+                                       int tm_wday;
+                                       int tm_yday;
+                                       int tm_isdst;
+                                       /* Those are for future use. */
+                                       long int __tm_gmtoff__;
+                                       __const char *__tm_zone__;
+                                   };
+
+    {
+      ffi_type tm_type;
+      ffi_type *tm_type_elements[12];
+      int i;
+
+      tm_type.size = tm_type.alignment = 0;
+      tm_type.elements = &tm_type_elements;
+    
+      for (i = 0; i < 9; i++)
+          tm_type_elements[i] = &ffi_type_sint;
+
+      tm_type_elements[9] = &ffi_type_slong;
+      tm_type_elements[10] = &ffi_type_pointer;
+      tm_type_elements[11] = NULL;
+
+      /* tm_type can now be used to represent tm argument types and
+        return types for ffi_prep_cif() */
+    }
+
+
+
+Platform Specific Notes
+=======================
+
+       Intel x86
+       ---------
+
+There are no known problems with the x86 port.
+
+       Sun SPARC - SunOS 4.1.3 & Solaris 2.x
+       -------------------------------------
+
+You must use GNU Make to build libffi on Sun platforms.
+
+       MIPS - Irix 5.3 & 6.x
+       ---------------------
+
+Irix 6.2 and better supports three different calling conventions: o32,
+n32 and n64. Currently, libffi only supports both o32 and n32 under
+Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be
+configured for whichever calling convention it was built for.
+
+By default, the configure script will try to build libffi with the GNU
+development tools. To build libffi with the SGI development tools, set
+the environment variable CC to either "cc -32" or "cc -n32" before
+running configure under Irix 6.x (depending on whether you want an o32
+or n32 library), or just "cc" for Irix 5.3.
+
+With the n32 calling convention, when returning structures smaller
+than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned.
+Here's one way of forcing this:
+
+       double struct_storage[2];
+       my_small_struct *s = (my_small_struct *) struct_storage;  
+       /* Use s for RVALUE */
+
+If you don't do this you are liable to get spurious bus errors. 
+
+"long long" values are not supported yet.
+
+You must use GNU Make to build libffi on SGI platforms.
+
+       ARM - System V ABI
+       ------------------
+
+The ARM port was performed on a NetWinder running ARM Linux ELF
+(2.0.31) and gcc 2.8.1.
+
+
+
+       PowerPC System V ABI
+       --------------------
+
+There are two `System V ABI's which libffi implements for PowerPC.
+They differ only in how small structures are returned from functions.
+
+In the FFI_SYSV version, structures that are 8 bytes or smaller are
+returned in registers.  This is what GCC does when it is configured
+for solaris, and is what the System V ABI I have (dated September
+1995) says.
+
+In the FFI_GCC_SYSV version, all structures are returned the same way:
+by passing a pointer as the first argument to the function.  This is
+what GCC does when it is configured for linux or a generic sysv
+target.
+
+EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a
+inconsistency with the SysV ABI: When a procedure is called with many
+floating-point arguments, some of them get put on the stack.  They are
+all supposed to be stored in double-precision format, even if they are
+only single-precision, but EGCS stores single-precision arguments as
+single-precision anyway.  This causes one test to fail (the `many
+arguments' test).
+
+
+What's With The Crazy Comments?
+===============================
+
+You might notice a number of cryptic comments in the code, delimited
+by /*@ and @*/. These are annotations read by the program LCLint, a
+tool for statically checking C programs. You can read all about it at
+<http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>.
+
+
+History
+=======
+
+1.20 Oct-5-98
+       Raffaele Sena produces ARM port.
+
+1.19 Oct-5-98
+       Fixed x86 long double and long long return support.
+       m68k bug fixes from Andreas Schwab.
+       Patch for DU assembler compatibility for the Alpha from Richard
+       Henderson.
+
+1.18 Apr-17-98
+       Bug fixes and MIPS configuration changes.
+
+1.17 Feb-24-98
+       Bug fixes and m68k port from Andreas Schwab. PowerPC port from
+       Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
+
+1.16 Feb-11-98
+       Richard Henderson produces Alpha port.
+
+1.15 Dec-4-97
+       Fixed an n32 ABI bug. New libtool, auto* support.
+
+1.14 May-13-97
+       libtool is now used to generate shared and static libraries.
+       Fixed a minor portability problem reported by Russ McManus
+       <mcmanr@eq.gs.com>.
+
+1.13 Dec-2-96
+       Added --enable-purify-safety to keep Purify from complaining
+       about certain low level code.
+       Sparc fix for calling functions with < 6 args.
+       Linux x86 a.out fix.
+
+1.12 Nov-22-96
+       Added missing ffi_type_void, needed for supporting void return 
+       types. Fixed test case for non MIPS machines. Cygnus Support 
+       is now Cygnus Solutions. 
+
+1.11 Oct-30-96
+       Added notes about GNU make.
+
+1.10 Oct-29-96
+       Added configuration fix for non GNU compilers.
+
+1.09 Oct-29-96
+       Added --enable-debug configure switch. Clean-ups based on LCLint 
+       feedback. ffi_mips.h is always installed. Many configuration 
+       fixes. Fixed ffitest.c for sparc builds.
+
+1.08 Oct-15-96
+       Fixed n32 problem. Many clean-ups.
+
+1.07 Oct-14-96
+       Gordon Irlam rewrites v8.S again. Bug fixes.
+
+1.06 Oct-14-96
+       Gordon Irlam improved the sparc port. 
+
+1.05 Oct-14-96
+       Interface changes based on feedback.
+
+1.04 Oct-11-96
+       Sparc port complete (modulo struct passing bug).
+
+1.03 Oct-10-96
+       Passing struct args, and returning struct values works for
+       all architectures/calling conventions. Expanded tests.
+
+1.02 Oct-9-96
+       Added SGI n32 support. Fixed bugs in both o32 and Linux support.
+       Added "make test".
+
+1.01 Oct-8-96
+       Fixed float passing bug in mips version. Restructured some
+       of the code. Builds cleanly with SGI tools.
+
+1.00 Oct-7-96
+       First release. No public announcement.
+
+
+Authors & Credits
+=================
+
+libffi was written by Anthony Green <green@cygnus.com>.
+
+Portions of libffi were derived from Gianni Mariani's free gencall
+library for Silicon Graphics machines.
+
+The closure mechanism was designed and implemented by Kresten Krab
+Thorup.
+
+The Sparc port was derived from code contributed by the fine folks at
+Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
+made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
+
+The Alpha port was written by Richard Henderson at Cygnus Solutions.
+
+Andreas Schwab ported libffi to m68k Linux and provided a number of
+bug fixes.
+
+Geoffrey Keating ported libffi to the PowerPC.
+
+Raffaele Sena ported libffi to the ARM.
+
+Jesper Skov and Andrew Haley both did more than their fair share of
+stepping through the code and tracking down bugs.
+
+Thanks also to Tom Tromey for bug fixes and configuration help.
+
+Thanks to Jim Blandy, who provided some useful feedback on the libffi
+interface.
+
+If you have a problem, or have found a bug, please send a note to
+green@cygnus.com.
diff --git a/Modules/_ctypes/libffi_msvc/README.ctypes b/Modules/_ctypes/libffi_msvc/README.ctypes
new file mode 100644 (file)
index 0000000..17e8a40
--- /dev/null
@@ -0,0 +1,7 @@
+The purpose is to hack the libffi sources so that they can be compiled
+with MSVC, and to extend them so that they have the features I need
+for ctypes.
+
+I retrieved the libffi sources from the gcc cvs repository on
+2004-01-27.  Then I did 'configure' in a 'build' subdirectory on a x86
+linux system, and copied the files I found useful.
diff --git a/Modules/_ctypes/libffi_msvc/ffi.c b/Modules/_ctypes/libffi_msvc/ffi.c
new file mode 100644 (file)
index 0000000..763d179
--- /dev/null
@@ -0,0 +1,457 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
+           Copyright (c) 2002  Ranjit Mathew
+           Copyright (c) 2002  Bo Thorsen
+           Copyright (c) 2002  Roger Sayle
+   
+   x86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+extern void Py_FatalError(const char *msg);
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += sizeof(void *);
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(void *) - 1) & (size_t) argp)
+       argp = (char *) ALIGN(argp, sizeof(void *));
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT8:
+             *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT16:
+             *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT16:
+             *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT32:
+             *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT32:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_STRUCT:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+       }
+      else
+       {
+         memcpy(argp, *p_argv, z);
+       }
+      p_argv++;
+      argp += z;
+    }
+
+  if (argp - stack > ecif->cif->bytes) 
+    {
+      Py_FatalError("FFI BUG: not enough stack space for arguments");
+    }
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_LONGDOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_UINT64:
+#ifdef _WIN64
+    case FFI_TYPE_POINTER:
+#endif
+      cif->flags = FFI_TYPE_SINT64;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+#ifdef _WIN32
+extern int
+ffi_call_x86(void (*)(char *, extended_cif *), 
+            /*@out@*/ extended_cif *, 
+            unsigned, unsigned, 
+            /*@out@*/ unsigned *, 
+            void (*fn)());
+#endif
+
+#ifdef _WIN64
+extern int
+ffi_call_AMD64(void (*)(char *, extended_cif *),
+                /*@out@*/ extended_cif *,
+                unsigned, unsigned,
+                /*@out@*/ unsigned *,
+                void (*fn)());
+#endif
+
+int
+ffi_call(/*@dependent@*/ ffi_cif *cif, 
+        void (*fn)(), 
+        /*@out@*/ void *rvalue, 
+        /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+#if !defined(_WIN64)
+    case FFI_SYSV:
+    case FFI_STDCALL:
+      return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes, 
+                         cif->flags, ecif.rvalue, fn);
+      break;
+#else
+    case FFI_SYSV:
+      /*@-usedef@*/
+      /* Function call needs at least 40 bytes stack size, on win64 AMD64 */
+      return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes ? cif->bytes : 40,
+                          cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#endif
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+  return -1; /* theller: Hrm. */
+}
+
+
+/** private members **/
+
+static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
+                                         void** args, ffi_cif* cif);
+/* This function is jumped to by the trampoline */
+
+#ifdef _WIN64
+void *
+#else
+static void __fastcall
+#endif
+ffi_closure_SYSV (ffi_closure *closure, int *argp)
+{
+  // this is our return value storage
+  long double    res;
+
+  // our various things...
+  ffi_cif       *cif;
+  void         **arg_area;
+  unsigned short rtype;
+  void          *resp = (void*)&res;
+  void *args = &argp[1];
+
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+
+  /* this call will initialize ARG_AREA, such that each
+   * element in that array points to the corresponding 
+   * value on the stack; and if the function returns
+   * a structure, it will re-set RESP to point to the
+   * structure return address.  */
+
+  ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
+  
+  (closure->fun) (cif, resp, arg_area, closure->user_data);
+
+  rtype = cif->flags;
+
+#if defined(_WIN32) && !defined(_WIN64)
+#ifdef _MSC_VER
+  /* now, do a generic return based on the value of rtype */
+  if (rtype == FFI_TYPE_INT)
+    {
+           _asm mov eax, resp ;
+           _asm mov eax, [eax] ;
+    }
+  else if (rtype == FFI_TYPE_FLOAT)
+    {
+           _asm mov eax, resp ;
+           _asm fld DWORD PTR [eax] ;
+//      asm ("flds (%0)" : : "r" (resp) : "st" );
+    }
+  else if (rtype == FFI_TYPE_DOUBLE)
+    {
+           _asm mov eax, resp ;
+           _asm fld QWORD PTR [eax] ;
+//      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
+    }
+  else if (rtype == FFI_TYPE_LONGDOUBLE)
+    {
+//      asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
+    }
+  else if (rtype == FFI_TYPE_SINT64)
+    {
+           _asm mov edx, resp ;
+           _asm mov eax, [edx] ;
+           _asm mov edx, [edx + 4] ;
+//      asm ("movl 0(%0),%%eax;"
+//        "movl 4(%0),%%edx" 
+//        : : "r"(resp)
+//        : "eax", "edx");
+    }
+#else
+  /* now, do a generic return based on the value of rtype */
+  if (rtype == FFI_TYPE_INT)
+    {
+      asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
+    }
+  else if (rtype == FFI_TYPE_FLOAT)
+    {
+      asm ("flds (%0)" : : "r" (resp) : "st" );
+    }
+  else if (rtype == FFI_TYPE_DOUBLE)
+    {
+      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
+    }
+  else if (rtype == FFI_TYPE_LONGDOUBLE)
+    {
+      asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
+    }
+  else if (rtype == FFI_TYPE_SINT64)
+    {
+      asm ("movl 0(%0),%%eax;"
+          "movl 4(%0),%%edx" 
+          : : "r"(resp)
+          : "eax", "edx");
+    }
+#endif
+#endif
+
+#ifdef _WIN64
+  /* The result is returned in rax.  This does the right thing for
+     result types except for floats; we have to 'mov xmm0, rax' in the
+     caller to correct this.
+  */
+  return *(void **)resp;
+#endif
+}
+
+/*@-exportheader@*/
+static void 
+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
+                           void **avalue, ffi_cif *cif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
+    *rvalue = *(void **) argp;
+    argp += 4;
+  }
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(char *) - 1) & (size_t) argp) {
+       argp = (char *) ALIGN(argp, sizeof(char*));
+      }
+
+      z = (*p_arg)->size;
+
+      /* because we're little endian, this is what it turns into.   */
+
+      *p_argv = (void*) argp;
+
+      p_argv++;
+      argp += z;
+    }
+  
+  return;
+}
+
+/* the cif must already be prep'ed */
+extern void ffi_closure_OUTER();
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data)
+{
+  short bytes;
+  char *tramp;
+#ifdef _WIN64
+  int mask;
+#endif
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+  
+  if (cif->abi == FFI_SYSV)
+    bytes = 0;
+#if !defined(_WIN64)
+  else if (cif->abi == FFI_STDCALL)
+    bytes = cif->bytes;
+#endif
+  else
+    return FFI_BAD_ABI;
+
+  tramp = &closure->tramp[0];
+
+#define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1
+#define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*)
+#define SHORT(x) *(short*)tramp = x, tramp += sizeof(short)
+#define INT(x) *(int*)tramp = x, tramp += sizeof(int)
+
+#ifdef _WIN64
+  if (cif->nargs >= 1 &&
+      (cif->arg_types[0]->type == FFI_TYPE_FLOAT
+       || cif->arg_types[0]->type == FFI_TYPE_DOUBLE))
+    mask |= 1;
+  if (cif->nargs >= 2 &&
+      (cif->arg_types[1]->type == FFI_TYPE_FLOAT
+       || cif->arg_types[1]->type == FFI_TYPE_DOUBLE))
+    mask |= 2;
+  if (cif->nargs >= 3 &&
+      (cif->arg_types[2]->type == FFI_TYPE_FLOAT
+       || cif->arg_types[2]->type == FFI_TYPE_DOUBLE))
+    mask |= 4;
+  if (cif->nargs >= 4 &&
+      (cif->arg_types[3]->type == FFI_TYPE_FLOAT
+       || cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
+    mask |= 8;
+
+  /* 41 BB ----         mov         r11d,mask */
+  BYTES("\x41\xBB"); INT(mask);
+
+  /* 48 B8 --------     mov         rax, closure                       */
+  BYTES("\x48\xB8"); POINTER(closure);
+
+  /* 49 BA --------     mov         r10, ffi_closure_OUTER */
+  BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER);
+
+  /* 41 FF E2           jmp         r10 */
+  BYTES("\x41\xFF\xE2");
+
+#else
+
+  /* mov ecx, closure */
+  BYTES("\xb9"); POINTER(closure);
+
+  /* mov edx, esp */
+  BYTES("\x8b\xd4");
+
+  /* call ffi_closure_SYSV */
+  BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4));
+
+  /* ret bytes */
+  BYTES("\xc2");
+  SHORT(bytes);
+  
+#endif
+
+  if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE)
+    Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__);
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
index 2db14363354e83f37eb432d3abc736a087eb7f16..a88d8744f7f240f7f7d83ce28ca22825ddda6bee 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------*-C-*-
-   libffi @VERSION@ - Copyright (c) 1996-2003, 2007, 2008  Red Hat, Inc.
+   libffi 2.00-beta - Copyright (c) 1996-2003  Red Hat, Inc.
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.
 
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-   DEALINGS IN THE SOFTWARE.
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
 
    ----------------------------------------------------------------------- */
 
@@ -57,7 +56,7 @@ extern "C" {
 #endif
 
 /* Specify which architecture libffi is configured for. */
-/* #define @TARGET@ */
+//XXX #define X86
 
 /* ---- System configuration information --------------------------------- */
 
@@ -65,10 +64,6 @@ extern "C" {
 
 #ifndef LIBFFI_ASM
 
-#ifdef _MSC_VER
-#define __attribute__(X)
-#endif
-
 #include <stddef.h>
 #include <limits.h>
 
@@ -84,21 +79,12 @@ extern "C" {
 #  ifdef __GNUC__
 #   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
 #  endif
+#  ifdef _MSC_VER
+#   define FFI_LONG_LONG_MAX _I64_MAX
+#  endif
 # endif
 #endif
 
-/* The closure code assumes that this works on pointers, i.e. a size_t */
-/* can hold a pointer.                                                 */
-
-typedef struct _ffi_type
-{
-  size_t size;
-  unsigned short alignment;
-  unsigned short type;
-  struct _ffi_type **elements;
-} ffi_type;
-
-#ifndef LIBFFI_HIDE_BASIC_TYPES
 #if SCHAR_MAX == 127
 # define ffi_type_uchar                ffi_type_uint8
 # define ffi_type_schar                ffi_type_sint8
@@ -129,23 +115,26 @@ typedef struct _ffi_type
  #error "int size not supported"
 #endif
 
+#define ffi_type_ulong         ffi_type_uint64
+#define ffi_type_slong         ffi_type_sint64
 #if LONG_MAX == 2147483647
 # if FFI_LONG_LONG_MAX != 9223372036854775807
- #error "no 64-bit data type supported"
 #error "no 64-bit data type supported"
 # endif
 #elif LONG_MAX != 9223372036854775807
  #error "long size not supported"
 #endif
 
-#if LONG_MAX == 2147483647
-# define ffi_type_ulong        ffi_type_uint32
-# define ffi_type_slong        ffi_type_sint32
-#elif LONG_MAX == 9223372036854775807
-# define ffi_type_ulong        ffi_type_uint64
-# define ffi_type_slong        ffi_type_sint64
-#else
- #error "long size not supported"
-#endif
+/* The closure code assumes that this works on pointers, i.e. a size_t */
+/* can hold a pointer.                                                 */
+
+typedef struct _ffi_type
+{
+  size_t size;
+  unsigned short alignment;
+  unsigned short type;
+  /*@null@*/ struct _ffi_type **elements;
+} ffi_type;
 
 /* These are defined in types.c */
 extern ffi_type ffi_type_void;
@@ -159,19 +148,14 @@ extern ffi_type ffi_type_uint64;
 extern ffi_type ffi_type_sint64;
 extern ffi_type ffi_type_float;
 extern ffi_type ffi_type_double;
+extern ffi_type ffi_type_longdouble;
 extern ffi_type ffi_type_pointer;
 
-#if HAVE_LONG_DOUBLE
-extern ffi_type ffi_type_longdouble;
-#else
-#define ffi_type_longdouble ffi_type_double
-#endif
-#endif /* LIBFFI_HIDE_BASIC_TYPES */
 
 typedef enum {
   FFI_OK = 0,
   FFI_BAD_TYPEDEF,
-  FFI_BAD_ABI
+  FFI_BAD_ABI 
 } ffi_status;
 
 typedef unsigned FFI_TYPE;
@@ -179,8 +163,8 @@ typedef unsigned FFI_TYPE;
 typedef struct {
   ffi_abi abi;
   unsigned nargs;
-  ffi_type **arg_types;
-  ffi_type *rtype;
+  /*@dependent@*/ ffi_type **arg_types;
+  /*@dependent@*/ ffi_type *rtype;
   unsigned bytes;
   unsigned flags;
 #ifdef FFI_EXTRA_CIF_FIELDS
@@ -190,16 +174,10 @@ typedef struct {
 
 /* ---- Definitions for the raw API -------------------------------------- */
 
-#ifndef FFI_SIZEOF_ARG
-# if LONG_MAX == 2147483647
-#  define FFI_SIZEOF_ARG        4
-# elif LONG_MAX == 9223372036854775807
-#  define FFI_SIZEOF_ARG        8
-# endif
-#endif
-
-#ifndef FFI_SIZEOF_JAVA_RAW
-#  define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
+#ifdef _WIN64
+#define FFI_SIZEOF_ARG 8
+#else
+#define FFI_SIZEOF_ARG 4
 #endif
 
 typedef union {
@@ -210,25 +188,10 @@ typedef union {
   void*     ptr;
 } ffi_raw;
 
-#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
-/* This is a special case for mips64/n32 ABI (and perhaps others) where
-   sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8.  */
-typedef union {
-  signed int   sint;
-  unsigned int uint;
-  float                flt;
-  char         data[FFI_SIZEOF_JAVA_RAW];
-  void*                ptr;
-} ffi_java_raw;
-#else
-typedef ffi_raw ffi_java_raw;
-#endif
-
-
-void ffi_raw_call (ffi_cif *cif,
-                  void (*fn)(void),
-                  void *rvalue,
-                  ffi_raw *avalue);
+void ffi_raw_call (/*@dependent@*/ ffi_cif *cif, 
+                  void (*fn)(), 
+                  /*@out@*/ void *rvalue, 
+                  /*@dependent@*/ ffi_raw *avalue);
 
 void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
 void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
@@ -238,35 +201,25 @@ size_t ffi_raw_size (ffi_cif *cif);
 /* packing, even on 64-bit machines.  I.e. on 64-bit machines          */
 /* longs and doubles are followed by an empty 64-bit word.             */
 
-void ffi_java_raw_call (ffi_cif *cif,
-                       void (*fn)(void),
-                       void *rvalue,
-                       ffi_java_raw *avalue);
+void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, 
+                       void (*fn)(), 
+                       /*@out@*/ void *rvalue, 
+                       /*@dependent@*/ ffi_raw *avalue);
 
-void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
-void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
 size_t ffi_java_raw_size (ffi_cif *cif);
 
 /* ---- Definitions for closures ----------------------------------------- */
 
 #if FFI_CLOSURES
 
-#ifdef _MSC_VER
-__declspec(align(8))
-#endif
 typedef struct {
   char tramp[FFI_TRAMPOLINE_SIZE];
   ffi_cif   *cif;
   void     (*fun)(ffi_cif*,void*,void**,void*);
   void      *user_data;
-#ifdef __GNUC__
-} ffi_closure __attribute__((aligned (8)));
-#else
 } ffi_closure;
-#endif
-
-void *ffi_closure_alloc (size_t size, void **code);
-void ffi_closure_free (void *);
 
 ffi_status
 ffi_prep_closure (ffi_closure*,
@@ -274,13 +227,6 @@ ffi_prep_closure (ffi_closure*,
                  void (*fun)(ffi_cif*,void*,void**,void*),
                  void *user_data);
 
-ffi_status
-ffi_prep_closure_loc (ffi_closure*,
-                     ffi_cif *,
-                     void (*fun)(ffi_cif*,void*,void**,void*),
-                     void *user_data,
-                     void*codeloc);
-
 typedef struct {
   char tramp[FFI_TRAMPOLINE_SIZE];
 
@@ -302,27 +248,6 @@ typedef struct {
 
 } ffi_raw_closure;
 
-typedef struct {
-  char tramp[FFI_TRAMPOLINE_SIZE];
-
-  ffi_cif   *cif;
-
-#if !FFI_NATIVE_RAW_API
-
-  /* if this is enabled, then a raw closure has the same layout 
-     as a regular closure.  We use this to install an intermediate 
-     handler to do the transaltion, void** -> ffi_raw*. */
-
-  void     (*translate_args)(ffi_cif*,void*,void**,void*);
-  void      *this_closure;
-
-#endif
-
-  void     (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
-  void      *user_data;
-
-} ffi_java_raw_closure;
-
 ffi_status
 ffi_prep_raw_closure (ffi_raw_closure*,
                      ffi_cif *cif,
@@ -330,42 +255,29 @@ ffi_prep_raw_closure (ffi_raw_closure*,
                      void *user_data);
 
 ffi_status
-ffi_prep_raw_closure_loc (ffi_raw_closure*,
-                         ffi_cif *cif,
-                         void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-                         void *user_data,
-                         void *codeloc);
-
-ffi_status
-ffi_prep_java_raw_closure (ffi_java_raw_closure*,
+ffi_prep_java_raw_closure (ffi_raw_closure*,
                           ffi_cif *cif,
-                          void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
+                          void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
                           void *user_data);
 
-ffi_status
-ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
-                              ffi_cif *cif,
-                              void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-                              void *user_data,
-                              void *codeloc);
-
 #endif /* FFI_CLOSURES */
 
 /* ---- Public interface definition -------------------------------------- */
 
-ffi_status ffi_prep_cif(ffi_cif *cif,
+ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, 
                        ffi_abi abi,
-                       unsigned int nargs,
-                       ffi_type *rtype,
-                       ffi_type **atypes);
+                       unsigned int nargs, 
+                       /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
+                       /*@dependent@*/ ffi_type **atypes);
 
-void ffi_call(ffi_cif *cif,
-             void (*fn)(void),
-             void *rvalue,
-             void **avalue);
+int
+ffi_call(/*@dependent@*/ ffi_cif *cif, 
+        void (*fn)(), 
+        /*@out@*/ void *rvalue, 
+        /*@dependent@*/ void **avalue);
 
 /* Useful for eliminating compiler warnings */
-#define FFI_FN(f) ((void (*)(void))f)
+#define FFI_FN(f) ((void (*)())f)
 
 /* ---- Definitions shared with assembly code ---------------------------- */
 
@@ -376,7 +288,7 @@ void ffi_call(ffi_cif *cif,
 #define FFI_TYPE_INT        1
 #define FFI_TYPE_FLOAT      2    
 #define FFI_TYPE_DOUBLE     3
-#if HAVE_LONG_DOUBLE
+#if 1
 #define FFI_TYPE_LONGDOUBLE 4
 #else
 #define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
@@ -400,3 +312,4 @@ void ffi_call(ffi_cif *cif,
 #endif
 
 #endif
+
diff --git a/Modules/_ctypes/libffi_msvc/ffi_common.h b/Modules/_ctypes/libffi_msvc/ffi_common.h
new file mode 100644 (file)
index 0000000..43fb83b
--- /dev/null
@@ -0,0 +1,77 @@
+/* -----------------------------------------------------------------------
+   ffi_common.h - Copyright (c) 1996  Red Hat, Inc.
+
+   Common internal definitions and macros. Only necessary for building
+   libffi.
+   ----------------------------------------------------------------------- */
+
+#ifndef FFI_COMMON_H
+#define FFI_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <fficonfig.h>
+#include <malloc.h>
+
+/* Check for the existence of memcpy. */
+#if STDC_HEADERS
+# include <string.h>
+#else
+# ifndef HAVE_MEMCPY
+#  define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#if defined(FFI_DEBUG) 
+#include <stdio.h>
+#endif
+
+#ifdef FFI_DEBUG
+/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
+void ffi_stop_here(void);
+void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
+
+#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
+#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
+#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
+#else
+#define FFI_ASSERT(x) 
+#define FFI_ASSERT_AT(x, f, l)
+#define FFI_ASSERT_VALID_TYPE(x)
+#endif
+
+#define ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+1)
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
+
+/* Extended cif, used in callback from assembly routine */
+typedef struct
+{
+  /*@dependent@*/ ffi_cif *cif;
+  /*@dependent@*/ void *rvalue;
+  /*@dependent@*/ void **avalue;
+} extended_cif;
+
+/* Terse sized type definitions.  */
+typedef unsigned int UINT8  __attribute__((__mode__(__QI__)));
+typedef signed int   SINT8  __attribute__((__mode__(__QI__)));
+typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
+typedef signed int   SINT16 __attribute__((__mode__(__HI__)));
+typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
+typedef signed int   SINT32 __attribute__((__mode__(__SI__)));
+typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
+typedef signed int   SINT64 __attribute__((__mode__(__DI__)));
+
+typedef float FLOAT32;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
index 26ad64bb85f1668f39d9bbc07ef7f96f2abf7c5a..c14f653ec894cfd8b1a868feea04092c74a8844a 100644 (file)
 /* fficonfig.h.  Originally created by configure, now hand_maintained for MSVC. */
 
-/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
+/* fficonfig.h.  Generated automatically by configure.  */
+/* fficonfig.h.in.  Generated automatically from configure.in by autoheader.  */
 
-/* Define if building universal (internal helper macro) */
-/* #undef AC_APPLE_UNIVERSAL_BUILD */
+/* Define this for MSVC, but not for mingw32! */
+#ifdef _MSC_VER
+#define __attribute__(x) /* */
+#endif
+#define alloca _alloca
 
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-   systems. This function is required for `alloca.c' support on those systems.
-   */
-/* #undef CRAY_STACKSEG_END */
+/*----------------------------------------------------------------*/
 
-/* Define to 1 if using `alloca.c'. */
+/* Define if using alloca.c.  */
 /* #undef C_ALLOCA */
 
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #undef EH_FRAME_FLAGS */
-
-/* Define this if you want extra debugging. */
-/* #undef FFI_DEBUG */
-
-/* Cannot use malloc on this target, so, we revert to alternative means */
-/* #undef FFI_MMAP_EXEC_WRIT */
-
-/* Define this is you do not want support for the raw API. */
-#define FFI_NO_RAW_API 1
-
-/* Define this is you do not want support for aggregate types. */
-/* #undef FFI_NO_STRUCTS */
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+/* #undef CRAY_STACKSEG_END */
 
-/* Define to 1 if you have `alloca', as a function or macro. */
+/* Define if you have alloca, as a function or macro.  */
 #define HAVE_ALLOCA 1
 
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
-   */
-/* #undef HAVE_ALLOCA_H */
-
-/* Define if your assembler supports .cfi_* directives. */
-/* #undef HAVE_AS_CFI_PSEUDO_OP */
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+/* #define HAVE_ALLOCA_H 1 */
 
-/* Define if your assembler supports .register. */
-/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-
-/* Define if your assembler and linker support unaligned PC relative relocs.
-   */
-/* #undef HAVE_AS_SPARC_UA_PCREL */
-
-/* Define if your assembler supports PC relative relocs. */
-/* #undef HAVE_AS_X86_PCREL */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-/* #undef HAVE_DLFCN_H */
-
-/* Define if __attribute__((visibility("hidden"))) is supported. */
-/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-/* #undef HAVE_INTTYPES_H */
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
 
-/* Define if you have the long double type and it is bigger than a double */
-/* #undef HAVE_LONG_DOUBLE */
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
 
-/* Define to 1 if you have the `memcpy' function. */
+/* Define if you have the memcpy function.  */
 #define HAVE_MEMCPY 1
 
-/* Define to 1 if you have the <memory.h> header file. */
-/* #undef HAVE_MEMORY_H */
-
-/* Define to 1 if you have the `mmap' function. */
-/* #undef HAVE_MMAP */
-
-/* Define if mmap with MAP_ANON(YMOUS) works. */
-/* #undef HAVE_MMAP_ANON */
-
-/* Define if mmap of /dev/zero works. */
-/* #undef HAVE_MMAP_DEV_ZERO */
-
 /* Define if read-only mmap of a plain file works. */
-/* #undef HAVE_MMAP_FILE */
+//#define HAVE_MMAP_FILE 1
 
-/* Define if .eh_frame sections should be read-only. */
-/* #undef HAVE_RO_EH_FRAME */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-/* #undef HAVE_SYS_MMAN_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-/* #undef HAVE_SYS_STAT_H */
+/* Define if mmap of /dev/zero works. */
+//#define HAVE_MMAP_DEV_ZERO 1
 
-/* Define to 1 if you have the <sys/types.h> header file. */
-/* #undef HAVE_SYS_TYPES_H */
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+//#define HAVE_MMAP_ANON 1
 
-/* Define to 1 if you have the <unistd.h> header file. */
-/* #undef HAVE_UNISTD_H */
+/* The number of bytes in type double */
+#define SIZEOF_DOUBLE 8
 
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
-   */
-/* #undef LT_OBJDIR */
+/* The number of bytes in type long double */
+#define SIZEOF_LONG_DOUBLE 12
 
-/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-/* #undef NO_MINUS_C_MINUS_O */
+/* Define if you have the long double type and it is bigger than a double */
+#define HAVE_LONG_DOUBLE 1
 
-/* Name of package */
-/* #undef PACKAGE */
+/* whether byteorder is bigendian */
+/* #undef WORDS_BIGENDIAN */
 
-/* Define to the address where bug reports for this package should be sent. */
-/* #undef PACKAGE_BUGREPORT */
+/* Define if the host machine stores words of multi-word integers in
+   big-endian order. */
+/* #undef HOST_WORDS_BIG_ENDIAN */
 
-/* Define to the full name of this package. */
-/* #undef PACKAGE_NAME */
+/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
+#define BYTEORDER 1234
 
-/* Define to the full name and version of this package. */
-/* #undef PACKAGE_STRING */
+/* Define if your assembler and linker support unaligned PC relative relocs. */
+/* #undef HAVE_AS_SPARC_UA_PCREL */
 
-/* Define to the one symbol short name of this package. */
-/* #undef PACKAGE_TARNAME */
+/* Define if your assembler supports .register. */
+/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
 
-/* Define to the home page for this package. */
-/* #undef PACKAGE_URL */
+/* Define if .eh_frame sections should be read-only. */
+/* #undef HAVE_RO_EH_FRAME */
 
-/* Define to the version of this package. */
-/* #undef PACKAGE_VERSION */
+/* Define to the flags needed for the .section .eh_frame directive. */
+/* #define EH_FRAME_FLAGS "aw" */
 
-/* The size of `double', as computed by sizeof. */
-#define SIZEOF_DOUBLE 8
+/* Define to the flags needed for the .section .eh_frame directive. */
+/* #define EH_FRAME_FLAGS "aw" */
 
-/* The size of `long double', as computed by sizeof. */
-#undef SIZEOF_LONG_DOUBLE
+/* Define this if you want extra debugging. */
+/* #undef FFI_DEBUG */
 
-/* If using the C implementation of alloca, define if you know the
-   direction of stack growth for your system; otherwise it will be
-   automatically deduced at runtime.
-       STACK_DIRECTION > 0 => grows toward higher addresses
-       STACK_DIRECTION < 0 => grows toward lower addresses
-       STACK_DIRECTION = 0 => direction of growth unknown */
-/* #undef STACK_DIRECTION */
+/* Define this is you do not want support for aggregate types. */
+/* #undef FFI_NO_STRUCTS */
 
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
+/* Define this is you do not want support for the raw API. */
+/* #undef FFI_NO_RAW_API */
 
-/* Define this if you are using Purify and want to suppress spurious messages.
-   */
+/* Define this if you are using Purify and want to suppress spurious messages. */
 /* #undef USING_PURIFY */
 
-/* Version number of package */
-/* #undef VERSION */
-
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
-   significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-#  define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-#  undef WORDS_BIGENDIAN
-# endif
-#endif
-
-
-#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
-#ifdef LIBFFI_ASM
-#define FFI_HIDDEN(name) .hidden name
-#else
-#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
-#endif
-#else
-#ifdef LIBFFI_ASM
-#define FFI_HIDDEN(name)
-#else
-#define FFI_HIDDEN
-#endif
-#endif
-
diff --git a/Modules/_ctypes/libffi_msvc/ffitarget.h b/Modules/_ctypes/libffi_msvc/ffitarget.h
new file mode 100644 (file)
index 0000000..85f5ee8
--- /dev/null
@@ -0,0 +1,85 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for x86 and x86-64.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#if defined (X86_64) && defined (__i386__)
+#undef X86_64
+#define X86
+#endif
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+#ifndef _WIN64
+typedef unsigned long          ffi_arg;
+#else
+typedef unsigned __int64       ffi_arg;
+#endif
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+  /* ---- Intel x86 Win32 ---------- */
+  FFI_SYSV,
+#ifndef _WIN64
+  FFI_STDCALL,
+#endif
+  /* TODO: Add fastcall support for the sake of completeness */
+  FFI_DEFAULT_ABI = FFI_SYSV,
+
+  /* ---- Intel x86 and AMD x86-64 - */
+/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */
+/*   FFI_SYSV, */
+/*   FFI_UNIX64,*/   /* Unix variants all use the same ABI for x86-64  */
+/* #ifdef __i386__ */
+/*   FFI_DEFAULT_ABI = FFI_SYSV, */
+/* #else */
+/*   FFI_DEFAULT_ABI = FFI_UNIX64, */
+/* #endif */
+/* #endif */
+
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+
+#ifdef _WIN64
+#define FFI_TRAMPOLINE_SIZE 29
+#define FFI_NATIVE_RAW_API 0
+#else
+#define FFI_TRAMPOLINE_SIZE 15
+#define FFI_NATIVE_RAW_API 1   /* x86 has native raw api support */
+#endif
+
+#endif
+
diff --git a/Modules/_ctypes/libffi_msvc/prep_cif.c b/Modules/_ctypes/libffi_msvc/prep_cif.c
new file mode 100644 (file)
index 0000000..2650fa0
--- /dev/null
@@ -0,0 +1,175 @@
+/* -----------------------------------------------------------------------
+   prep_cif.c - Copyright (c) 1996, 1998  Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+
+
+/* Round up to FFI_SIZEOF_ARG. */
+
+#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
+
+/* Perform machine independent initialization of aggregate type
+   specifications. */
+
+static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
+{
+  ffi_type **ptr; 
+
+  FFI_ASSERT(arg != NULL);
+
+  /*@-usedef@*/
+
+  FFI_ASSERT(arg->elements != NULL);
+  FFI_ASSERT(arg->size == 0);
+  FFI_ASSERT(arg->alignment == 0);
+
+  ptr = &(arg->elements[0]);
+
+  while ((*ptr) != NULL)
+    {
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+      
+      /* Perform a sanity check on the argument type */
+      FFI_ASSERT_VALID_TYPE(*ptr);
+
+      arg->size = ALIGN(arg->size, (*ptr)->alignment);
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > (*ptr)->alignment) ? 
+       arg->alignment : (*ptr)->alignment;
+
+      ptr++;
+    }
+
+  /* Structure size includes tail padding.  This is important for
+     structures that fit in one register on ABIs like the PowerPC64
+     Linux ABI that right justify small structs in a register.
+     It's also needed for nested structure layout, for example
+     struct A { long a; char b; }; struct B { struct A x; char y; };
+     should find y at an offset of 2*sizeof(long) and result in a
+     total size of 3*sizeof(long).  */
+  arg->size = ALIGN (arg->size, arg->alignment);
+
+  if (arg->size == 0)
+    return FFI_BAD_TYPEDEF;
+  else
+    return FFI_OK;
+
+  /*@=usedef@*/
+}
+
+/* Perform machine independent ffi_cif preparation, then call
+   machine dependent routine. */
+
+ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, 
+                       ffi_abi abi, unsigned int nargs, 
+                       /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
+                       /*@dependent@*/ ffi_type **atypes)
+{
+  unsigned bytes = 0;
+  unsigned int i;
+  ffi_type **ptr;
+
+  FFI_ASSERT(cif != NULL);
+  FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
+
+  cif->abi = abi;
+  cif->arg_types = atypes;
+  cif->nargs = nargs;
+  cif->rtype = rtype;
+
+  cif->flags = 0;
+
+  /* Initialize the return type if necessary */
+  /*@-usedef@*/
+  if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
+    return FFI_BAD_TYPEDEF;
+  /*@=usedef@*/
+
+  /* Perform a sanity check on the return type */
+  FFI_ASSERT_VALID_TYPE(cif->rtype);
+
+  /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
+#if !defined M68K && !defined __x86_64__ && !defined S390
+  /* Make space for the return structure pointer */
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      /* MSVC returns small structures in registers.  But we have a different
+      workaround: pretend int32 or int64 return type, and converting to
+      structure afterwards. */
+#ifdef SPARC
+      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
+#endif
+      )
+    bytes = STACK_ARG_SIZE(sizeof(void*));
+#endif
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+
+      /* Initialize any uninitialized aggregate type definitions */
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+
+      /* Perform a sanity check on the argument type, do this 
+        check after the initialization.  */
+      FFI_ASSERT_VALID_TYPE(*ptr);
+
+#if !defined __x86_64__ && !defined S390
+#ifdef SPARC
+      if (((*ptr)->type == FFI_TYPE_STRUCT
+          && ((*ptr)->size > 16 || cif->abi != FFI_V9))
+         || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
+             && cif->abi != FFI_V9))
+       bytes += sizeof(void*);
+      else
+#endif
+       {
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+               /* Don't know if this is a libffi bug or not.  At least on
+                  Windows with MSVC, function call parameters are *not*
+                  aligned in the same way as structure fields are, they are
+                  only aligned in integer boundaries.
+
+                  This doesn't do any harm for cdecl functions and closures,
+                  since the caller cleans up the stack, but it is wrong for
+                  stdcall functions where the callee cleans.
+               */
+
+         /* Add any padding if necessary */
+         if (((*ptr)->alignment - 1) & bytes)
+           bytes = ALIGN(bytes, (*ptr)->alignment);
+         
+#endif
+         bytes += STACK_ARG_SIZE((*ptr)->size);
+       }
+#endif
+    }
+
+  cif->bytes = bytes;
+
+  /* Perform machine dependent cif processing */
+  return ffi_prep_cif_machdep(cif);
+}
diff --git a/Modules/_ctypes/libffi_msvc/types.c b/Modules/_ctypes/libffi_msvc/types.c
new file mode 100644 (file)
index 0000000..df32190
--- /dev/null
@@ -0,0 +1,104 @@
+/* -----------------------------------------------------------------------
+   types.c - Copyright (c) 1996, 1998  Red Hat, Inc.
+   
+   Predefined ffi_types needed by libffi.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+/* Type definitions */
+
+#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
+#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
+
+/* Size and alignment are fake here. They must not be 0. */
+FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
+
+FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
+FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
+FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
+FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
+FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
+FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
+FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
+
+#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \
+    || defined IA64
+
+FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
+
+#endif
+
+#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
+
+#elif defined SH
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
+
+#endif
+
+
+#if defined X86 || defined X86_WIN32 || defined M68K
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
+
+#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
+
+#elif defined SPARC
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+#ifdef SPARC64
+FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
+#else
+FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
+#endif
+
+#elif defined X86_64
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
+
+#endif
+
diff --git a/Modules/_ctypes/libffi_msvc/win32.c b/Modules/_ctypes/libffi_msvc/win32.c
new file mode 100644 (file)
index 0000000..d1149a8
--- /dev/null
@@ -0,0 +1,162 @@
+/* -----------------------------------------------------------------------
+   win32.S - Copyright (c) 1996, 1998, 2001, 2002  Red Hat, Inc.
+            Copyright (c) 2001  John Beniton
+            Copyright (c) 2002  Ranjit Mathew
+                       
+   X86 Foreign Function Interface
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+/* theller: almost verbatim translation from gas syntax to MSVC inline
+   assembler code. */
+
+/* theller: ffi_call_x86 now returns an integer - the difference of the stack
+   pointer before and after the function call.  If everything is ok, zero is
+   returned.  If stdcall functions are passed the wrong number of arguments,
+   the difference will be nonzero. */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+__declspec(naked) int
+ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */
+            extended_cif *ecif, /* 12 */
+            unsigned bytes, /* 16 */
+            unsigned flags, /* 20 */
+            unsigned *rvalue, /* 24 */
+            void (*fn)()) /* 28 */
+{
+       _asm {
+               push ebp
+               mov ebp, esp
+
+               push esi // NEW: this register must be preserved across function calls
+// XXX SAVE ESP NOW!
+               mov esi, esp            // save stack pointer before the call
+
+// Make room for all of the new args.
+               mov ecx, [ebp+16]
+               sub esp, ecx            // sub esp, bytes
+               
+               mov eax, esp
+
+// Place all of the ffi_prep_args in position
+               push [ebp + 12] // ecif
+               push eax
+               call [ebp + 8] // prepfunc
+
+// Return stack to previous state and call the function
+               add esp, 8
+// FIXME: Align the stack to a 128-bit boundary to avoid
+// potential performance hits.
+               call [ebp + 28]
+
+// Load ecif->cif->abi
+               mov ecx, [ebp + 12]
+               mov ecx, [ecx]ecif.cif
+               mov ecx, [ecx]ecif.cif.abi
+               
+               cmp ecx, FFI_STDCALL
+               je noclean
+// STDCALL: Remove the space we pushed for the args
+               mov ecx, [ebp + 16]
+               add esp, ecx
+// CDECL: Caller has already cleaned the stack
+noclean:
+// Check that esp has the same value as before!
+               sub esi, esp
+
+// Load %ecx with the return type code
+               mov ecx, [ebp + 20]
+
+// If the return value pointer is NULL, assume no return value.
+/*
+  Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction,
+  otherwise only one BYTE will be compared (instead of a DWORD)!
+ */
+               cmp DWORD PTR [ebp + 24], 0
+               jne sc_retint
+
+// Even if there is no space for the return value, we are
+// obliged to handle floating-point values.
+               cmp ecx, FFI_TYPE_FLOAT
+               jne sc_noretval
+//        fstp  %st(0)
+               fstp st(0)
+
+               jmp sc_epilogue
+
+sc_retint:
+               cmp ecx, FFI_TYPE_INT
+               jne sc_retfloat
+//        # Load %ecx with the pointer to storage for the return value
+               mov ecx, [ebp + 24]
+               mov [ecx + 0], eax
+               jmp sc_epilogue
+
+sc_retfloat:
+               cmp ecx, FFI_TYPE_FLOAT
+               jne sc_retdouble
+// Load %ecx with the pointer to storage for the return value
+               mov ecx, [ebp+24]
+//        fstps (%ecx)
+               fstp DWORD PTR [ecx]
+               jmp sc_epilogue
+
+sc_retdouble:
+               cmp ecx, FFI_TYPE_DOUBLE
+               jne sc_retlongdouble
+//        movl  24(%ebp),%ecx
+               mov ecx, [ebp+24]
+               fstp QWORD PTR [ecx]
+               jmp sc_epilogue
+
+               jmp sc_retlongdouble // avoid warning about unused label
+sc_retlongdouble:
+               cmp ecx, FFI_TYPE_LONGDOUBLE
+               jne sc_retint64
+// Load %ecx with the pointer to storage for the return value
+               mov ecx, [ebp+24]
+//        fstpt (%ecx)
+               fstp QWORD PTR [ecx] /* XXX ??? */
+               jmp sc_epilogue
+
+sc_retint64:
+               cmp ecx, FFI_TYPE_SINT64
+               jne sc_retstruct
+// Load %ecx with the pointer to storage for the return value
+               mov ecx, [ebp+24]
+               mov [ecx+0], eax
+               mov [ecx+4], edx
+
+sc_retstruct:
+// Nothing to do!
+
+sc_noretval:
+sc_epilogue:
+               mov eax, esi
+               pop esi // NEW restore: must be preserved across function calls
+               mov esp, ebp
+               pop ebp
+               ret
+       }
+}
diff --git a/Modules/_ctypes/libffi_msvc/win64.asm b/Modules/_ctypes/libffi_msvc/win64.asm
new file mode 100644 (file)
index 0000000..301188b
--- /dev/null
@@ -0,0 +1,156 @@
+PUBLIC ffi_call_AMD64
+
+EXTRN  __chkstk:NEAR
+EXTRN  ffi_closure_SYSV:NEAR
+
+_TEXT  SEGMENT
+
+;;; ffi_closure_OUTER will be called with these registers set:
+;;;    rax points to 'closure'
+;;;    r11 contains a bit mask that specifies which of the
+;;;    first four parameters are float or double
+;;;
+;;; It must move the parameters passed in registers to their stack location,
+;;; call ffi_closure_SYSV for the actual work, then return the result.
+;;; 
+ffi_closure_OUTER PROC FRAME
+       ;; save actual arguments to their stack space.
+       test    r11, 1
+       jne     first_is_float  
+       mov     QWORD PTR [rsp+8], rcx
+       jmp     second
+first_is_float:
+       movlpd  QWORD PTR [rsp+8], xmm0
+
+second:
+       test    r11, 2
+       jne     second_is_float 
+       mov     QWORD PTR [rsp+16], rdx
+       jmp     third
+second_is_float:
+       movlpd  QWORD PTR [rsp+16], xmm1
+
+third:
+       test    r11, 4
+       jne     third_is_float  
+       mov     QWORD PTR [rsp+24], r8
+       jmp     forth
+third_is_float:
+       movlpd  QWORD PTR [rsp+24], xmm2
+
+forth:
+       test    r11, 8
+       jne     forth_is_float  
+       mov     QWORD PTR [rsp+32], r9
+       jmp     done
+forth_is_float:
+       movlpd  QWORD PTR [rsp+32], xmm3
+
+done:
+.ALLOCSTACK 40
+       sub     rsp, 40
+.ENDPROLOG
+       mov     rcx, rax        ; context is first parameter
+       mov     rdx, rsp        ; stack is second parameter
+       add     rdx, 40         ; correct our own area
+       mov     rax, ffi_closure_SYSV
+       call    rax             ; call the real closure function
+       ;; Here, code is missing that handles float return values
+       add     rsp, 40
+       movd    xmm0, rax       ; In case the closure returned a float.
+       ret     0
+ffi_closure_OUTER ENDP
+
+
+;;; ffi_call_AMD64
+
+stack$ = 0
+prepfunc$ = 32
+ecif$ = 40
+bytes$ = 48
+flags$ = 56
+rvalue$ = 64
+fn$ = 72
+
+ffi_call_AMD64 PROC FRAME
+
+       mov     QWORD PTR [rsp+32], r9
+       mov     QWORD PTR [rsp+24], r8
+       mov     QWORD PTR [rsp+16], rdx
+       mov     QWORD PTR [rsp+8], rcx
+.PUSHREG rbp
+       push    rbp
+.ALLOCSTACK 48
+       sub     rsp, 48                                 ; 00000030H
+.SETFRAME rbp, 32
+       lea     rbp, QWORD PTR [rsp+32]
+.ENDPROLOG
+
+       mov     eax, DWORD PTR bytes$[rbp]
+       add     rax, 15
+       and     rax, -16
+       call    __chkstk
+       sub     rsp, rax
+       lea     rax, QWORD PTR [rsp+32]
+       mov     QWORD PTR stack$[rbp], rax
+
+       mov     rdx, QWORD PTR ecif$[rbp]
+       mov     rcx, QWORD PTR stack$[rbp]
+       call    QWORD PTR prepfunc$[rbp]
+
+       mov     rsp, QWORD PTR stack$[rbp]
+
+       movlpd  xmm3, QWORD PTR [rsp+24]
+       movd    r9, xmm3
+
+       movlpd  xmm2, QWORD PTR [rsp+16]
+       movd    r8, xmm2
+
+       movlpd  xmm1, QWORD PTR [rsp+8]
+       movd    rdx, xmm1
+
+       movlpd  xmm0, QWORD PTR [rsp]
+       movd    rcx, xmm0
+
+       call    QWORD PTR fn$[rbp]
+ret_int$:
+       cmp     DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT
+       jne     ret_float$
+
+       mov     rcx, QWORD PTR rvalue$[rbp]
+       mov     DWORD PTR [rcx], eax
+       jmp     SHORT ret_nothing$
+
+ret_float$:
+       cmp     DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT
+       jne     SHORT ret_double$
+
+       mov     rax, QWORD PTR rvalue$[rbp]
+       movlpd  QWORD PTR [rax], xmm0
+       jmp     SHORT ret_nothing$
+
+ret_double$:
+       cmp     DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE
+       jne     SHORT ret_int64$
+
+       mov     rax, QWORD PTR rvalue$[rbp]
+       movlpd  QWORD PTR [rax], xmm0
+       jmp     SHORT ret_nothing$
+
+ret_int64$:
+       cmp     DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64
+       jne     ret_nothing$
+
+       mov     rcx, QWORD PTR rvalue$[rbp]
+       mov     QWORD PTR [rcx], rax
+       jmp     SHORT ret_nothing$
+       
+ret_nothing$:
+       xor     eax, eax
+
+       lea     rsp, QWORD PTR [rbp+16]
+       pop     rbp
+       ret     0
+ffi_call_AMD64 ENDP
+_TEXT  ENDS
+END
index db5a85ef1562499da2875286251774b2cf52fb3b..b6abbe05ec7641fbeb051b0868afa0fe894edcd5 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
        ProjectType="Visual C++"
-       Version="9,00"
+       Version="9.00"
        Name="_ctypes"
        ProjectGUID="{0E9791DB-593A-465F-98BC-681011311618}"
        RootNamespace="_ctypes"
@@ -42,8 +42,7 @@
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
-                               PreprocessorDefinitions="X86_WIN32"
+                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
                        />
                        <Tool
                                Name="VCManagedResourceCompilerTool"
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
-                               PreprocessorDefinitions="X86_WIN64"
+                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
                        />
                        <Tool
                                Name="VCManagedResourceCompilerTool"
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
-                               PreprocessorDefinitions="X86_WIN32"
+                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
                        />
                        <Tool
                                Name="VCManagedResourceCompilerTool"
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
-                               PreprocessorDefinitions="X86_WIN64"
+                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
                        />
                        <Tool
                                Name="VCManagedResourceCompilerTool"
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
-                               PreprocessorDefinitions="X86_WIN32"
+                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
                        />
                        <Tool
                                Name="VCManagedResourceCompilerTool"
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
-                               PreprocessorDefinitions="X86_WIN64"
+                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
                        />
                        <Tool
                                Name="VCManagedResourceCompilerTool"
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
-                               PreprocessorDefinitions="X86_WIN32"
+                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
                        />
                        <Tool
                                Name="VCManagedResourceCompilerTool"
                        />
                        <Tool
                                Name="VCCLCompilerTool"
-                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
-                               PreprocessorDefinitions="X86_WIN64"
+                               AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
                        />
                        <Tool
                                Name="VCManagedResourceCompilerTool"
                                >
                        </File>
                        <File
-                               RelativePath="..\Modules\_ctypes\libffi\include\ffi_common.h"
+                               RelativePath="..\Modules\_ctypes\libffi_msvc\ffi_common.h"
                                >
                        </File>
                        <File
                                >
                        </File>
                        <File
-                               RelativePath="..\Modules\_ctypes\libffi\src\x86\ffitarget.h"
+                               RelativePath="..\Modules\_ctypes\libffi_msvc\ffitarget.h"
                                >
                        </File>
                </Filter>
                                >
                        </File>
                        <File
-                               RelativePath="..\Modules\_ctypes\libffi\src\x86\ffi.c"
+                               RelativePath="..\Modules\_ctypes\libffi_msvc\ffi.c"
                                >
-                               <FileConfiguration
-                                       Name="Debug|x64"
-                                       >
-                                       <Tool
-                                               Name="VCCLCompilerTool"
-                                               PreprocessorDefinitions="X86_WIN64"
-                                       />
-                               </FileConfiguration>
                        </File>
                        <File
                                RelativePath="..\Modules\_ctypes\malloc_closure.c"
                                >
                        </File>
                        <File
-                               RelativePath="..\Modules\_ctypes\libffi\src\prep_cif.c"
+                               RelativePath="..\Modules\_ctypes\libffi_msvc\prep_cif.c"
                                >
                        </File>
                        <File
                                >
                        </File>
                        <File
-                               RelativePath="..\Modules\_ctypes\libffi\src\x86\win32.S"
+                               RelativePath="..\Modules\_ctypes\libffi_msvc\win32.c"
                                >
-                               <FileConfiguration
-                                       Name="Debug|Win32"
-                                       >
-                                       <Tool
-                                               Name="VCCustomBuildTool"
-                                               CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml /nologo /Zi /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
-                                               Outputs="$(IntDir)$(InputName).obj"
-                                       />
-                               </FileConfiguration>
                                <FileConfiguration
                                        Name="Debug|x64"
                                        ExcludedFromBuild="true"
                                        >
                                        <Tool
-                                               Name="VCCustomBuildTool"
-                                       />
-                               </FileConfiguration>
-                               <FileConfiguration
-                                       Name="Release|Win32"
-                                       >
-                                       <Tool
-                                               Name="VCCustomBuildTool"
-                                               CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
-                                               Outputs="$(IntDir)$(InputName).obj"
+                                               Name="VCCLCompilerTool"
                                        />
                                </FileConfiguration>
                                <FileConfiguration
                                        ExcludedFromBuild="true"
                                        >
                                        <Tool
-                                               Name="VCCustomBuildTool"
-                                       />
-                               </FileConfiguration>
-                               <FileConfiguration
-                                       Name="PGInstrument|Win32"
-                                       >
-                                       <Tool
-                                               Name="VCCustomBuildTool"
-                                               CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml /nologo /Zi /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
-                                               Outputs="$(IntDir)$(InputName).obj"
+                                               Name="VCCLCompilerTool"
                                        />
                                </FileConfiguration>
                                <FileConfiguration
                                        ExcludedFromBuild="true"
                                        >
                                        <Tool
-                                               Name="VCCustomBuildTool"
-                                       />
-                               </FileConfiguration>
-                               <FileConfiguration
-                                       Name="PGUpdate|Win32"
-                                       >
-                                       <Tool
-                                               Name="VCCustomBuildTool"
-                                               CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml /nologo /Zi /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
-                                               Outputs="$(IntDir)$(InputName).obj"
+                                               Name="VCCLCompilerTool"
                                        />
                                </FileConfiguration>
                                <FileConfiguration
                                        ExcludedFromBuild="true"
                                        >
                                        <Tool
-                                               Name="VCCustomBuildTool"
+                                               Name="VCCLCompilerTool"
                                        />
                                </FileConfiguration>
                        </File>
                        <File
-                               RelativePath="..\Modules\_ctypes\libffi\src\x86\win64.S"
+                               RelativePath="..\Modules\_ctypes\libffi_msvc\win64.asm"
                                >
                                <FileConfiguration
                                        Name="Debug|Win32"
                                        >
                                        <Tool
                                                Name="VCCustomBuildTool"
-                                               CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml64 /Zi /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
-                                               Outputs="$(IntDir)$(InputName).obj"
+                                               CommandLine="ml64 /nologo /c /Zi /Fo &quot;$(IntDir)\win64.obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
+                                               Outputs="$(IntDir)\win64.obj"
                                        />
                                </FileConfiguration>
                                <FileConfiguration
                                        >
                                        <Tool
                                                Name="VCCustomBuildTool"
-                                               CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml64 /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
-                                               Outputs="$(IntDir)$(InputName).obj"
+                                               CommandLine="ml64 /nologo /c /Fo &quot;$(IntDir)\win64.obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
+                                               Outputs="$(IntDir)\win64.obj"
                                        />
                                </FileConfiguration>
                                <FileConfiguration
                                        >
                                        <Tool
                                                Name="VCCustomBuildTool"
-                                               CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml64 /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
-                                               Outputs="$(IntDir)$(InputName).obj"
+                                               CommandLine="ml64 /nologo /c /Fo &quot;$(IntDir)\win64.obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
+                                               Outputs="$(IntDir)\win64.obj"
                                        />
                                </FileConfiguration>
                                <FileConfiguration
                                        >
                                        <Tool
                                                Name="VCCustomBuildTool"
-                                               CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml64 /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
-                                               Outputs="$(IntDir)$(InputName).obj"
+                                               CommandLine="ml64 /nologo /c /Fo &quot;$(IntDir)\win64.obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
+                                               Outputs="$(IntDir)\win64.obj"
                                        />
                                </FileConfiguration>
                        </File>