Back to index

plt-scheme  4.2.1
raw_api.c
Go to the documentation of this file.
00001 /* -----------------------------------------------------------------------
00002    raw_api.c - Copyright (c) 1999  Red Hat, Inc.
00003 
00004    Author: Kresten Krab Thorup <krab@gnu.org>
00005 
00006    $Id $
00007 
00008    Permission is hereby granted, free of charge, to any person obtaining
00009    a copy of this software and associated documentation files (the
00010    ``Software''), to deal in the Software without restriction, including
00011    without limitation the rights to use, copy, modify, merge, publish,
00012    distribute, sublicense, and/or sell copies of the Software, and to
00013    permit persons to whom the Software is furnished to do so, subject to
00014    the following conditions:
00015 
00016    The above copyright notice and this permission notice shall be included
00017    in all copies or substantial portions of the Software.
00018 
00019    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
00020    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00021    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00022    IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
00023    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00024    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00025    OTHER DEALINGS IN THE SOFTWARE.
00026    ----------------------------------------------------------------------- */
00027 
00028 /* This file defines generic functions for use with the raw api. */
00029 
00030 #include <ffi.h>
00031 #include <ffi_common.h>
00032 
00033 #if !FFI_NO_RAW_API
00034 
00035 size_t
00036 ffi_raw_size (ffi_cif *cif)
00037 {
00038   size_t result = 0;
00039   int i;
00040 
00041   ffi_type **at = cif->arg_types;
00042 
00043   for (i = cif->nargs-1; i >= 0; i--, at++)
00044     {
00045 #if !FFI_NO_STRUCTS
00046       if ((*at)->type == FFI_TYPE_STRUCT)
00047        result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
00048       else
00049 #endif
00050        result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
00051     }
00052 
00053   return result;
00054 }
00055 
00056 
00057 void
00058 ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
00059 {
00060   unsigned i;
00061   ffi_type **tp = cif->arg_types;
00062 
00063 #if WORDS_BIGENDIAN
00064 
00065   for (i = 0; i < cif->nargs; i++, tp++, args++)
00066     {    
00067       switch ((*tp)->type)
00068        {
00069        case FFI_TYPE_UINT8:
00070        case FFI_TYPE_SINT8:
00071          *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
00072          break;
00073          
00074        case FFI_TYPE_UINT16:
00075        case FFI_TYPE_SINT16:
00076          *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
00077          break;
00078 
00079 #if FFI_SIZEOF_ARG >= 4       
00080        case FFI_TYPE_UINT32:
00081        case FFI_TYPE_SINT32:
00082          *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
00083          break;
00084 #endif
00085        
00086 #if !FFI_NO_STRUCTS  
00087        case FFI_TYPE_STRUCT:
00088          *args = (raw++)->ptr;
00089          break;
00090 #endif
00091 
00092        case FFI_TYPE_POINTER:
00093          *args = (void*) &(raw++)->ptr;
00094          break;
00095          
00096        default:
00097          *args = raw;
00098          raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
00099        }
00100     }
00101 
00102 #else /* WORDS_BIGENDIAN */
00103 
00104 #if !PDP
00105 
00106   /* then assume little endian */
00107   for (i = 0; i < cif->nargs; i++, tp++, args++)
00108     {    
00109 #if !FFI_NO_STRUCTS
00110       if ((*tp)->type == FFI_TYPE_STRUCT)
00111        {
00112          *args = (raw++)->ptr;
00113        }
00114       else
00115 #endif
00116        {
00117          *args = (void*) raw;
00118          raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
00119        }
00120     }
00121 
00122 #else
00123 #error "pdp endian not supported"
00124 #endif /* ! PDP */
00125 
00126 #endif /* WORDS_BIGENDIAN */
00127 }
00128 
00129 void
00130 ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
00131 {
00132   unsigned i;
00133   ffi_type **tp = cif->arg_types;
00134 
00135   for (i = 0; i < cif->nargs; i++, tp++, args++)
00136     {    
00137       switch ((*tp)->type)
00138        {
00139        case FFI_TYPE_UINT8:
00140          (raw++)->uint = *(UINT8*) (*args);
00141          break;
00142 
00143        case FFI_TYPE_SINT8:
00144          (raw++)->sint = *(SINT8*) (*args);
00145          break;
00146 
00147        case FFI_TYPE_UINT16:
00148          (raw++)->uint = *(UINT16*) (*args);
00149          break;
00150 
00151        case FFI_TYPE_SINT16:
00152          (raw++)->sint = *(SINT16*) (*args);
00153          break;
00154 
00155 #if FFI_SIZEOF_ARG >= 4
00156        case FFI_TYPE_UINT32:
00157          (raw++)->uint = *(UINT32*) (*args);
00158          break;
00159 
00160        case FFI_TYPE_SINT32:
00161          (raw++)->sint = *(SINT32*) (*args);
00162          break;
00163 #endif
00164 
00165 #if !FFI_NO_STRUCTS
00166        case FFI_TYPE_STRUCT:
00167          (raw++)->ptr = *args;
00168          break;
00169 #endif
00170 
00171        case FFI_TYPE_POINTER:
00172          (raw++)->ptr = **(void***) args;
00173          break;
00174 
00175        default:
00176          memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
00177          raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
00178        }
00179     }
00180 }
00181 
00182 #if !FFI_NATIVE_RAW_API
00183 
00184 
00185 /* This is a generic definition of ffi_raw_call, to be used if the
00186  * native system does not provide a machine-specific implementation.
00187  * Having this, allows code to be written for the raw API, without
00188  * the need for system-specific code to handle input in that format;
00189  * these following couple of functions will handle the translation forth
00190  * and back automatically. */
00191 
00192 void ffi_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw)
00193 {
00194   void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
00195   ffi_raw_to_ptrarray (cif, raw, avalue);
00196   ffi_call (cif, fn, rvalue, avalue);
00197 }
00198 
00199 #if FFI_CLOSURES            /* base system provides closures */
00200 
00201 static void
00202 ffi_translate_args (ffi_cif *cif, void *rvalue,
00203                   void **avalue, void *user_data)
00204 {
00205   ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
00206   ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
00207 
00208   ffi_ptrarray_to_raw (cif, avalue, raw);
00209   (*cl->fun) (cif, rvalue, raw, cl->user_data);
00210 }
00211 
00212 ffi_status
00213 ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
00214                        ffi_cif *cif,
00215                        void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
00216                        void *user_data,
00217                        void *codeloc)
00218 {
00219   ffi_status status;
00220 
00221   status = ffi_prep_closure_loc ((ffi_closure*) cl,
00222                              cif,
00223                              &ffi_translate_args,
00224                              codeloc,
00225                              codeloc);
00226   if (status == FFI_OK)
00227     {
00228       cl->fun       = fun;
00229       cl->user_data = user_data;
00230     }
00231 
00232   return status;
00233 }
00234 
00235 #endif /* FFI_CLOSURES */
00236 #endif /* !FFI_NATIVE_RAW_API */
00237 
00238 #if FFI_CLOSURES
00239 
00240 /* Again, here is the generic version of ffi_prep_raw_closure, which
00241  * will install an intermediate "hub" for translation of arguments from
00242  * the pointer-array format, to the raw format */
00243 
00244 ffi_status
00245 ffi_prep_raw_closure (ffi_raw_closure* cl,
00246                     ffi_cif *cif,
00247                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
00248                     void *user_data)
00249 {
00250   return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
00251 }
00252 
00253 #endif /* FFI_CLOSURES */
00254 
00255 #endif /* !FFI_NO_RAW_API */