diff --git a/SWIG/Lib/cffi/cffi.swg b/SWIG/Lib/cffi/cffi.swg new file mode 100644 index 000000000..c87eeff3d --- /dev/null +++ b/SWIG/Lib/cffi/cffi.swg @@ -0,0 +1,96 @@ +/* Define a C preprocessor symbol that can be used in interface files + to distinguish between the SWIG language modules. */ + +#define SWIG_CFFI + +/* Typespecs for basic types. */ + +%typemap(cin) void ":void"; + +%typemap(cin) char ":char"; +%typemap(cin) char * ":string"; +%typemap(cin) unsigned char ":unsigned-char"; +%typemap(cin) signed char ":char"; + +%typemap(cin) short ":short"; +%typemap(cin) signed short ":short"; +%typemap(cin) unsigned short ":unsigned-short"; + +%typemap(cin) int ":int"; +%typemap(cin) signed int ":int"; +%typemap(cin) unsigned int ":unsigned-nt"; + +%typemap(cin) long ":long"; +%typemap(cin) signed long ":long"; +%typemap(cin) unsigned long ":unsigned-long"; + +%typemap(cin) float ":float"; +%typemap(cin) double ":double"; +%typemap(cin) SWIGTYPE ":pointer"; + +%typemap(cout) void ":void"; + +%typemap(cout) char ":char"; +%typemap(cout) char * ":string"; +%typemap(cout) unsigned char ":unsigned-char"; +%typemap(cout) signed char ":char"; + +%typemap(cout) short ":short"; +%typemap(cout) signed short ":short"; +%typemap(cout) unsigned short ":unsigned-short"; + +%typemap(cout) int ":int"; +%typemap(cout) signed int ":int"; +%typemap(cout) unsigned int ":unsigned-nt"; + +%typemap(cout) long ":long"; +%typemap(cout) signed long ":long"; +%typemap(cout) unsigned long ":unsigned-long"; + +%typemap(cout) float ":float"; +%typemap(cout) double ":double"; +%typemap(cout) SWIGTYPE ":pointer"; + + +%typemap(ctype) bool "int"; +%typemap(ctype) char, unsigned char, signed char, + short, signed short, unsigned short, + int, signed int, unsigned int, + long, signed long, unsigned long, + float, double, long double, char *, void *, void, + enum SWIGTYPE, SWIGTYPE *, + SWIGTYPE[ANY], SWIGTYPE & "$1_ltype"; +%typemap(ctype) SWIGTYPE "$&1_type"; + +%typemap(in) bool "$1 = (bool)$input;"; +%typemap(in) char, unsigned char, signed char, + short, signed short, unsigned short, + int, signed int, unsigned int, + long, signed long, unsigned long, + float, double, long double, char *, void *, void, + enum SWIGTYPE, SWIGTYPE *, + SWIGTYPE[ANY], SWIGTYPE & "$1 = $input;"; +%typemap(in) SWIGTYPE "$1 = *$input;"; + +%typemap(out) bool "$result = (int)$1;"; +%typemap(out) char, unsigned char, signed char, + short, signed short, unsigned short, + int, signed int, unsigned int, + long, signed long, unsigned long, + float, double, long double, char *, void *, void, + enum SWIGTYPE, SWIGTYPE *, + SWIGTYPE[ANY], SWIGTYPE & "$result = $1;"; +%typemap(out) SWIGTYPE "$result = new $1_type($1);"; + + +%{ + +#ifdef __cplusplus +# define EXTERN extern "C" +#else +# define EXTERN extern +#endif + +#define EXPORT EXTERN SWIGEXPORT + +%} diff --git a/SWIG/Source/Modules/cffi.cxx b/SWIG/Source/Modules/cffi.cxx new file mode 100644 index 000000000..31d6c0a82 --- /dev/null +++ b/SWIG/Source/Modules/cffi.cxx @@ -0,0 +1,558 @@ +/* ----------------------------------------------------------------------------- + * cffi.cxx + * + * cffi module. + * + * Author(s) : Surendra Singhi (surendra@asu.edu) + * + * Copyright (C) 2005 Surendra Singhi + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_cffi_cxx[] = "$Header$"; + +#include +#include "swigmod.h" +#include "cparse.h" + +#define CFFI_DEBUG +class CFFI : public Language { +public: + File *f_cl; + String *f_clhead; + String *f_clwrap; + + File *f_cxx; + File *f_cxx_header; + File *f_cxx_wrapper; + + String *module; + virtual void main(int argc, char *argv[]); + virtual int top(Node *n); + virtual int functionWrapper(Node *n); + virtual int variableWrapper(Node *n); + virtual int constantWrapper(Node *n); + // virtual int classDeclaration(Node *n); + virtual int enumDeclaration(Node *n); + virtual int typedefHandler(Node *n); + + //c++ specific code + virtual int constructorHandler(Node *n); + virtual int destructorHandler(Node *n); + virtual int memberfunctionHandler(Node *n); + virtual int membervariableHandler(Node *n); + virtual int classHandler(Node *n); + +private: + void emit_defun(Node *n, String *name); + void emit_struct_union(Node *n, bool un); + String* lispify_name(String *ty); + String* convert_literal(String *num_param, String *type); + String* strip_parens(String *string); + int extern_all_flag; + int generate_typedef_flag; +}; + +void CFFI :: main(int argc, char *argv[]) { + int i; + + SWIG_library_directory("cffi"); + SWIG_config_file("cffi.swg"); + generate_typedef_flag = 0; + extern_all_flag=0; + + for(i=1; icode,"%s\n", parm_code); + p = Getattr(p,"tmap:in:next"); + } + + Delete(arg); + } + Printf(name_and_parms, ")"); + + // Emit the function definition + String *signature = SwigType_str(return_type, name_and_parms); + Printf(wrap->def, "EXPORT %s {", signature); + Printf(wrap->code," try {\n"); + emit_action(n, wrap); + if (!is_void_return) + { + String *result_convert = Swig_typemap_lookup_new("out",n,"result",0); + Replaceall(result_convert, "$result", "lresult"); + Printf(wrap->code, "%s\n", result_convert); + Printf(wrap->code, " return lresult;\n"); + Delete(result_convert); + } + + Printf(wrap->code," } catch (...) {\n"); + if (!is_void_return) + Printf(wrap->code," return (%s)0;\n", raw_return_type); + Printf(wrap->code," }\n"); + Printf(wrap->code,"}\n"); + + if (CPlusPlus) + Wrapper_print(wrap, f_cxx); + + if (CPlusPlus) + emit_defun(n,wname); + else + emit_defun(n,iname); + + // if (!overloaded || !Getattr(n, "sym:nextSibling")) { + // update_package_if_needed(n); + // emit_buffered_defuns(n); + // // this is the last overload. + // if (overloaded) { + // emit_dispatch_defun(n); + // } + // } + + return SWIG_OK; +} + + +void CFFI::emit_defun(Node *n,String *name) +{ + +// String *storage=Getattr(n,"storage"); +// if(!extern_all_flag && (!storage || (Strcmp(storage,"extern") && Strcmp(storage,"externc")))) +// return SWIG_OK; + + String *func_name=Getattr(n, "sym:name"); + + ParmList *pl=Getattr(n, "parms"); + + int argnum=0, first=1; + + Printf(f_cl, "\n(defcfun (\"%s\" %s)", name, func_name); + String *ffitype= Swig_typemap_lookup_new("cout",n,":pointer",0); + + Printf(f_cl, " %s", ffitype); + Delete(ffitype); + + for (Parm *p=pl; p; p=nextSibling(p), argnum++) { + + String *argname=Getattr(p, "name"); + + ffitype = Swig_typemap_lookup_new("cin",p, "",0); + + int tempargname=0; + + if (!argname) { + argname=NewStringf("arg%d", argnum); + tempargname=1; + } + + Printf(f_cl, "\n (%s %s)", argname, ffitype); + first=0; + + Delete(ffitype); + + if (tempargname) + Delete(argname); + } + Printf(f_cl, ")\n"); /* finish arg list */ +} + + +int CFFI :: constantWrapper(Node *n) { + String *type=Getattr(n, "type"); + String *converted_value=convert_literal(Getattr(n, "value"), type); + String *name=Getattr(n, "sym:name"); + + Printf(f_cl, "\n(defconstant %s %s)\n", name, converted_value); + Delete(converted_value); + + return SWIG_OK; +} + +int CFFI :: variableWrapper(Node *n) { + String *storage=Getattr(n,"storage"); + + if(!extern_all_flag && (!storage || (Strcmp(storage,"extern") && Strcmp(storage,"externc")))) + return SWIG_OK; + + String *var_name=Getattr(n, "sym:name"); + String *lisp_type = Swig_typemap_lookup_new("cin",n, "",0); + Printf(f_cl,"\n(defcvar (\"%s\" %s)\n %s)\n",var_name,var_name,lisp_type); + + Delete(lisp_type); + return SWIG_OK; +} + +int CFFI :: typedefHandler(Node *n) { + if(generate_typedef_flag) { + Printf(f_cl,"\n(defctype %s %s)\n",Getattr(n,"name"),Swig_typemap_lookup_new("cin",n, "",0)); + } + return Language::typedefHandler(n); +} + +int CFFI :: enumDeclaration(Node *n) { + String *name=Getattr(n, "sym:name"); + + Printf(f_cl,"\n(defcenum %s ",name); + + for (Node *c=firstChild(n); c; c=nextSibling(c)) { + + String *slot_name = Getattr(c, "name"); + String *value = Getattr(c, "enumvalue"); + + Printf(f_cl,"(:%s %s)",slot_name,value); + + Delete(value); + } + + Printf(f_cl, ")\n"); + return SWIG_OK; +} + +// Includes structs +void CFFI :: emit_struct_union(Node *n, bool un=false) { + String *name=Getattr(n, "sym:name"); + String *kind = Getattr(n,"kind"); + + if (Strcmp(kind, "struct")) { + Printf(stderr, "Don't know how to deal with %s kind of class yet.\n", + kind); + Printf(stderr, " (name: %s)\n", name); + SWIG_exit(EXIT_FAILURE); + } + + if(un) + Printf(f_cl,"\n(defcunion %s",name); + else + Printf(f_cl,"\n(defcstruct %s",name); + + for (Node *c=firstChild(n); c; c=nextSibling(c)) { + + if (Strcmp(nodeType(c), "cdecl")) { + Printf(stderr, "Structure %s has a slot that we can't deal with.\n", + name); + Printf(stderr, "nodeType: %s, name: %s, type: %s\n", + nodeType(c), + Getattr(c, "name"), + Getattr(c, "type")); + SWIG_exit(EXIT_FAILURE); + } + + String *temp=Copy(Getattr(c,"decl")); + Append(temp,Getattr(c,"type")); //appending type to the end, otherwise wrong type + String *lisp_type=Swig_typemap_lookup_new("cin",c, "",0); + Delete(temp); + + String *slot_name = Getattr(c, "sym:name"); + Printf(f_cl, + "\n\t(%s %s)", + slot_name, + lisp_type); + + Delete(lisp_type); + } + + Printf(f_cl, ")\n"); + + /* Add this structure to the known lisp types */ + //Printf(stdout, "Adding %s foreign type\n", name); + // add_defined_foreign_type(name); + +} + +/* utilities */ +/* returns new string w/ parens stripped */ +String* CFFI::strip_parens(String *string) { + char *s=Char(string), *p; + int len=Len(string); + String *res; + + if (len==0 || s[0] != '(' || s[len-1] != ')') { + return NewString(string); + } + + p=(char *)malloc(len-2+1); + if (!p) { + Printf(stderr, "Malloc failed\n"); + SWIG_exit(EXIT_FAILURE); + } + + strncpy(p, s+1, len-1); + p[len-2]=0; /* null terminate */ + + res=NewString(p); + free(p); + + return res; +} + +String* CFFI::convert_literal(String *num_param, String *type) { + String *num=strip_parens(num_param), *res; + char *s=Char(num); + + /* Make sure doubles use 'd' instead of 'e' */ + if (!Strcmp(type, "double")) { + String *updated=Copy(num); + if (Replace(updated, "e", "d", DOH_REPLACE_ANY) > 1) { + Printf(stderr, "Weird!! number %s looks invalid.\n", num); + SWIG_exit(EXIT_FAILURE); + } + Delete(num); + return updated; + } + + if (SwigType_type(type) == T_CHAR) { + /* Use CL syntax for character literals */ + return NewStringf("#\\%s", num_param); + } + else if (SwigType_type(type) == T_STRING) { + /* Use CL syntax for string literals */ + return NewStringf("\"%s\"", num_param); + } + + if (Len(num) < 2 || s[0] != '0') { + return num; + } + + /* octal or hex */ + + res=NewStringf("#%c%s", + s[1] == 'x' ? 'x' : 'o', + s+2); + Delete(num); + + return res; +} + +extern "C" Language *swig_cffi(void) { + return new CFFI(); +} + +