Many changes
authorgreen <green>
Sun, 22 Apr 2001 18:10:47 +0000 (18:10 +0000)
committergreen <green>
Sun, 22 Apr 2001 18:10:47 +0000 (18:10 +0000)
libffi/debug.c [new file with mode: 0644]
libffi/ffitest.c [new file with mode: 0644]
libffi/java_raw_api.c [new file with mode: 0644]
libffi/prep_cif.c [new file with mode: 0644]
libffi/raw_api.c [new file with mode: 0644]
libffi/types.c [new file with mode: 0644]

diff --git a/libffi/debug.c b/libffi/debug.c
new file mode 100644 (file)
index 0000000..17196ba
--- /dev/null
@@ -0,0 +1,65 @@
+/* -----------------------------------------------------------------------
+   debug.c - Copyright (c) 1996 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 RED HAT 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>
+#include <stdio.h>
+
+/* General debugging routines */
+
+void ffi_stop_here(void)
+{
+  /* This function is only useful for debugging purposes.
+     Place a breakpoint on ffi_stop_here to be notified of 
+     significant events. */
+}
+
+/* This function should only be called via the FFI_ASSERT() macro */
+
+int ffi_assert(char *file, int line)
+{
+  fprintf(stderr, "ASSERTION FAILURE: %s line %d\n", file, line);
+  ffi_stop_here();
+  abort();
+
+  /* This has to return something for the compiler not to complain */
+  /*@notreached@*/
+  return 0;
+}
+
+/* Perform a sanity check on an ffi_type structure */
+
+bool ffi_type_test(ffi_type *a)
+{
+  /*@-usedef@*/
+  FFI_ASSERT(a->type <= FFI_TYPE_LAST);
+  FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->size > 0 : 1);
+  FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->alignment > 0 : 1);
+  FFI_ASSERT(a->type == FFI_TYPE_STRUCT ? a->elements != NULL : 1);
+  /*@=usedef@*/
+
+  /* This is a silly thing to return, but it keeps the compiler from
+     issuing warnings about "a" not being used in non-debug builds. */
+  return (a != NULL);
+}
diff --git a/libffi/ffitest.c b/libffi/ffitest.c
new file mode 100644 (file)
index 0000000..2489a71
--- /dev/null
@@ -0,0 +1,736 @@
+/* -----------------------------------------------------------------------
+   ffitest.c - Copyright (c) 1996, 1997, 1998  Cygnus Solutions
+
+   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 RED HAT 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+/* This is lame. Long double support is barely there under SunOS 4.x  */
+#if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16)
+#define BROKEN_LONG_DOUBLE
+#endif
+
+#define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0 
+
+static int fail(char *file, int line)
+{
+  fprintf(stderr, "Test failure: %s line %d\n", file, line);
+  exit(EXIT_FAILURE);
+  /*@notreached@*/
+  return 0;
+}
+
+#define MAX_ARGS 256
+
+static size_t my_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+static int promotion(signed char sc, signed short ss, 
+                    unsigned char uc, unsigned short us)
+{
+  int r = (int) sc + (int) ss + (int) uc + (int) us;
+
+  return r;
+}
+
+static signed char return_sc(signed char sc)
+{
+  return sc;
+}
+
+static unsigned char return_uc(unsigned char uc)
+{
+  return uc;
+}
+
+static long long return_ll(long long ll)
+{
+  return ll;
+}
+
+static int floating(int a, float b, double c, long double d, int e)
+{
+  int i;
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+  printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
+#endif
+
+  i = (int) ((float)a/b + ((float)c/(float)d));
+
+  return i;
+}
+
+static float many(float f1,
+                 float f2,
+                 float f3,
+                 float f4,
+                 float f5,
+                 float f6,
+                 float f7,
+                 float f8,
+                 float f9,
+                 float f10,
+                 float f11,
+                 float f12,
+                 float f13)
+{
+#if 0
+  printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+        (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, 
+        (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+        (double) f11, (double) f12, (double) f13);
+#endif
+
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+static double dblit(float f)
+{
+  return f/3.0;
+}
+
+static long double ldblit(float f)
+{
+  return (long double) (((long double) f)/ (long double) 3.0);
+}
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+typedef struct
+{
+  double d1;
+  double d2;
+} test_structure_2;
+
+typedef struct
+{
+  int si;
+} test_structure_3;
+
+typedef struct
+{
+  unsigned ui1;
+  unsigned ui2;
+  unsigned ui3;
+} test_structure_4;
+
+typedef struct
+{
+  char c1;
+  char c2;
+} test_structure_5;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+  /*@-type@*/
+  ts.uc++;
+  /*@=type@*/
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+static test_structure_2 struct2(test_structure_2 ts)
+{
+  ts.d1--;
+  ts.d2--;
+
+  return ts;
+}
+
+static test_structure_3 struct3(test_structure_3 ts)
+{
+  ts.si = -(ts.si*2);
+
+  return ts;
+}
+
+static test_structure_4 struct4(test_structure_4 ts)
+{
+  ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
+
+  return ts;
+}
+
+static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
+{
+  ts1.c1 += ts2.c1;
+  ts1.c2 -= ts2.c2;
+
+  return ts1;
+}
+
+/* Take an int and a float argument, together with int userdata, and   */
+/* return the sum.                                                     */
+static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
+{
+    *(int*)resp =
+        *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
+}
+
+typedef int (*closure_test_type)(int, float);
+
+int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  char *s;
+  signed char sc;
+  unsigned char uc;
+  signed short ss;
+  unsigned short us;
+  unsigned long ul;
+  long long ll;
+  float f;
+  double d;
+  long double ld;
+  signed int si1;
+  signed int si2;
+
+#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(__mips__) && (_MIPS_SIM == _ABIN32))
+  long long rint;
+#else
+  int rint;
+#endif
+  long long rlonglong;
+
+  ffi_type ts1_type;
+  ffi_type ts2_type;
+  ffi_type ts3_type;
+  ffi_type ts4_type;  
+  ffi_type ts5_type;
+  ffi_type *ts1_type_elements[4];
+  ffi_type *ts2_type_elements[3];
+  ffi_type *ts3_type_elements[2];
+  ffi_type *ts4_type_elements[4];
+  ffi_type *ts5_type_elements[3];
+
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+
+  ts2_type.size = 0;
+  ts2_type.alignment = 0;
+  ts2_type.type = FFI_TYPE_STRUCT;
+
+  ts3_type.size = 0;
+  ts3_type.alignment = 0;
+  ts3_type.type = FFI_TYPE_STRUCT;
+
+  ts4_type.size = 0;
+  ts4_type.alignment = 0;
+  ts4_type.type = FFI_TYPE_STRUCT;
+
+  ts5_type.size = 0;
+  ts5_type.alignment = 0;
+  ts5_type.type = FFI_TYPE_STRUCT;
+
+  /*@-immediatetrans@*/
+  ts1_type.elements = ts1_type_elements;
+  ts2_type.elements = ts2_type_elements;
+  ts3_type.elements = ts3_type_elements;
+  ts4_type.elements = ts4_type_elements;
+  ts5_type.elements = ts5_type_elements;
+  /*@=immediatetrans@*/
+  
+  ts1_type_elements[0] = &ffi_type_uchar;
+  ts1_type_elements[1] = &ffi_type_double;
+  ts1_type_elements[2] = &ffi_type_uint;
+  ts1_type_elements[3] = NULL;
+  
+  ts2_type_elements[0] = &ffi_type_double;
+  ts2_type_elements[1] = &ffi_type_double;
+  ts2_type_elements[2] = NULL;
+
+  ts3_type_elements[0] = &ffi_type_sint;
+  ts3_type_elements[1] = NULL;
+
+  ts4_type_elements[0] = &ffi_type_uint;
+  ts4_type_elements[1] = &ffi_type_uint;
+  ts4_type_elements[2] = &ffi_type_uint;
+  ts4_type_elements[3] = NULL;
+
+  ts5_type_elements[0] = &ffi_type_schar;
+  ts5_type_elements[1] = &ffi_type_schar;
+  ts5_type_elements[2] = NULL;
+
+  ul = 0;
+
+  /* return value tests */
+  {
+#if defined(__mips__) /* || defined(ARM) */
+    puts ("long long tests not run. This is a known bug on this architecture.");
+#else
+    args[0] = &ffi_type_sint64;
+    values[0] = &ll;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_sint64, args) == FFI_OK);
+
+    for (ll = 0LL; ll < 100LL; ll++)
+      {
+       ul++;
+       ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+       CHECK(rlonglong == ll);
+      }
+
+    for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
+      {
+       ul++;
+       ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+       CHECK(rlonglong == ll);
+      }
+#endif
+
+    args[0] = &ffi_type_schar;
+    values[0] = &sc;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_schar, args) == FFI_OK);
+
+    for (sc = (signed char) -127; 
+        sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
+      {
+       ul++;
+       ffi_call(&cif, FFI_FN(return_sc), &rint, values);
+       CHECK(rint == (int) sc);
+      }
+
+    args[0] = &ffi_type_uchar;
+    values[0] = &uc;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_uchar, args) == FFI_OK);
+
+    for (uc = (unsigned char) '\x00'; 
+        uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
+      {
+       ul++;
+       ffi_call(&cif, FFI_FN(return_uc), &rint, values);
+       CHECK(rint == (signed int) uc);
+      }
+
+    printf("%lu return value tests run\n", ul);
+  }
+
+#ifdef BROKEN_LONG_DOUBLE
+  printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
+#else
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_float;
+    values[0] = &f;
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_longdouble, args) == FFI_OK);
+
+    f = 3.14159;
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+    printf ("%Lf\n", ldblit(f));
+#endif
+    ld = 666;
+    ffi_call(&cif, FFI_FN(ldblit), &ld, values);
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+    printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
+#endif
+
+    /* These are not always the same!! Check for a reasonable delta */
+    /*@-realcompare@*/
+    if (ld - ldblit(f) < LDBL_EPSILON)
+    /*@=realcompare@*/
+       puts("long double return value tests ok!");
+    else
+        CHECK(0);
+  }
+
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_sint;
+    values[0] = &si1;
+    args[1] = &ffi_type_float;
+    values[1] = &f;
+    args[2] = &ffi_type_double;
+    values[2] = &d;
+    args[3] = &ffi_type_longdouble;
+    values[3] = &ld;
+    args[4] = &ffi_type_sint;
+    values[4] = &si2;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
+                      &ffi_type_sint, args) == FFI_OK);
+
+    si1 = 6;
+    f = 3.14159;
+    d = (double)1.0/(double)3.0;
+    ld = 2.71828182846L;
+    si2 = 10;
+
+    floating (si1, f, d, ld, si2);
+
+    ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+    printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
+
+    CHECK(rint == floating(si1, f, d, ld, si2));
+
+    printf("float arg tests ok!\n");
+  }
+#endif
+
+  /* strlen tests */
+  {
+    args[0] = &ffi_type_pointer;
+    values[0] = (void*) &s;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_sint, args) == FFI_OK);
+
+    s = "a";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 1);
+
+    s = "1234567";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 7);
+
+    s = "1234567890123456789012345";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 25);
+
+    printf("strlen tests passed\n");
+  }
+
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_float;
+    values[0] = &f;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_double, args) == FFI_OK);
+
+    f = 3.14159;
+
+    ffi_call(&cif, FFI_FN(dblit), &d, values);
+
+    /* These are not always the same!! Check for a reasonable delta */
+    /*@-realcompare@*/
+    CHECK(d - dblit(f) < DBL_EPSILON);
+    /*@=realcompare@*/
+
+    printf("double return value tests ok!\n");
+  }
+
+  /* many arg tests */
+  {
+    float ff;
+    float fa[13];
+    
+    for (ul = 0; ul < 13; ul++)
+      {
+       args[ul] = &ffi_type_float;
+       values[ul] = &fa[ul];
+       fa[ul] = (float) ul;
+      }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
+                      &ffi_type_float, args) == FFI_OK);
+
+    /*@-usedef@*/
+    ff =  many(fa[0], fa[1],
+              fa[2], fa[3],
+              fa[4], fa[5],
+              fa[6], fa[7],
+              fa[8], fa[9],
+              fa[10],fa[11],fa[12]);
+    /*@=usedef@*/
+
+    ffi_call(&cif, FFI_FN(many), &f, values);
+
+    /*@-realcompare@*/
+    if (f - ff < FLT_EPSILON)
+    /*@=realcompare@*/
+       printf("many arg tests ok!\n");
+    else
+#ifdef POWERPC
+       printf("many arg tests failed!  This is a gcc bug.\n");
+#else
+        CHECK(0);
+#endif
+  }
+
+  /* promotion tests */
+  {
+    args[0] = &ffi_type_schar;
+    args[1] = &ffi_type_sshort;
+    args[2] = &ffi_type_uchar;
+    args[3] = &ffi_type_ushort;
+    values[0] = &sc;
+    values[1] = &ss;
+    values[2] = &uc;
+    values[3] = &us;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, 
+                      &ffi_type_sint, args) == FFI_OK);
+
+    us = 0;
+    ul = 0;
+
+    for (sc = (signed char) -127; 
+        sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
+      for (ss = -30000; ss <= 30000; ss += 10000)
+       for (uc = (unsigned char) 0; 
+            uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
+         for (us = 0; us <= 60000; us += 10000)
+           {
+             ul++;
+             ffi_call(&cif, FFI_FN(promotion), &rint, values);
+             CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
+           }
+    printf("%lu promotion tests run\n", ul);
+  }
+
+#ifndef X86_WIN32 /* Structures dont work on Win32 */
+
+  /* struct tests */
+  {
+    test_structure_1 ts1_arg;
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_1 *ts1_result = 
+      (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+    args[0] = &ts1_type;
+    values[0] = &ts1_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ts1_type, args) == FFI_OK);
+
+    ts1_arg.uc = '\x01';
+    ts1_arg.d = 3.14159;
+    ts1_arg.ui = 555;
+
+    ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+
+    CHECK(ts1_result->ui == 556);
+    CHECK(ts1_result->d == 3.14159 - 1);
+
+    puts ("structure test 1 ok!\n");
+
+    free (ts1_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_2 ts2_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_2 *ts2_result = 
+      (test_structure_2 *) malloc (sizeof(test_structure_2));
+
+    args[0] = &ts2_type;
+    values[0] = &ts2_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ts2_type, args) == FFI_OK);
+
+    ts2_arg.d1 = 5.55;
+    ts2_arg.d2 = 6.66;
+
+    printf ("%g\n", ts2_result->d1);
+    printf ("%g\n", ts2_result->d2);
+
+    ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
+
+    printf ("%g\n", ts2_result->d1);
+    printf ("%g\n", ts2_result->d2);
+    
+    CHECK(ts2_result->d1 == 5.55 - 1);
+    CHECK(ts2_result->d2 == 6.66 - 1);
+
+    printf("structure test 2 ok!\n");
+
+    free (ts2_result);
+  }
+
+  /* struct tests */
+  {
+    int compare_value;
+    test_structure_3 ts3_arg;
+    test_structure_3 *ts3_result = 
+      (test_structure_3 *) malloc (sizeof(test_structure_3));
+
+    args[0] = &ts3_type;
+    values[0] = &ts3_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ts3_type, args) == FFI_OK);
+
+    ts3_arg.si = -123;
+    compare_value = ts3_arg.si;
+
+    ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
+
+    printf ("%d %d\n", ts3_result->si, -(compare_value*2));
+
+    if (ts3_result->si == -(ts3_arg.si*2))
+       puts ("structure test 3 ok!");
+    else
+      {
+       puts ("Structure test 3 found structure passing bug.");
+       puts ("  Current versions of GCC are not 100% compliant with the");
+       puts ("  n32 ABI.  There is a known problem related to passing");
+       puts ("  small structures.  Send a bug report to the gcc maintainers.");
+      }
+
+    free (ts3_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_4 ts4_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_4 *ts4_result = 
+      (test_structure_4 *) malloc (sizeof(test_structure_4));
+
+    args[0] = &ts4_type;
+    values[0] = &ts4_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ts4_type, args) == FFI_OK);
+
+    ts4_arg.ui1 = 2;
+    ts4_arg.ui2 = 3;
+    ts4_arg.ui3 = 4;
+
+    ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
+    
+    if (ts4_result->ui3 == 2U * 3U * 4U)
+      puts ("structure test 4 ok!");
+    else
+      puts ("Structure test 4 found GCC's structure passing bug.");
+
+    free (ts4_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_5 ts5_arg1, ts5_arg2;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_5 *ts5_result = 
+      (test_structure_5 *) malloc (sizeof(test_structure_5));
+
+    args[0] = &ts5_type;
+    args[1] = &ts5_type;
+    values[0] = &ts5_arg1;
+    values[1] = &ts5_arg2;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
+                      &ts5_type, args) == FFI_OK);
+
+    ts5_arg1.c1 = 2;
+    ts5_arg1.c2 = 6;
+    ts5_arg2.c1 = 5;
+    ts5_arg2.c2 = 3;
+
+    ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
+    
+    if (ts5_result->c1 == 7 
+       && ts5_result->c2 == 3)
+      puts ("structure test 5 ok!");
+    else
+      puts ("Structure test 5 found GCC's structure passing bug.");
+
+    free (ts5_result);
+  }
+
+#else
+  printf("Structure passing doesn't work on Win32.\n");
+#endif /* X86_WIN32 */
+
+# if FFI_CLOSURES
+  /* A simple closure test */
+    {
+      ffi_closure cl;
+      ffi_type * cl_arg_types[3];
+
+      cl_arg_types[0] = &ffi_type_sint;
+      cl_arg_types[1] = &ffi_type_float;
+      cl_arg_types[2] = NULL;
+      
+      /* Initialize the cif */
+      CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
+                        &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+      CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
+                            (void *) 3 /* userdata */)
+           == FFI_OK);
+      CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
+    }
+# endif
+
+  /* If we arrived here, all is good */
+  (void) puts("\nLooks good. No surprises.\n");
+
+  /*@-compdestroy@*/
+
+  return 0;
+}
+
diff --git a/libffi/java_raw_api.c b/libffi/java_raw_api.c
new file mode 100644 (file)
index 0000000..9d82e4b
--- /dev/null
@@ -0,0 +1,270 @@
+/* -----------------------------------------------------------------------
+   java_raw_api.c - Copyright (c) 1999  Cygnus Solutions
+
+   Cloned from raw_api.c
+
+   Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
+   Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
+
+   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 RED HAT 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.
+   ----------------------------------------------------------------------- */
+
+/* This defines a Java- and 64-bit specific variant of the raw API.    */
+/* It assumes that "raw" argument blocks look like Java stacks on a    */
+/* 64-bit machine.  Arguments that can be stored in a single stack     */
+/* stack slots (longs, doubles) occupy 128 bits, but only the first    */
+/* 64 bits are actually used.                                                  */
+
+#include <ffi.h>
+#include <ffi_private.h>
+#include <ffi_common.h>
+
+#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
+
+size_t
+ffi_java_raw_size (ffi_cif *cif)
+{
+  size_t result = 0;
+  int i;
+
+  ffi_type **at = cif->arg_types;
+
+  for (i = cif->nargs-1; i >= 0; i--, at++)
+    {
+      switch((*at) -> type) {
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+         result += 2 * SIZEOF_ARG;
+         break;
+       case FFI_TYPE_STRUCT:
+         /* No structure parameters in Java.   */
+         abort();
+       default:
+         result += SIZEOF_ARG;
+      }
+    }
+
+  return result;
+}
+
+
+void
+ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+#if WORDS_BIGENDIAN
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {    
+      switch ((*tp)->type)
+       {
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT8:
+         *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
+         break;
+         
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT16:
+         *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
+         break;
+
+#if SIZEOF_ARG >= 4      
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+         *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
+         break;
+#endif
+       
+#if SIZEOF_ARG == 8      
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_DOUBLE:
+         *args = (void *)raw;
+         raw += 2;
+         break;
+#endif
+
+       case FFI_TYPE_POINTER:
+         *args = (void*) &(raw++)->ptr;
+         break;
+         
+       default:
+         *args = raw;
+         raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
+       }
+    }
+
+#else /* WORDS_BIGENDIAN */
+
+#if !PDP
+
+  /* then assume little endian */
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {
+#if SIZEOF_ARG == 8
+      switch((*tp)->type) {
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_DOUBLE:
+         *args = (void*) raw;
+         raw += 2;
+         break;
+       default:
+         *args = (void*) raw++;
+      }
+#else /* SIZEOF_ARG != 8 */
+       *args = (void*) raw;
+       raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
+#endif /* SIZEOF_ARG == 8 */
+    }
+
+#else
+#error "pdp endian not supported"
+#endif /* ! PDP */
+
+#endif /* WORDS_BIGENDIAN */
+}
+
+void
+ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {    
+      switch ((*tp)->type)
+       {
+       case FFI_TYPE_UINT8:
+         (raw++)->uint = *(UINT8*) (*args);
+         break;
+
+       case FFI_TYPE_SINT8:
+         (raw++)->sint = *(SINT8*) (*args);
+         break;
+
+       case FFI_TYPE_UINT16:
+         (raw++)->uint = *(UINT16*) (*args);
+         break;
+
+       case FFI_TYPE_SINT16:
+         (raw++)->sint = *(SINT16*) (*args);
+         break;
+
+#if SIZEOF_ARG >= 4
+       case FFI_TYPE_UINT32:
+         (raw++)->uint = *(UINT32*) (*args);
+         break;
+
+       case FFI_TYPE_SINT32:
+         (raw++)->sint = *(SINT32*) (*args);
+         break;
+#endif
+        case FFI_TYPE_FLOAT:
+         (raw++)->flt = *(FLOAT32*) (*args);
+         break;
+
+#if SIZEOF_ARG == 8
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_DOUBLE:
+         raw->uint = *(UINT64*) (*args);
+         raw += 2;
+         break;
+#endif
+
+       case FFI_TYPE_POINTER:
+         (raw++)->ptr = **(void***) args;
+         break;
+
+       default:
+#if SIZEOF_ARG == 8
+         FFI_ASSERT(FALSE);    /* Should have covered all cases */
+#else  
+         memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
+         raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
+#endif
+       }
+    }
+}
+
+#if !FFI_NATIVE_RAW_API
+
+
+/* This is a generic definition of ffi_raw_call, to be used if the
+ * native system does not provide a machine-specific implementation.
+ * Having this, allows code to be written for the raw API, without
+ * the need for system-specific code to handle input in that format;
+ * these following couple of functions will handle the translation forth
+ * and back automatically. */
+
+void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, 
+                  void (*fn)(), 
+                  /*@out@*/ void *rvalue, 
+                  /*@dependent@*/ ffi_raw *raw)
+{
+  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
+  ffi_java_raw_to_ptrarray (cif, raw, avalue);
+  ffi_call (cif, fn, rvalue, avalue);
+}
+
+#if FFI_CLOSURES               /* base system provides closures */
+
+static void 
+ffi_java_translate_args (ffi_cif *cif, void *rvalue,
+                   void **avalue, void *user_data)
+{
+  ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif));
+  ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
+
+  ffi_java_ptrarray_to_raw (cif, avalue, raw);
+  (*cl->fun) (cif, rvalue, raw, cl->user_data);
+}
+
+/* Again, here is the generic version of ffi_prep_raw_closure, which
+ * will install an intermediate "hub" for translation of arguments from
+ * the pointer-array format, to the raw format */
+
+ffi_status
+ffi_prep_java_raw_closure (ffi_raw_closure* cl,
+                     ffi_cif *cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data)
+{
+  ffi_status status;
+
+  status = ffi_prep_closure ((ffi_closure*) cl, 
+                            cif,
+                            &ffi_java_translate_args,
+                            (void*)cl);
+  if (status == FFI_OK)
+    {
+      cl->fun       = fun;
+      cl->user_data = user_data;
+    }
+
+  return status;
+}
+
+#endif /* FFI_CLOSURES */
+#endif /* !FFI_NATIVE_RAW_API */
+#endif /* !FFI_NO_RAW_API */
diff --git a/libffi/prep_cif.c b/libffi/prep_cif.c
new file mode 100644 (file)
index 0000000..a15d676
--- /dev/null
@@ -0,0 +1,147 @@
+/* -----------------------------------------------------------------------
+   prep_cif.c - Copyright (c) 1996, 1998  Cygnus Solutions
+
+   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 RED HAT 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_private.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+
+
+/* Round up to SIZEOF_ARG. */
+
+#define STACK_ARG_SIZE(x) ALIGN(x, 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(ffi_type_test((*ptr)));
+
+      arg->size = ALIGN(arg->size, (*ptr)->alignment);
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > (*ptr)->alignment) ? 
+       arg->alignment : (*ptr)->alignment;
+
+      ptr++;
+    }
+
+  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_LAST_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(ffi_type_test(cif->rtype));
+
+#ifndef M68K
+  /* Make space for the return structure pointer */
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+#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++)
+    {
+      /* Perform a sanity check on the argument type */
+      FFI_ASSERT(ffi_type_test(*ptr));
+
+      /* Initialize any uninitialized aggregate type definitions */
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+
+#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
+       {
+         /* Add any padding if necessary */
+         if (((*ptr)->alignment - 1) & bytes)
+           bytes = ALIGN(bytes, (*ptr)->alignment);
+         
+         bytes += STACK_ARG_SIZE((*ptr)->size);
+       }
+    }
+
+  cif->bytes = bytes;
+
+  /* Perform machine dependent cif processing */
+  return ffi_prep_cif_machdep(cif);
+}
diff --git a/libffi/raw_api.c b/libffi/raw_api.c
new file mode 100644 (file)
index 0000000..4830709
--- /dev/null
@@ -0,0 +1,241 @@
+/* -----------------------------------------------------------------------
+   raw_api.c - Copyright (c) 1999  Cygnus Solutions
+
+   Author: Kresten Krab Thorup <krab@gnu.org>
+
+   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 RED HAT 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.
+   ----------------------------------------------------------------------- */
+
+/* This file defines generic functions for use with the raw api. */
+
+#include <ffi.h>
+#include <ffi_private.h>
+#include <ffi_common.h>
+
+#if !FFI_NO_RAW_API
+
+size_t
+ffi_raw_size (ffi_cif *cif)
+{
+  size_t result = 0;
+  int i;
+
+  ffi_type **at = cif->arg_types;
+
+  for (i = cif->nargs-1; i >= 0; i--, at++)
+    {
+#if !FFI_NO_STRUCTS
+      if ((*at)->type == FFI_TYPE_STRUCT)
+       result += ALIGN (sizeof (void*), SIZEOF_ARG);
+      else
+#endif
+       result += ALIGN ((*at)->size, SIZEOF_ARG);
+    }
+
+  return result;
+}
+
+
+void
+ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+#if WORDS_BIGENDIAN
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {    
+      switch ((*tp)->type)
+       {
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT8:
+         *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
+         break;
+         
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT16:
+         *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
+         break;
+
+#if SIZEOF_ARG >= 4      
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+         *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
+         break;
+#endif
+       
+#if !FFI_NO_STRUCTS  
+       case FFI_TYPE_STRUCT:
+         *args = (raw++)->ptr;
+         break;
+#endif
+
+       case FFI_TYPE_POINTER:
+         *args = (void*) &(raw++)->ptr;
+         break;
+         
+       default:
+         *args = raw;
+         raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
+       }
+    }
+
+#else /* WORDS_BIGENDIAN */
+
+#if !PDP
+
+  /* then assume little endian */
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {    
+#if !FFI_NO_STRUCTS
+      if ((*tp)->type == FFI_TYPE_STRUCT)
+       {
+         *args = (raw++)->ptr;
+       }
+      else
+#endif
+       {
+         *args = (void*) raw;
+         raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
+       }
+    }
+
+#else
+#error "pdp endian not supported"
+#endif /* ! PDP */
+
+#endif /* WORDS_BIGENDIAN */
+}
+
+void
+ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {    
+      switch ((*tp)->type)
+       {
+       case FFI_TYPE_UINT8:
+         (raw++)->uint = *(UINT8*) (*args);
+         break;
+
+       case FFI_TYPE_SINT8:
+         (raw++)->sint = *(SINT8*) (*args);
+         break;
+
+       case FFI_TYPE_UINT16:
+         (raw++)->uint = *(UINT16*) (*args);
+         break;
+
+       case FFI_TYPE_SINT16:
+         (raw++)->sint = *(SINT16*) (*args);
+         break;
+
+#if SIZEOF_ARG >= 4
+       case FFI_TYPE_UINT32:
+         (raw++)->uint = *(UINT32*) (*args);
+         break;
+
+       case FFI_TYPE_SINT32:
+         (raw++)->sint = *(SINT32*) (*args);
+         break;
+#endif
+
+#if !FFI_NO_STRUCTS
+       case FFI_TYPE_STRUCT:
+         (raw++)->ptr = *args;
+         break;
+#endif
+
+       case FFI_TYPE_POINTER:
+         (raw++)->ptr = **(void***) args;
+         break;
+
+       default:
+         memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
+         raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
+       }
+    }
+}
+
+#if !FFI_NATIVE_RAW_API
+
+
+/* This is a generic definition of ffi_raw_call, to be used if the
+ * native system does not provide a machine-specific implementation.
+ * Having this, allows code to be written for the raw API, without
+ * the need for system-specific code to handle input in that format;
+ * these following couple of functions will handle the translation forth
+ * and back automatically. */
+
+void ffi_raw_call (/*@dependent@*/ ffi_cif *cif, 
+                  void (*fn)(), 
+                  /*@out@*/ void *rvalue, 
+                  /*@dependent@*/ ffi_raw *raw)
+{
+  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
+  ffi_raw_to_ptrarray (cif, raw, avalue);
+  ffi_call (cif, fn, rvalue, avalue);
+}
+
+#if FFI_CLOSURES               /* base system provides closures */
+
+static void 
+ffi_translate_args (ffi_cif *cif, void *rvalue,
+                   void **avalue, void *user_data)
+{
+  ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
+  ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
+
+  ffi_ptrarray_to_raw (cif, avalue, raw);
+  (*cl->fun) (cif, rvalue, raw, cl->user_data);
+}
+
+/* Again, here is the generic version of ffi_prep_raw_closure, which
+ * will install an intermediate "hub" for translation of arguments from
+ * the pointer-array format, to the raw format */
+
+ffi_status
+ffi_prep_raw_closure (ffi_raw_closure* cl,
+                     ffi_cif *cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data)
+{
+  ffi_status status;
+
+  status = ffi_prep_closure ((ffi_closure*) cl, 
+                            cif,
+                            &ffi_translate_args,
+                            (void*)cl);
+  if (status == FFI_OK)
+    {
+      cl->fun       = fun;
+      cl->user_data = user_data;
+    }
+
+  return status;
+}
+
+#endif /* FFI_CLOSURES */
+#endif /* !FFI_NATIVE_RAW_API */
+#endif /* !FFI_NO_RAW_API */
diff --git a/libffi/types.c b/libffi/types.c
new file mode 100644 (file)
index 0000000..76aff40
--- /dev/null
@@ -0,0 +1,154 @@
+/* -----------------------------------------------------------------------
+   types.c - Copyright (c) 1996, 1998  Cygnus Solutions
+   
+   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 RED HAT 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_private.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
+
+FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
+
+#endif
+
+#ifdef __i386__
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
+
+#elif defined X86_WIN32
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
+
+#elif defined ARM
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
+
+#elif defined M68K
+
+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
+
+
+#ifdef __i386__
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
+
+#elif defined X86_WIN32
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
+
+#elif defined ARM
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
+
+#elif defined M68K
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 12, 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
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
+
+#endif
+
+#if SIZEOF_SHORT==1
+extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint8")));
+extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint8")));
+#elif SIZEOF_SHORT==2
+extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint16")));
+extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint16")));
+#elif SIZEOF_SHORT==4
+extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint32")));
+extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint32")));
+#endif
+
+#if SIZEOF_INT==2
+extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint16")));
+extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint16")));
+#elif SIZEOF_INT==4
+extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint32")));
+extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint32")));
+#elif SIZEOF_INT==8
+extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint64")));
+extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint64")));
+#endif
+
+#if SIZEOF_LONG==4
+extern ffi_type ffi_type_slong __attribute__((alias("ffi_type_sint32")));
+extern ffi_type ffi_type_ulong __attribute__((alias("ffi_type_uint32")));
+#elif SIZEOF_INT==8
+extern ffi_type ffi_type_slong __attribute__((alias("ffi_type_sint64")));
+extern ffi_type ffi_type_ulong __attribute__((alias("ffi_type_uint64")));
+#endif
+