Mercurial > pub > dyncall > dyncall
annotate dyncall/dyncall_callf.c @ 359:e8a13c880399
- better implementation of callf sigchar cc mode checking
author | Tassilo Philipp |
---|---|
date | Mon, 13 Apr 2020 16:01:17 +0200 |
parents | 30aae7371373 |
children | 78dfa2f9783a |
rev | line source |
---|---|
0 | 1 /* |
2 | |
3 Package: dyncall | |
4 Library: dyncall | |
5 File: dyncall/dyncall_callf.c | |
6 Description: formatted call C interface (extension module) | |
7 License: | |
8 | |
281 | 9 Copyright (c) 2007-2018 Daniel Adler <dadler@uni-goettingen.de>, |
0 | 10 Tassilo Philipp <tphilipp@potion-studios.com> |
11 | |
12 Permission to use, copy, modify, and distribute this software for any | |
13 purpose with or without fee is hereby granted, provided that the above | |
14 copyright notice and this permission notice appear in all copies. | |
15 | |
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
23 | |
24 */ | |
25 | |
26 | |
27 | |
28 #include "dyncall_callf.h" | |
29 | |
30 | |
171
011b5e3a8548
- compatibility for older platforms - use ANSI comments
cslag
parents:
74
diff
changeset
|
31 /* Shareable implementation for argument binding used in ArgF and CallF below. */ |
0 | 32 static void dcArgF_impl(DCCallVM* vm, const DCsigchar** sigptr, va_list args) |
33 { | |
34 DCsigchar ch; | |
35 dcReset(vm); | |
36 while((ch=*(*sigptr)++) != '\0' && ch != DC_SIGCHAR_ENDARG) { | |
37 switch(ch) { | |
358
30aae7371373
- extended signature with calling convention mode switches for fastcall (gnu), default, cdecl, stdcall, arm (arm), arm (thumb), syscall
Tassilo Philipp
parents:
281
diff
changeset
|
38 /* types */ |
0 | 39 case DC_SIGCHAR_BOOL: dcArgBool (vm, (DCbool) va_arg(args, DCint )); break; |
40 case DC_SIGCHAR_CHAR: dcArgChar (vm, (DCchar) va_arg(args, DCint )); break; | |
41 case DC_SIGCHAR_UCHAR: dcArgChar (vm, (DCchar)(DCuchar) va_arg(args, DCint )); break; | |
42 case DC_SIGCHAR_SHORT: dcArgShort (vm, (DCshort) va_arg(args, DCint )); break; | |
43 case DC_SIGCHAR_USHORT: dcArgShort (vm, (DCshort)(DCushort)va_arg(args, DCint )); break; | |
44 case DC_SIGCHAR_INT: dcArgInt (vm, (DCint) va_arg(args, DCint )); break; | |
45 case DC_SIGCHAR_UINT: dcArgInt (vm, (DCint)(DCuint) va_arg(args, DCint )); break; | |
46 case DC_SIGCHAR_LONG: dcArgLong (vm, (DClong) va_arg(args, DClong )); break; | |
47 case DC_SIGCHAR_ULONG: dcArgLong (vm, (DCulong) va_arg(args, DClong )); break; | |
48 case DC_SIGCHAR_LONGLONG: dcArgLongLong(vm, (DClonglong) va_arg(args, DClonglong)); break; | |
49 case DC_SIGCHAR_ULONGLONG: dcArgLongLong(vm, (DCulonglong) va_arg(args, DClonglong)); break; | |
50 case DC_SIGCHAR_FLOAT: dcArgFloat (vm, (DCfloat) va_arg(args, DCdouble )); break; | |
51 case DC_SIGCHAR_DOUBLE: dcArgDouble (vm, (DCdouble) va_arg(args, DCdouble )); break; | |
52 case DC_SIGCHAR_POINTER: dcArgPointer (vm, (DCpointer) va_arg(args, DCpointer )); break; | |
53 case DC_SIGCHAR_STRING: dcArgPointer (vm, (DCpointer) va_arg(args, DCpointer )); break; | |
358
30aae7371373
- extended signature with calling convention mode switches for fastcall (gnu), default, cdecl, stdcall, arm (arm), arm (thumb), syscall
Tassilo Philipp
parents:
281
diff
changeset
|
54 /* calling convention modes */ |
30aae7371373
- extended signature with calling convention mode switches for fastcall (gnu), default, cdecl, stdcall, arm (arm), arm (thumb), syscall
Tassilo Philipp
parents:
281
diff
changeset
|
55 case DC_SIGCHAR_CC_PREFIX: |
30aae7371373
- extended signature with calling convention mode switches for fastcall (gnu), default, cdecl, stdcall, arm (arm), arm (thumb), syscall
Tassilo Philipp
parents:
281
diff
changeset
|
56 { |
359
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
57 if(*((*sigptr)+1) != '\0') { |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
58 switch(*(*sigptr)++) { |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
59 case DC_SIGCHAR_CC_DEFAULT: dcMode(vm, DC_CALL_C_DEFAULT ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
60 case DC_SIGCHAR_CC_ELLIPSIS: dcMode(vm, DC_CALL_C_ELLIPSIS ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
61 case DC_SIGCHAR_CC_ELLIPSIS_VARARGS: dcMode(vm, DC_CALL_C_ELLIPSIS_VARARGS ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
62 #if defined(DC__Arch_Intel_x86) /* @@@ theoretically not needed, if mode isn't understood the implementations shouldn't attempt ny mode switch */ |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
63 case DC_SIGCHAR_CC_CDECL: dcMode(vm, DC_CALL_C_X86_CDECL ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
64 case DC_SIGCHAR_CC_STDCALL: dcMode(vm, DC_CALL_C_X86_WIN32_STD ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
65 case DC_SIGCHAR_CC_FASTCALL_MS: dcMode(vm, DC_CALL_C_X86_WIN32_FAST_MS ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
66 case DC_SIGCHAR_CC_FASTCALL_GNU: dcMode(vm, DC_CALL_C_X86_WIN32_FAST_GNU); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
67 case DC_SIGCHAR_CC_THISCALL_MS: dcMode(vm, DC_CALL_C_X86_WIN32_THIS_MS ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
68 case DC_SIGCHAR_CC_THISCALL_GNU: dcMode(vm, DC_CALL_C_X86_WIN32_THIS_GNU); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
69 #elif defined(DC__Arch_ARM) /* @@@ theoretically not needed, if mode isn't understood the implementations shouldn't attempt any mode switch */ |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
70 case DC_SIGCHAR_CC_ARM_ARM: dcMode(vm, DC_CALL_C_ARM_ARM ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
71 case DC_SIGCHAR_CC_ARM_THUMB: dcMode(vm, DC_CALL_C_ARM_THUMB ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
72 #endif |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
73 case DC_SIGCHAR_CC_SYSCALL: dcMode(vm, DC_CALL_SYS_DEFAULT ); break; |
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
74 } |
358
30aae7371373
- extended signature with calling convention mode switches for fastcall (gnu), default, cdecl, stdcall, arm (arm), arm (thumb), syscall
Tassilo Philipp
parents:
281
diff
changeset
|
75 } |
30aae7371373
- extended signature with calling convention mode switches for fastcall (gnu), default, cdecl, stdcall, arm (arm), arm (thumb), syscall
Tassilo Philipp
parents:
281
diff
changeset
|
76 } |
359
e8a13c880399
- better implementation of callf sigchar cc mode checking
Tassilo Philipp
parents:
358
diff
changeset
|
77 break; |
0 | 78 } |
79 } | |
80 } | |
81 | |
82 void dcVArgF(DCCallVM* vm, const DCsigchar* signature, va_list args) | |
83 { | |
84 dcArgF_impl(vm, &signature, args); | |
85 } | |
86 | |
87 void dcArgF(DCCallVM* vm, const DCsigchar* signature, ...) | |
88 { | |
89 va_list va; | |
90 va_start(va, signature); | |
91 dcVArgF(vm,signature,va); | |
92 va_end(va); | |
93 } | |
94 | |
95 void dcVCallF(DCCallVM* vm, DCValue* result, DCpointer funcptr, const DCsigchar* signature, va_list args) | |
96 { | |
97 const DCsigchar* ptr = signature; | |
98 dcArgF_impl(vm, &ptr, args); | |
99 | |
100 switch(*ptr) { | |
74
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
101 case DC_SIGCHAR_VOID: dcCallVoid (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
102 case DC_SIGCHAR_BOOL: result->B = dcCallBool (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
103 case DC_SIGCHAR_CHAR: result->c = dcCallChar (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
104 case DC_SIGCHAR_UCHAR: result->C = (DCuchar)dcCallChar (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
105 case DC_SIGCHAR_SHORT: result->s = dcCallShort (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
106 case DC_SIGCHAR_USHORT: result->S = dcCallShort (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
107 case DC_SIGCHAR_INT: result->i = dcCallInt (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
108 case DC_SIGCHAR_UINT: result->I = dcCallInt (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
109 case DC_SIGCHAR_LONG: result->j = dcCallLong (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
110 case DC_SIGCHAR_ULONG: result->J = dcCallLong (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
111 case DC_SIGCHAR_LONGLONG: result->l = dcCallLongLong (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
112 case DC_SIGCHAR_ULONGLONG: result->L = dcCallLongLong (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
113 case DC_SIGCHAR_FLOAT: result->f = dcCallFloat (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
114 case DC_SIGCHAR_DOUBLE: result->d = dcCallDouble (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
115 case DC_SIGCHAR_POINTER: result->p = dcCallPointer (vm,funcptr); break; |
f2a8dfd795e8
- pointer cast for callf to make C++ compilers happy that don't do void* implicit casts (also, as DC_POINTER might be set to something other than void*, this cast would be needed)
cslag
parents:
0
diff
changeset
|
116 case DC_SIGCHAR_STRING: result->Z = (DCstring)dcCallPointer(vm,funcptr); break; |
0 | 117 } |
118 } | |
119 | |
120 void dcCallF(DCCallVM* vm, DCValue* result, DCpointer funcptr, const DCsigchar* signature, ...) | |
121 { | |
122 va_list va; | |
123 va_start(va, signature); | |
124 dcVCallF(vm,result,funcptr,signature,va); | |
125 va_end(va); | |
126 } | |
127 |