Mercurial > pub > dyncall > bindings
diff shell/shdc/shdc.c @ 0:0cfcc391201f
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:26:28 +0100 |
parents | |
children | 5e159be89d73 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shell/shdc/shdc.c Thu Mar 19 22:26:28 2015 +0100 @@ -0,0 +1,187 @@ +/* + Package: dyncall + File: bindings/shell.c + Description: printf(1) style function call mechanism + License: + Copyright (c) 2007-2014 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/dyncall/dyncall.h" +#include "../../dyncall/dynload/dynload.h" +#include "../../dyncall/dyncall/dyncall_signature.h" +#include <stdio.h> +#include <stdlib.h> /* needed on some platforms to make atof work _at_runtime_ */ + +#define SHDC_VERSION "0.8" + + +void usage(const char* s) +{ + printf( + "Usage: %s -l SO\n" + " %s -c SO SYM SIG [ARGS]\n" + " %s -v\n" + " where SO is the name of the shared object.\n" + "\n" + " -l lists all symbol names in the shared object\n" + " -c calls function in the shared object, where SYM is the symbol name,\n" + " SIG the symbol's type signature, and ARGS the arguments.\n" + " -v displays the binding's version\n", + s, s, s + ); +} + + +int main(int argc, char* argv[]) +{ + const char* libPath; + const char* symName; + const DCsigchar* sig; + const DCsigchar* i; + void* sym; + DCCallVM* vm; + DLLib* dlLib; + DLSyms* dlSyms; + int c, l; + + if(argc == 2 && strcmp(argv[1], "-v") == 0) { + printf(SHDC_VERSION"\n"); + return 0; + } + + /* Parse arguments and check validity. */ + /* Need at least shared object name and action, and symbol name and signature string for call. */ + if(argc < 2) { + usage(argv[0]); + return 1; + } + + c = strcmp(argv[1], "-c"); + l = strcmp(argv[1], "-l"); + if((c != 0 && l != 0) || (c == 0 && argc < 4)) { + usage(argv[0]); + return 1; + } + + + libPath = argv[2]; + + /* List symbols, if 'ls', else it must be 'call', so proceed to call. */ + if(l == 0) { + dlSyms = dlSymsInit(libPath); + if(!dlSyms) { + printf("Can't load \"%s\".\n", libPath); + usage(argv[0]); + return 1; + } + + /* hacky: reuse c and l */ + for(c=dlSymsCount(dlSyms), l=0; l<c; ++l) + printf("%s\n", dlSymsName(dlSyms, l)); + + dlSymsCleanup(dlSyms); + } + else { + /* Check if number of arguments matches sigstring spec. */ + /*if(n != argc-4)@@@*/ /* 0 is prog, 1 is flag, 2 is lib, 3 is symbol name, 4 is sig */ + + /* Load library and get a pointer to the symbol to call. */ + dlLib = dlLoadLibrary(libPath); + if(!dlLib) { + printf("Can't load \"%s\".\n", libPath); + usage(argv[0]); + return 1; + } + + symName = argv[3]; + sig = i = argv[4]; + + sym = dlFindSymbol(dlLib, symName); + if(!sym) { + printf("Can't find symbol \"%s\".\n", symName); + dlFreeLibrary(dlLib); + usage(argv[0]); + return 1; + } + + + vm = dcNewCallVM(4096/*@@@*/);/*@@@ error checking */ + dcReset(vm); + + while(*i != '\0' && *i != DC_SIGCHAR_ENDARG) { + switch(*i) { + case DC_SIGCHAR_CC_PREFIX: + switch(*++i) { + case DC_SIGCHAR_CC_ELLIPSIS: dcMode(vm, DC_CALL_C_ELLIPSIS); break; + case DC_SIGCHAR_CC_STDCALL: dcMode(vm, DC_CALL_C_X86_WIN32_STD); break; + case DC_SIGCHAR_CC_FASTCALL_GNU: dcMode(vm, DC_CALL_C_X86_WIN32_FAST_GNU); break; + case DC_SIGCHAR_CC_FASTCALL_MS: dcMode(vm, DC_CALL_C_X86_WIN32_FAST_MS); break; + case DC_SIGCHAR_CC_THISCALL_MS: dcMode(vm, DC_CALL_C_X86_WIN32_THIS_MS); break; + /* @@@ extend with other modes when they become available */ + } + sig += 2; + break; + + case DC_SIGCHAR_BOOL: dcArgBool (vm, (DCbool) atoi (argv[5+i-sig] )); break; + case DC_SIGCHAR_CHAR: dcArgChar (vm, (DCchar) atoi (argv[5+i-sig] )); break; + case DC_SIGCHAR_UCHAR: dcArgChar (vm, (DCchar)(DCuchar) atoi (argv[5+i-sig] )); break; + case DC_SIGCHAR_SHORT: dcArgShort (vm, (DCshort) atoi (argv[5+i-sig] )); break; + case DC_SIGCHAR_USHORT: dcArgShort (vm, (DCshort)(DCushort)atoi (argv[5+i-sig] )); break; + case DC_SIGCHAR_INT: dcArgInt (vm, (DCint) strtol (argv[5+i-sig],NULL,10)); break; + case DC_SIGCHAR_UINT: dcArgInt (vm, (DCint)(DCuint) strtoul (argv[5+i-sig],NULL,10)); break; + case DC_SIGCHAR_LONG: dcArgLong (vm, (DClong) strtol (argv[5+i-sig],NULL,10)); break; + case DC_SIGCHAR_ULONG: dcArgLong (vm, (DCulong) strtoul (argv[5+i-sig],NULL,10)); break; + case DC_SIGCHAR_LONGLONG: dcArgLongLong(vm, (DClonglong) strtoll (argv[5+i-sig],NULL,10)); break; + case DC_SIGCHAR_ULONGLONG: dcArgLongLong(vm, (DCulonglong) strtoull(argv[5+i-sig],NULL,10)); break; + case DC_SIGCHAR_FLOAT: dcArgFloat (vm, (DCfloat) atof (argv[5+i-sig] )); break; + case DC_SIGCHAR_DOUBLE: dcArgDouble (vm, (DCdouble) atof (argv[5+i-sig] )); break; + case DC_SIGCHAR_POINTER: dcArgPointer (vm, (DCpointer) argv[5+i-sig] ); break; + case DC_SIGCHAR_STRING: dcArgPointer (vm, (DCpointer) argv[5+i-sig] ); break; + } + ++i; + } + + if(*i == DC_SIGCHAR_ENDARG) + ++i; + + switch(*i) { + case '\0': + case DC_SIGCHAR_VOID: dcCallVoid (vm,sym) ; break; + case DC_SIGCHAR_BOOL: printf("%d\n", dcCallBool (vm,sym)); break; + case DC_SIGCHAR_CHAR: printf("%d\n", dcCallChar (vm,sym)); break; + case DC_SIGCHAR_UCHAR: printf("%d\n", dcCallChar (vm,sym)); break; + case DC_SIGCHAR_SHORT: printf("%d\n", dcCallShort (vm,sym)); break; + case DC_SIGCHAR_USHORT: printf("%d\n", dcCallShort (vm,sym)); break; + case DC_SIGCHAR_INT: printf("%d\n", dcCallInt (vm,sym)); break; + case DC_SIGCHAR_UINT: printf("%d\n", dcCallInt (vm,sym)); break; + case DC_SIGCHAR_LONG: printf("%d\n", dcCallLong (vm,sym)); break; + case DC_SIGCHAR_ULONG: printf("%d\n", dcCallLong (vm,sym)); break; + case DC_SIGCHAR_LONGLONG: printf("%lld\n", dcCallLongLong(vm,sym)); break; + case DC_SIGCHAR_ULONGLONG: printf("%lld\n", dcCallLongLong(vm,sym)); break; + case DC_SIGCHAR_FLOAT: printf("%g\n", dcCallFloat (vm,sym)); break; + case DC_SIGCHAR_DOUBLE: printf("%g\n", dcCallDouble (vm,sym)); break; + case DC_SIGCHAR_POINTER: printf("%x\n", dcCallPointer (vm,sym)); break; + case DC_SIGCHAR_STRING: printf( dcCallPointer (vm,sym)); break; + } + + dlFreeLibrary(dlLib); + dcFree(vm); + } + + return 0; +} +