diff dyncall/dyncall_callf.c @ 0:3e629dc19168

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:24:28 +0100
parents
children f2a8dfd795e8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dyncall/dyncall_callf.c	Thu Mar 19 22:24:28 2015 +0100
@@ -0,0 +1,102 @@
+/*
+
+ Package: dyncall
+ Library: dyncall
+ File: dyncall/dyncall_callf.c
+ Description: formatted call C interface (extension module)
+ License:
+
+   Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>, 
+                           Tassilo Philipp <tphilipp@potion-studios.com>
+
+   Permission to use, copy, modify, and distribute this software for any
+   purpose with or without fee is hereby granted, provided that the above
+   copyright notice and this permission notice appear in all copies.
+
+   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+
+
+#include "dyncall_callf.h"
+
+
+// Shareable implementation for argument binding used in ArgF and CallF  below.
+static void dcArgF_impl(DCCallVM* vm, const DCsigchar** sigptr, va_list args)
+{
+  DCsigchar ch;
+  dcReset(vm);
+  while((ch=*(*sigptr)++) != '\0' && ch != DC_SIGCHAR_ENDARG) {
+    switch(ch) {
+      case DC_SIGCHAR_BOOL:      dcArgBool    (vm, (DCbool)           va_arg(args, DCint     )); break;
+      case DC_SIGCHAR_CHAR:      dcArgChar    (vm, (DCchar)           va_arg(args, DCint     )); break;
+      case DC_SIGCHAR_UCHAR:     dcArgChar    (vm, (DCchar)(DCuchar)  va_arg(args, DCint     )); break;
+      case DC_SIGCHAR_SHORT:     dcArgShort   (vm, (DCshort)          va_arg(args, DCint     )); break;
+      case DC_SIGCHAR_USHORT:    dcArgShort   (vm, (DCshort)(DCushort)va_arg(args, DCint     )); break;
+      case DC_SIGCHAR_INT:       dcArgInt     (vm, (DCint)            va_arg(args, DCint     )); break;
+      case DC_SIGCHAR_UINT:      dcArgInt     (vm, (DCint)(DCuint)    va_arg(args, DCint     )); break;
+      case DC_SIGCHAR_LONG:      dcArgLong    (vm, (DClong)           va_arg(args, DClong    )); break;
+      case DC_SIGCHAR_ULONG:     dcArgLong    (vm, (DCulong)          va_arg(args, DClong    )); break;
+      case DC_SIGCHAR_LONGLONG:  dcArgLongLong(vm, (DClonglong)       va_arg(args, DClonglong)); break;
+      case DC_SIGCHAR_ULONGLONG: dcArgLongLong(vm, (DCulonglong)      va_arg(args, DClonglong)); break;
+      case DC_SIGCHAR_FLOAT:     dcArgFloat   (vm, (DCfloat)          va_arg(args, DCdouble  )); break;
+      case DC_SIGCHAR_DOUBLE:    dcArgDouble  (vm, (DCdouble)         va_arg(args, DCdouble  )); break;
+      case DC_SIGCHAR_POINTER:   dcArgPointer (vm, (DCpointer)        va_arg(args, DCpointer )); break;
+      case DC_SIGCHAR_STRING:    dcArgPointer (vm, (DCpointer)        va_arg(args, DCpointer )); break;
+    }
+  }
+}
+
+void dcVArgF(DCCallVM* vm, const DCsigchar* signature, va_list args)
+{
+  dcArgF_impl(vm, &signature, args);
+}
+
+void dcArgF(DCCallVM* vm, const DCsigchar* signature, ...)
+{
+  va_list va;
+  va_start(va, signature);
+  dcVArgF(vm,signature,va);
+  va_end(va);
+}
+
+void dcVCallF(DCCallVM* vm, DCValue* result, DCpointer funcptr, const DCsigchar* signature, va_list args)
+{
+  const DCsigchar* ptr = signature;
+  dcArgF_impl(vm, &ptr, args);
+
+  switch(*ptr) {
+    case DC_SIGCHAR_VOID:                   dcCallVoid         (vm,funcptr); break;
+    case DC_SIGCHAR_BOOL:       result->B = dcCallBool         (vm,funcptr); break;
+    case DC_SIGCHAR_CHAR:       result->c = dcCallChar         (vm,funcptr); break;
+    case DC_SIGCHAR_UCHAR:      result->C = (DCuchar)dcCallChar(vm,funcptr); break;
+    case DC_SIGCHAR_SHORT:      result->s = dcCallShort        (vm,funcptr); break;
+    case DC_SIGCHAR_USHORT:     result->S = dcCallShort        (vm,funcptr); break;
+    case DC_SIGCHAR_INT:        result->i = dcCallInt          (vm,funcptr); break;
+    case DC_SIGCHAR_UINT:       result->I = dcCallInt          (vm,funcptr); break;
+    case DC_SIGCHAR_LONG:       result->j = dcCallLong         (vm,funcptr); break;
+    case DC_SIGCHAR_ULONG:      result->J = dcCallLong         (vm,funcptr); break;
+    case DC_SIGCHAR_LONGLONG:   result->l = dcCallLongLong     (vm,funcptr); break;
+    case DC_SIGCHAR_ULONGLONG:  result->L = dcCallLongLong     (vm,funcptr); break;
+    case DC_SIGCHAR_FLOAT:      result->f = dcCallFloat        (vm,funcptr); break;
+    case DC_SIGCHAR_DOUBLE:     result->d = dcCallDouble       (vm,funcptr); break;
+    case DC_SIGCHAR_POINTER:    result->p = dcCallPointer      (vm,funcptr); break;
+    case DC_SIGCHAR_STRING:     result->Z = dcCallPointer      (vm,funcptr); break;
+  }
+}
+
+void dcCallF(DCCallVM* vm, DCValue* result, DCpointer funcptr, const DCsigchar* signature, ...)
+{
+  va_list va;
+  va_start(va, signature);
+  dcVCallF(vm,result,funcptr,signature,va);
+  va_end(va);
+}
+