Patch 1565413 (bitfield support)

Patch 1562280 (vararg support)
Patch 1561115 (C expression to Lisp) + enhanced support for most operators.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@9381 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Surendra Singhi 2006-09-30 18:57:32 +00:00
commit 5f2930a9b3

View file

@ -37,7 +37,7 @@ public:
virtual int enumDeclaration(Node *n); virtual int enumDeclaration(Node *n);
virtual int typedefHandler(Node *n); virtual int typedefHandler(Node *n);
//c++ specific code //c++ specific code
virtual int constructorHandler(Node *n); virtual int constructorHandler(Node *n);
virtual int destructorHandler(Node *n); virtual int destructorHandler(Node *n);
virtual int memberfunctionHandler(Node *n); virtual int memberfunctionHandler(Node *n);
@ -55,8 +55,10 @@ private:
void emit_inline(Node *n,String *name); void emit_inline(Node *n,String *name);
String* lispy_name(char *name); String* lispy_name(char *name);
String* lispify_name(Node* n,String *ty,const char* flag,bool kw=false); String* lispify_name(Node* n,String *ty,const char* flag,bool kw=false);
String* convert_literal(String *num_param, String *type); String* convert_literal(String *num_param, String *type, bool try_to_split = true);
String* infix_to_prefix(String *val, char split_op, const String *op, String *type);
String* strip_parens(String *string); String* strip_parens(String *string);
String* trim(String *string);
int generate_typedef_flag; int generate_typedef_flag;
bool no_swig_lisp; bool no_swig_lisp;
}; };
@ -73,9 +75,9 @@ void CFFI :: main(int argc, char *argv[]) {
if (!Strcmp(argv[i], "-help")) { if (!Strcmp(argv[i], "-help")) {
Printf(stdout, "cffi Options (available with -cffi)\n"); Printf(stdout, "cffi Options (available with -cffi)\n");
Printf(stdout, Printf(stdout,
" -generate-typedef\n" " -generate-typedef\n"
"\t If this option is given then defctype will be used to generate shortcuts\n" "\tIf this option is given then defctype will be used to generate\n"
"according to the typedefs in the input.\n" "\tshortcuts according to the typedefs in the input.\n"
" -[no]cwrap\n" " -[no]cwrap\n"
"\tTurn on or turn off generation of an intermediate C file when\n" "\tTurn on or turn off generation of an intermediate C file when\n"
"\tcreating a C interface. By default this is only done for C++ code.\n" "\tcreating a C interface. By default this is only done for C++ code.\n"
@ -129,21 +131,21 @@ int CFFI :: top(Node *n) {
} }
if (CPlusPlus || CWrap) { if (CPlusPlus || CWrap) {
f_cxx=NewFile(cxx_filename, "w"); f_cxx=NewFile(cxx_filename, "w");
if (!f_cxx) { if (!f_cxx) {
Close(f_lisp); Delete(f_lisp); Close(f_lisp); Delete(f_lisp);
Printf(stderr, "Unable to open %s for writing\n", cxx_filename); Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
SWIG_exit(EXIT_FAILURE); SWIG_exit(EXIT_FAILURE);
} }
String *clos_filename=NewString(""); String *clos_filename=NewString("");
Printf(clos_filename, "%s%s-clos.lisp", SWIG_output_directory(), module); Printf(clos_filename, "%s%s-clos.lisp", SWIG_output_directory(), module);
f_clos=NewFile(clos_filename, "w"); f_clos=NewFile(clos_filename, "w");
if (!f_clos) { if (!f_clos) {
Close(f_lisp); Delete(f_lisp); Close(f_lisp); Delete(f_lisp);
Printf(stderr, "Unable to open %s for writing\n", cxx_filename); Printf(stderr, "Unable to open %s for writing\n", cxx_filename);
SWIG_exit(EXIT_FAILURE); SWIG_exit(EXIT_FAILURE);
} }
} }
else { else {
f_cxx=NewString(""); f_cxx=NewString("");
@ -282,9 +284,9 @@ void CFFI::emit_defmethod(Node*n) {
int x = Replace(method_name,"operator ","",DOH_REPLACE_FIRST); // int x = Replace(method_name,"operator ","",DOH_REPLACE_FIRST); //
if(x==1) if(x==1)
Printf(f_clos, "(shadow \"%s\")\n",method_name); Printf(f_clos, "(cl:shadow \"%s\")\n",method_name);
Printf(f_clos,"(defmethod %s ((obj %s)%s)\n (%s (ff-pointer obj)%s))\n\n", Printf(f_clos,"(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(n,lispy_name(Char(method_name)),"'method"),
lispify_name(parent,lispy_name(Char(Getattr(parent, "sym:name"))),"'class"),args_placeholder, lispify_name(parent,lispy_name(Char(Getattr(parent, "sym:name"))),"'class"),args_placeholder,
lispify_name(n, Getattr(n, "sym:name"), "'function"),args_call); lispify_name(n, Getattr(n, "sym:name"), "'function"),args_call);
@ -293,7 +295,7 @@ void CFFI::emit_defmethod(Node*n) {
void CFFI::emit_setter(Node*n) { void CFFI::emit_setter(Node*n) {
Node *p = parentNode(n); Node *p = parentNode(n);
Printf(f_clos,"(defmethod (setf %s) (arg0 (obj %s))\n (%s (ff-pointer obj) arg0))\n\n", Printf(f_clos,"(clos:defmethod (cl:setf %s) (arg0 (obj %s))\n (%s (ff-pointer obj) arg0))\n\n",
lispify_name(n, Getattr(n, "name"), "'method"), lispify_name(n, Getattr(n, "name"), "'method"),
lispify_name(p,lispy_name(Char(Getattr(p, "sym:name"))),"'class"), lispify_name(p,lispy_name(Char(Getattr(p, "sym:name"))),"'class"),
lispify_name(n, Getattr(n, "sym:name"), "'function")); lispify_name(n, Getattr(n, "sym:name"), "'function"));
@ -302,7 +304,7 @@ void CFFI::emit_setter(Node*n) {
void CFFI::emit_getter(Node*n) { void CFFI::emit_getter(Node*n) {
Node *p = parentNode(n); Node *p = parentNode(n);
Printf(f_clos,"(defmethod %s ((obj %s))\n (%s (ff-pointer obj)))\n\n", Printf(f_clos,"(clos:defmethod %s ((obj %s))\n (%s (ff-pointer obj)))\n\n",
lispify_name(n, Getattr(n, "name"), "'method"), lispify_name(n, Getattr(n, "name"), "'method"),
lispify_name(p,lispy_name(Char(Getattr(p, "sym:name"))),"'class"), lispify_name(p,lispy_name(Char(Getattr(p, "sym:name"))),"'class"),
lispify_name(n, Getattr(n, "sym:name"), "'function")); lispify_name(n, Getattr(n, "sym:name"), "'function"));
@ -333,11 +335,11 @@ int CFFI :: functionWrapper(Node *n) {
Delete(resolved); Delete(resolved);
if (!is_void_return) if (!is_void_return)
{ {
String *lresult_init = NewStringf("lresult = (%s)0", raw_return_type); String *lresult_init = NewStringf("lresult = (%s)0", raw_return_type);
Wrapper_add_localv(wrap,"lresult", raw_return_type, lresult_init, NIL); Wrapper_add_localv(wrap,"lresult", raw_return_type, lresult_init, NIL);
Delete(lresult_init); Delete(lresult_init);
} }
String *overname = 0; String *overname = 0;
if (Getattr(n,"sym:overloaded")) { if (Getattr(n,"sym:overloaded")) {
@ -455,9 +457,9 @@ int CFFI :: functionWrapper(Node *n) {
void CFFI::emit_defun(Node *n,String *name) void CFFI::emit_defun(Node *n,String *name)
{ {
// String *storage=Getattr(n,"storage"); // String *storage=Getattr(n,"storage");
// if(!storage || (Strcmp(storage,"extern") && Strcmp(storage,"externc"))) // if(!storage || (Strcmp(storage,"extern") && Strcmp(storage,"externc")))
// return SWIG_OK; // return SWIG_OK;
String *func_name=Getattr(n, "sym:name"); String *func_name=Getattr(n, "sym:name");
@ -477,13 +479,18 @@ void CFFI::emit_defun(Node *n,String *name)
for (Parm *p=pl; p; p=nextSibling(p), argnum++) { for (Parm *p=pl; p; p=nextSibling(p), argnum++) {
if (SwigType_isvarargs(Getattr(p, "type"))){
Printf(f_cl,"\n %s",NewString("&rest"));
continue;
}
String *argname=Getattr(p, "name"); String *argname=Getattr(p, "name");
ffitype = Swig_typemap_lookup_new("cin",p, "",0); ffitype = Swig_typemap_lookup_new("cin",p, "",0);
int tempargname=0; int tempargname=0;
if (!argname) { if (!argname) {
argname=NewStringf("arg%d", argnum); argname=NewStringf("arg%d", argnum);
tempargname=1; tempargname=1;
} }
@ -492,7 +499,6 @@ void CFFI::emit_defun(Node *n,String *name)
tempargname=1; tempargname=1;
} }
Printf(f_cl, "\n (%s %s)", argname, ffitype); Printf(f_cl, "\n (%s %s)", argname, ffitype);
Delete(ffitype); Delete(ffitype);
@ -560,7 +566,12 @@ int CFFI :: enumDeclaration(Node *n) {
String *lisp_name = 0; String *lisp_name = 0;
if(name && Len(name)!=0) { if(name && Len(name)!=0) {
lisp_name = lispify_name(n, name, "'enumname"); lisp_name = lispify_name(n, name, "'enumname");
Printf(f_cl,"\n(cffi:defcenum %s",lisp_name); if (GetFlag(n,"feature:bitfield")){
Printf(f_cl,"\n(cffi:defbitfield %s",lisp_name);
}
else{
Printf(f_cl,"\n(cffi:defcenum %s",lisp_name);
}
slot_name_keywords = true; slot_name_keywords = true;
//Registering the enum name to the cin and cout typemaps //Registering the enum name to the cin and cout typemaps
@ -585,7 +596,7 @@ int CFFI :: enumDeclaration(Node *n) {
String *slot_name = lispify_name(c, Getattr(c, "name"), "'enumvalue", slot_name_keywords); String *slot_name = lispify_name(c, Getattr(c, "name"), "'enumvalue", slot_name_keywords);
String *value = Getattr(c, "enumvalue"); String *value = Getattr(c, "enumvalue");
if(!value) if(!value || GetFlag(n,"feature:bitfield:ignore_values"))
Printf(f_cl,"\n\t%s",slot_name); Printf(f_cl,"\n\t%s",slot_name);
else { else {
String *type=Getattr(c, "type"); String *type=Getattr(c, "type");
@ -683,8 +694,8 @@ void CFFI :: emit_class(Node *n) {
// String *ns = listify_namespace(Getattr(n, "cffi:package")); // String *ns = listify_namespace(Getattr(n, "cffi:package"));
String *ns = NewString(""); String *ns = NewString("");
#ifdef CFFI_WRAP_DEBUG #ifdef CFFI_WRAP_DEBUG
Printf(stderr, "slot name = '%s' ns = '%s' class-of '%s' and type = '%s'\n", Printf(stderr, "slot name = '%s' ns = '%s' class-of '%s' and type = '%s'\n",
cname, ns, name, childType); cname, ns, name, childType);
#endif #endif
Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)", Printf(slotdefs, "(#.(swig-insert-id \"%s\" %s :type :slot :class \"%s\") %s)",
cname, ns, name, childType); //compose_foreign_type(childType) cname, ns, name, childType); //compose_foreign_type(childType)
@ -700,11 +711,11 @@ void CFFI :: emit_class(Node *n) {
} }
// String *ns_list = listify_namespace(Getattr(n,"cffi:namespace")); // String *ns_list = listify_namespace(Getattr(n,"cffi:namespace"));
// update_package_if_needed(n,f_clhead); // update_package_if_needed(n,f_clhead);
// Printf(f_clos, // Printf(f_clos,
// "(swig-def-foreign-class \"%s\"\n %s\n (:%s\n%s))\n\n", // "(swig-def-foreign-class \"%s\"\n %s\n (:%s\n%s))\n\n",
// name, supers, kind, slotdefs); // name, supers, kind, slotdefs);
Delete(supers); Delete(supers);
// Delete(ns_list); // Delete(ns_list);
@ -761,36 +772,36 @@ void CFFI :: emit_struct_union(Node *n, bool un=false) {
#ifdef CFFI_DEBUG #ifdef CFFI_DEBUG
Printf(stderr, "struct/union %s\n", Getattr(c, "name")); Printf(stderr, "struct/union %s\n", Getattr(c, "name"));
Printf(stderr, "struct/union %s and %s \n", Printf(stderr, "struct/union %s and %s \n",
Getattr(c,"kind"),Getattr(c,"sym:name")); Getattr(c,"kind"),Getattr(c,"sym:name"));
#endif #endif
if (Strcmp(nodeType(c), "cdecl")) { if (Strcmp(nodeType(c), "cdecl")) {
//C declaration ignore //C declaration ignore
// Printf(stderr, "Structure %s has a slot that we can't deal with.\n", // Printf(stderr, "Structure %s has a slot that we can't deal with.\n",
// name); // name);
// Printf(stderr, "nodeType: %s, name: %s, type: %s\n", // Printf(stderr, "nodeType: %s, name: %s, type: %s\n",
// nodeType(c), // nodeType(c),
// Getattr(c, "name"), // Getattr(c, "name"),
// Getattr(c, "type")); // Getattr(c, "type"));
// SWIG_exit(EXIT_FAILURE); // SWIG_exit(EXIT_FAILURE);
} }
else{ else{
SwigType *childType=NewStringf("%s%s", Getattr(c,"decl"), SwigType *childType=NewStringf("%s%s", Getattr(c,"decl"),
Getattr(c,"type")); Getattr(c,"type"));
Hash *typemap = Swig_typemap_search("cin", childType,"", 0); Hash *typemap = Swig_typemap_search("cin", childType,"", 0);
String *typespec = NewString(""); String *typespec = NewString("");
if (typemap) { if (typemap) {
typespec = NewString(Getattr(typemap, "code")); typespec = NewString(Getattr(typemap, "code"));
} }
String *slot_name = lispify_name(c, Getattr(c, "sym:name"), "'slotname"); String *slot_name = lispify_name(c, Getattr(c, "sym:name"), "'slotname");
if(Strcmp(slot_name,"t")==0 || Strcmp(slot_name,"T")==0) if(Strcmp(slot_name,"t")==0 || Strcmp(slot_name,"T")==0)
slot_name=NewStringf("t_var"); slot_name=NewStringf("t_var");
Printf(f_cl, "\n\t(%s %s)", slot_name, typespec); Printf(f_cl, "\n\t(%s %s)", slot_name, typespec);
Delete(typespec); Delete(typespec);
} }
} }
@ -819,12 +830,12 @@ void CFFI :: emit_inline(Node *n,String *name) {
Printf(f_cl, "\n(cl:declaim (cl:inline %s))\n", name); Printf(f_cl, "\n(cl:declaim (cl:inline %s))\n", name);
} }
String* CFFI :: lispify_name(Node *n,String* ty,const char* flag,bool kw) { String* CFFI ::lispify_name(Node *n, String* ty, const char* flag, bool kw) {
String* intern_func = Getattr(n, "feature:intern_function"); String* intern_func = Getattr(n, "feature:intern_function");
if (intern_func) { if (intern_func) {
if(Strcmp(intern_func,"1") == 0) if(Strcmp(intern_func,"1") == 0)
intern_func = NewStringf("swig-lispify"); intern_func = NewStringf("swig-lispify");
return NewStringf("#.(%s \"%s\" %s%s)", intern_func, ty, flag, kw? " :keyword":""); return NewStringf("#.(%s \"%s\" %s%s)", intern_func, ty, flag, kw ? " :keyword":"");
} }
else if(kw) else if(kw)
return NewStringf(":%s",ty); return NewStringf(":%s",ty);
@ -858,45 +869,147 @@ String* CFFI::strip_parens(String *string) {
return res; return res;
} }
String* CFFI::convert_literal(String *num_param, String *type) { String* CFFI::trim(String *str) {
String *num=strip_parens(num_param), *res; char *c = Char(str);
while (*c != '\0' && isspace((int)*c))
++c;
String *result = NewString(c);
Chop(result);
return result;
}
String * CFFI::infix_to_prefix(String *val, char split_op, const String *op, String *type) {
List *ored = Split(val, split_op, -1);
// some float hackery
//i don't understand it, if you do then please explain
// if ( ((split_op == '+') || (split_op == '-')) && Len(ored) == 2 &&
// (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE ||
// SwigType_type(type) == T_LONGDOUBLE) ) {
// // check that we're not splitting a float
// String *possible_result = convert_literal(val, type, false);
// if (possible_result) return possible_result;
// }
// try parsing the split results. if any part fails, kick out.
bool part_failed = false;
if (Len(ored) > 1) {
String *result = NewStringf("(%s", op);
for(Iterator i = First(ored); i.item; i = Next(i)) {
String *converted = convert_literal(i.item, type);
if(converted) {
Printf(result, " %s", converted);
Delete(converted);
} else {
part_failed = true;
break;
}
}
Printf(result, ")");
Delete(ored);
return part_failed ? 0 : result;
}
else {
Delete(ored);
}
return 0;
}
/* To be called by code generating the lisp interface
Will return a containing the literal based on type.
Will return null if there are problems.
try_to_split defaults to true (see stub above).
*/
String * CFFI::convert_literal(String *literal, String *type, bool try_to_split) {
String *num_param = Copy(literal);
String *trimmed = trim(num_param);
String *num=strip_parens(trimmed), *res=0;
Delete(trimmed);
char *s=Char(num); char *s=Char(num);
/* Make sure doubles use 'd' instead of 'e' */ // very basic parsing of infix expressions.
if (!Strcmp(type, "double")) { if(try_to_split) {
String *updated=Copy(num); if( (res = infix_to_prefix(num, '|', "cl:logior", type)) ) return res;
if (Replace(updated, "e", "d", DOH_REPLACE_ANY) > 1) { if( (res = infix_to_prefix(num, '&', "cl:logand", type)) ) return res;
Printf(stderr, "Weird!! number %s looks invalid.\n", num); if( (res = infix_to_prefix(num, '^', "cl:logxor", type)) ) return res;
SWIG_exit(EXIT_FAILURE); if( (res = infix_to_prefix(num, '*', "cl:*", type)) ) return res;
} if( (res = infix_to_prefix(num, '/', "cl:/", type)) ) return res;
Delete(num); if( (res = infix_to_prefix(num, '+', "cl:+", type)) ) return res;
return updated; if( (res = infix_to_prefix(num, '-', "cl:-", type)) ) return res;
} }
if (SwigType_type(type) == T_CHAR) { if (SwigType_type(type) == T_FLOAT || SwigType_type(type) == T_DOUBLE || SwigType_type(type) == T_LONGDOUBLE) {
// Use CL syntax for float literals
// careful. may be a float identifier or float constant.
char *num_start = Char(num);
char *num_end = num_start + strlen(num_start) - 1;
bool is_literal = isdigit(*num_start) || (*num_start == '.') || (*num_start == '+') || (*num_start == '-');
String *lisp_exp = 0;
if(is_literal) {
if (*num_end == 'f' || *num_end == 'F') {
lisp_exp = NewString("f");
} else {
lisp_exp = NewString("d");
}
if (*num_end == 'l' || *num_end == 'L' || *num_end == 'f' || *num_end == 'F') {
*num_end = '\0';
num_end--;
}
int exponents = Replaceall(num, "e", lisp_exp) + Replaceall(num, "E", lisp_exp);
if (!exponents)
Printf(num, "%s0", lisp_exp);
if (exponents > 1 || (exponents + Replaceall(num,".",".") == 0)) {
Delete(num);
num = 0;
}
}
return num;
}
else if (SwigType_type(type) == T_CHAR) {
/* Use CL syntax for character literals */ /* Use CL syntax for character literals */
return NewStringf("#\\%s", num_param); Delete(num);
// Printf(stderr, "%s %c %d", s, s[2], s);
return NewStringf("#\\%c", s[2]);
} }
else if (SwigType_type(type) == T_STRING) { else if (SwigType_type(type) == T_STRING) {
/* Use CL syntax for string literals */ /* Use CL syntax for string literals */
Delete(num);
return NewStringf("\"%s\"", num_param); return NewStringf("\"%s\"", num_param);
} }
else if (SwigType_type(type) == T_INT){
Replaceall(num, "u", "") + Replaceall(num, "U", "");
Replaceall(num, "l", "") + Replaceall(num, "L", "");
if (Len(num) < 2 || s[0] != '0') { int i,j;
return num; if (sscanf (s,"%d >> %d",&i,&j) == 2){
Delete(num);
return NewStringf("(cl:ash %d -%d)",i,j);
}
else if (sscanf(s,"%d << %d",&i,&j) == 2){
Delete(num);
return NewStringf("(cl:ash %d %d)",i,j);
}
} }
/* octal or hex */ if (Len(num) >= 2 && s[0] == '0') { /* octal or hex */
Delete(num);
res=NewStringf("#%c%s", if(s[1] == 'x')
s[1] == 'x' ? 'x' : 'o', return NewStringf("#x%s", s+2);
s+2); else
Delete(num); return NewStringf("#o%s", s+1);
}
return res; return num;
} }
//less flexible as it does the conversion in C, the lispify name does the conversion in lisp //less flexible as it does the conversion in C, the lispify name does the conversion in lisp
String* CFFI::lispy_name(char *name) { String* CFFI::lispy_name(char *name) {
bool helper=false; bool helper=false;