added preliminary C++ support

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@9248 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Surendra Singhi 2006-08-13 13:22:11 +00:00
commit 3effced22a

View file

@ -14,6 +14,8 @@ char cvsroot_cffi_cxx[] = "$Header$";
#include <ctype.h>
//#define CFFI_DEBUG
//#define CFFI_WRAP_DEBUG
class CFFI : public Language {
public:
String *f_cl;
@ -23,6 +25,7 @@ public:
File *f_cxx;
File *f_cxx_header;
File *f_cxx_wrapper;
File *f_clos;
String *module;
virtual void main(int argc, char *argv[]);
@ -43,9 +46,14 @@ public:
private:
void emit_defun(Node *n, String *name);
void emit_defmethod(Node *n);
void emit_getter(Node *n);
void emit_setter(Node *n);
void emit_class(Node *n);
void emit_struct_union(Node *n, bool un);
void emit_export(Node *n,String *name);
void emit_inline(Node *n,String *name);
String* lispy_name(char *name);
String* lispify_name(Node* n,String *ty,const char* flag,bool kw=false);
String* convert_literal(String *num_param, String *type);
String* strip_parens(String *string);
@ -112,7 +120,9 @@ int CFFI :: top(Node *n) {
String *lisp_filename=NewString("");
Printf(lisp_filename, "%s%s.lisp", SWIG_output_directory(), module);
File *f_lisp=NewFile(lisp_filename, "w");
NewFile(lisp_filename, "w");
if (!f_lisp) {
FileErrorDisplay(lisp_filename);
SWIG_exit(EXIT_FAILURE);
@ -125,9 +135,20 @@ int CFFI :: top(Node *n) {
Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
SWIG_exit(EXIT_FAILURE);
}
String *clos_filename=NewString("");
Printf(clos_filename, "%s%s-clos.lisp", SWIG_output_directory(), module);
f_clos=NewFile(clos_filename, "w");
if (!f_clos) {
Close(f_lisp); Delete(f_lisp);
Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
SWIG_exit(EXIT_FAILURE);
}
}
else
else {
f_cxx=NewString("");
f_clos=NewString("");
}
f_cxx_header = f_cxx;
f_cxx_wrapper=NewString("");
@ -181,6 +202,7 @@ int CFFI :: classHandler(Node *n) {
}
else if (Strcmp(kind, "class") == 0)
{
emit_class(n);
Language::classHandler(n);
}
else
@ -216,23 +238,85 @@ int CFFI :: destructorHandler(Node *n)
return Language::destructorHandler(n);
}
int CFFI :: memberfunctionHandler(Node *n) {
#ifdef CFFI_DEBUG
Printf(stderr, "member function %s::%s\n",
Getattr(parentNode(n), "name"), Getattr(n, "name"));
#endif
void CFFI::emit_defmethod(Node*n) {
String *args_placeholder = NewStringf("");
String *args_call = NewStringf("");
ParmList *pl=Getattr(n, "parms");
int argnum=0;
Node *parent = parentNode(n);
for (Parm *p=pl; p; p=nextSibling(p), argnum++) {
String *argname=Getattr(p, "name");
String *ffitype = Swig_typemap_lookup_new("lispclass",p, "",0);
int tempargname=0;
if (!argname) {
argname=NewStringf("arg%d", argnum);
tempargname=1;
}
else if(Strcmp(argname,"t")==0 || Strcmp(argname,"T")==0) {
argname=NewStringf("t-arg%d", argnum);
tempargname=1;
}
if(Len(ffitype) > 0)
Printf(args_placeholder, " (%s %s)", argname, ffitype);
else
Printf(args_placeholder, " %s", argname, ffitype);
if(Strcmp(ffitype,lispify_name(parent,lispy_name(Char(Getattr(parent, "sym:name"))), "'classname")) == 0)
Printf(args_call, " (ff-pointer %s)", argname);
else
Printf(args_call, " %s", argname);
Delete(ffitype);
if (tempargname)
Delete(argname);
}
String *method_name = Getattr(n, "name");
int x = Replace(method_name,"operator ","",DOH_REPLACE_FIRST); //
if(x==1)
Printf(f_clos, "(shadow \"%s\")\n",method_name);
Printf(f_clos,"(defmethod %s ((obj %s)%s)\n (%s (ff-pointer obj)%s))\n\n",
lispify_name(n,lispy_name(Char(method_name)),"'method"),
lispify_name(parent,lispy_name(Char(Getattr(parent, "sym:name"))),"'class"),args_placeholder,
lispify_name(n, Getattr(n, "sym:name"), "'function"),args_call);
}
void CFFI::emit_setter(Node*n) {
Node *p = parentNode(n);
Printf(f_clos,"(defmethod (setf %s) (arg0 (obj %s))\n (%s (ff-pointer obj) arg0))\n\n",
lispify_name(n, Getattr(n, "name"), "'method"),
lispify_name(p,lispy_name(Char(Getattr(p, "sym:name"))),"'class"),
lispify_name(n, Getattr(n, "sym:name"), "'function"));
}
void CFFI::emit_getter(Node*n) {
Node *p = parentNode(n);
Printf(f_clos,"(defmethod %s ((obj %s))\n (%s (ff-pointer obj)))\n\n",
lispify_name(n, Getattr(n, "name"), "'method"),
lispify_name(p,lispy_name(Char(Getattr(p, "sym:name"))),"'class"),
lispify_name(n, Getattr(n, "sym:name"), "'function"));
}
int CFFI :: memberfunctionHandler(Node *n) {
// Let SWIG generate a global forwarding function.
Setattr(n,"cffi:memberfunction","1");
return Language::memberfunctionHandler(n);
}
int CFFI :: membervariableHandler(Node *n) {
#ifdef CFFI_DEBUG
Printf(stderr, "member variable %s::%s\n",
Getattr(parentNode(n), "name"), Getattr(n, "name"));
#endif
// Let SWIG generate a get/set function pair.
Setattr(n,"cffi:membervariable","1");
return Language::membervariableHandler(n);
}
@ -284,7 +368,7 @@ int CFFI :: functionWrapper(Node *n) {
int gencomma = 0;
#ifdef CFFI_DEBUG
Printf(stderr, "function %s - %d\n", Getattr(n, "name"),num_arguments);
Printf(stderr, "function - %s - %d\n", Getattr(n, "name"),num_arguments);
#endif
for (i = 0, p=parms; i < num_arguments; i++) {
@ -342,8 +426,17 @@ int CFFI :: functionWrapper(Node *n) {
if (CPlusPlus)
Wrapper_print(wrap, f_cxx);
if (CPlusPlus)
if (CPlusPlus) {
emit_defun(n,wname);
if(Getattr(n,"cffi:memberfunction"))
emit_defmethod(n);
else if(Getattr(n,"cffi:membervariable")) {
if(Getattr(n,"memberget"))
emit_getter(n);
else if(Getattr(n,"memberset"))
emit_setter(n);
}
}
else
emit_defun(n,iname);
@ -371,7 +464,7 @@ void CFFI::emit_defun(Node *n,String *name)
ParmList *pl=Getattr(n, "parms");
int argnum=0, first=1;
int argnum=0;
func_name=lispify_name(n, func_name, "'function");
@ -402,7 +495,6 @@ void CFFI::emit_defun(Node *n,String *name)
Printf(f_cl, "\n (%s %s)", argname, ffitype);
first=0;
Delete(ffitype);
@ -518,6 +610,115 @@ int CFFI :: enumDeclaration(Node *n) {
return SWIG_OK;
}
void CFFI :: emit_class(Node *n) {
#ifdef CFFI_WRAP_DEBUG
Printf(stderr,"emit_class: ENTER... '%s'(%x)\n", Getattr(n,"sym:name"), n);
#endif
String *name = Getattr(n, "sym:name");
String *lisp_name = lispify_name(n, lispy_name(Char(name)), "'classname");
String *bases = Getattr(n,"bases");
String *supers = NewString("(");
if(bases) {
int first=1;
for (Iterator i=First(bases); i.item; i = Next(i)) {
if (!first) Printf(supers," ");
String *s = Getattr(i.item,"name");
Printf(supers,"%s",lispify_name(i.item, s, "'classname"));
}
} else {
// Printf(supers,"ff:foreign-pointer");
}
Printf(supers,")");
Printf(f_clos,"\n(clos:defclass %s%s",lisp_name,supers);
Printf(f_clos,"\n ((ff :reader ff-pointer)))\n\n");
Parm *pattern = NewParm(Getattr(n, "name"),NULL);
Swig_typemap_register("lispclass",pattern,lisp_name,NULL,NULL);
SwigType_add_pointer(Getattr(pattern,"type"));
Swig_typemap_register("lispclass",pattern,lisp_name,NULL,NULL);
SwigType_add_qualifier(Getattr(pattern,"type"), "const");
Swig_typemap_register("lispclass",pattern,lisp_name,NULL,NULL);
SwigType_del_pointer(Getattr(pattern,"type"));
SwigType_add_reference(Getattr(pattern,"type"));
Swig_typemap_register("lispclass",pattern,lisp_name,NULL,NULL);
#ifdef CFFI_WRAP_DEBUG
Printf(stderr, " pattern %s name %s .. ... %s .\n",pattern,lisp_name);
#endif
Delete(pattern);
// Walk children to generate type definition.
String *slotdefs = NewString(" ");
#ifdef CFFI_WRAP_DEBUG
Printf(stderr, " walking children...\n");
#endif
Node *c;
for (c=firstChild(n); c; c=nextSibling(c)) {
String *storage_type = Getattr(c,"storage");
if((!Strcmp(nodeType(c),"cdecl") &&
(!storage_type || Strcmp(storage_type,"typedef")))) {
String *access = Getattr(c,"access");
// hack. why would decl have a value of "variableHandler" and now "0"?
String *childDecl = Getattr(c,"decl");
// Printf(stderr,"childDecl = '%s' (%s)\n", childDecl, Getattr(c,"view"));
if(!Strcmp(childDecl,"0"))
childDecl = NewString("");
SwigType *childType=NewStringf("%s%s", childDecl,
Getattr(c,"type"));
String *cname = (access && Strcmp(access,"public")) ?
NewString("nil") : Copy(Getattr(c,"name"));
if(!SwigType_isfunction(childType)) {
// Printf(slotdefs, ";;; member functions don't appear as slots.\n ");
// Printf(slotdefs, ";; ");
// String *ns = listify_namespace(Getattr(n, "cffi:package"));
String *ns = NewString("");
#ifdef CFFI_WRAP_DEBUG
Printf(stderr, "slot name = '%s' ns = '%s' class-of '%s' and type = '%s'\n",
cname, ns, name, childType);
#endif
Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)",
cname, ns, name, childType); //compose_foreign_type(childType)
Delete(ns);
if(access && Strcmp(access,"public"))
Printf(slotdefs, " ;; %s member", access);
Printf(slotdefs, "\n ");
}
Delete(childType);
Delete(cname);
}
}
// String *ns_list = listify_namespace(Getattr(n,"cffi:namespace"));
// update_package_if_needed(n,f_clhead);
// Printf(f_clos,
// "(swig-def-foreign-class \"%s\"\n %s\n (:%s\n%s))\n\n",
// name, supers, kind, slotdefs);
Delete(supers);
// Delete(ns_list);
// Parm *pattern = NewParm(name,NULL);
// Swig_typemap_register("cin",pattern,lisp_name,NULL,NULL);
//Swig_typemap_register("cout",pattern,lisp_name,NULL,NULL);
//Delete(pattern);
#ifdef CFFI_WRAP_DEBUG
Printf(stderr,"emit_class: EXIT\n");
#endif
}
// Includes structs
void CFFI :: emit_struct_union(Node *n, bool un=false) {
@ -696,6 +897,30 @@ String* CFFI::convert_literal(String *num_param, String *type) {
return res;
}
//less flexible as it does the conversion in C, the lispify name does the conversion in lisp
String* CFFI::lispy_name(char *name) {
bool helper=false;
String *new_name=NewString("");
for(unsigned int i=0;i < strlen(name);i++) {
if(name[i] =='_' || name[i] =='-') {
Printf(new_name,"%c",'-');
helper=false;
}
else if(name[i]>='A' && name[i]<='Z') {
if(helper)
Printf(new_name,"%c",'-');
Printf(new_name,"%c",('a' + (name[i] - 'A')));
helper = false;
}
else {
helper = true;
Printf(new_name,"%c",name[i]);
}
}
return new_name;
}
extern "C" Language *swig_cffi(void) {
return new CFFI();
}