Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.Parser.XML2 1.50
Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
wx
Viewing contents of wx-0.5/bindgen.pike

/*
   wxPike - (c) 2005 Julio César Gázquez
 
   bindgen.pike:
   C++ bindings generator
 
*/

class BindingType
{
	string ctype;
	string piketype;
	
	string parameterMacro;
}

class VoidType
{
	inherit BindingType;
	static void create()
	{
		parameterMacro="tVoid";
		ctype="void";
		piketype="void";
	}
	string resultReturn(string scall, string modifier)
	{
		return "\t"+scall+";\n";
	}
	string overrideReturn(string modifier)
	{
		return "\tpop_stack();\n";
	}
}

class IntType
{
	inherit BindingType;
	
	static void create()
	{
		parameterMacro="tInt";
		ctype="int";
		piketype="int";
	}
	string parameterRetrieving(string funcname, int n, string defaultvalue, string modifier)
	{
		string s="\n";
		s+="\tINT_TYPE par"+(string)n+";\n";
		if (defaultvalue) {
			s+="\tif (args<"+(string)(n+1)+")\n";
			s+="\t\tpar"+(string)n+"="+defaultvalue+";\n";
			s+="\telse {\n";
		}
		s+="\tif (Pike_sp["+(string)n+"-args].type!=T_INT)\n";
		s+="\t\tSIMPLE_BAD_ARG_ERROR(\""+funcname+"\","+(string)n+",\"integer\");\n";
		// Guardo el valor
		s+="\tpar"+(string)n;
		s+="=Pike_sp["+(string)n+"-args].u.integer;\n";
		if (defaultvalue)
			s+="\t}\n";
		return s;
	}

	string resultReturn(string scall, string modifier)
	{
		return "\tpush_int("+scall+");\n";
	}
	string overrideReturn(string modifier)
	{
		return "\tint r=Pike_sp[-1].u.integer;\n"
			+"\tpop_stack();\n"	
			+"\treturn r;\n";
	}	
}

class LongType {

	inherit IntType;
	
	static void create()
	{
		parameterMacro="tInt";
		ctype="long";
		piketype="int";
	}
	string overrideReturn(string modifier)
	{
		return "\tlong r=Pike_sp[-1].u.integer;\n"
			+"\tpop_stack();\n"	
			+"\treturn r;\n";
	}	
}
// Should be mixed
class BoolType
{
	inherit BindingType;
	
	static void create()
	{
		parameterMacro="tInt";
		ctype="bool";
		piketype="int";
	}
	string parameterRetrieving(string funcname, int n, string defaultvalue, string modifier)
	{
		string s="\n";
		
		s+="\tbool par"+(string)n+";\n";
		if (defaultvalue) {
			s+="\tif (args<"+(string)(n+1)+")\n";
			s+="\t\tpar"+(string)n+"="+defaultvalue+";\n";
			s+="\telse {\n";
		}

		s+="\tif (Pike_sp["+(string)n+"-args].type!=T_INT)\n";
		s+="\t\tSIMPLE_BAD_ARG_ERROR(\""+funcname+"\","+(string)n+",\"integer\");\n";
		// Guardo el valor
		s+="\tpar"+(string)n;
		s+="=Pike_sp["+(string)n+"-args].u.integer;\n";
		if (defaultvalue)
			s+="\t}\n";		
		return s;
	}
	
	string resultReturn(string scall, string modifier)
	{
		return "\tpush_int("+scall+" ? 1 : 0);\n";
	}
	string overrideReturn(string modifier)
	{
		return "\tbool r=Pike_sp[-1].u.integer;\n"
			+"\tpop_stack();\n"	
			+"\treturn r;\n";
	}		
}
	
class FloatType
{
	inherit BindingType;
	static void create()
	{
		parameterMacro="tFloat";
		ctype="float";
		piketype="float";		
	}
	string parameterRetrieving(string funcname, int n, string defaultvalue, string modifier)
	{
		string s="\n";
		
		s+="\tFLOAT_TYPE par"+(string)n+";\n";
		if (defaultvalue) {
			s+="\tif (args<"+(string)(n+1)+")\n";
			s+="\t\tpar"+(string)n+"="+defaultvalue+";\n";
			s+="\telse {\n";
		} 
		s+="\tif (Pike_sp["+(string)n+"-args].type!=T_FLOAT)\n";
		s+="\t\tSIMPLE_BAD_ARG_ERROR(\""+funcname+"\","+(string)n+",\"float\");\n";
		// Guardo el valor
		s+="\tpar"+(string)n;
		s+="=Pike_sp["+(string)n+"-args].u.float_number;\n";
		if (defaultvalue)
			s+="\t}\n";
		return s;
	}	
	string resultReturn(string scall, string modifier)
	{
		return "\tpush_float("+scall+");\n";
	}
	string overrideReturn(string modifier)
	{
		return "\tfloat r=Pike_sp[-1].u.float_number;\n"
			+"\tpop_stack();\n"	
			+"\treturn r;\n";
	}	
}


class StringType
{
	inherit BindingType;
	static void create()
	{
		parameterMacro="tString"; 
		ctype="wxString";
		piketype="string";
	}

	string parameterRetrieving(string funcname, int n, string defaultvalue, string modifier)
	{
		string s="\n";
		
		s+="\twxString par"+(string)n+";\n";
		if (defaultvalue) {
			s+="\tif (args<"+(string)(n+1)+")\n";
			s+="\t\tpar"+(string)n+"="+defaultvalue+";\n";
			s+="\telse {\n";
		} 
		s+="\tif (Pike_sp["+(string)n+"-args].type!=T_STRING)\n";
		s+="\t\tSIMPLE_BAD_ARG_ERROR(\""+funcname+"\","+(string)n+",\"string\");\n";
		s+="\tstruct pike_string *pstr"+(string)n;
		s+="=(Pike_sp["+(string)n+"-args].u.string);\n";
		s+="\tpar"+(string)n;
		s+="=pstr"+(string)n+"->str;\n";
		if (defaultvalue)
			s+="\t}\n";
		return s;
	} 
	// Unicode? 
	string resultReturn(string scall, string modifier)
	{
		string s="";
		s+="\tconst char *rval=(const char *)"+scall+".c_str();\n";
		s+="\tstruct pike_string *str=make_shared_string(rval);\n";
		s+="\tpush_string(str);\n";
		return s;
	}
	string overrideReturn(string modifier)
	{
		return "\twxString r=Pike_sp[-1].u.string->str;\n"
			+"\tpop_stack();\n"	
			+"\treturn r;\n";
	}	
}


// Este es el único tipo que ha de tener múltiples instancias
// una por cada clase, a fin de poder usarlas como tipo
class ObjectType
{
	inherit BindingType;
	string className;
	static void create(string _className)
	{
		// To allow null references
		parameterMacro="tOr(tObj,tZero)";
		className=_className;
		ctype=_className;
		piketype=_className;
	}
	string parameterRetrieving(string funcname, int n, string defaultvalue, string modifier, string directive)
	{
		string s="\n";
		// Control de tipo
		// No sé si estará bien chequear contra T_OBJECT
		// Guardo el valor
		if (modifier=="*") {
			s+="\t"+className+"* par"+(string)n+";\n";
			if (defaultvalue) {
				s+="\tif (args<"+(string)(n+1)+")\n";
				s+="\t\tpar"+(string)n+"="+defaultvalue+";\n";
				s+="\telse {\n";
			}
			s+="\n\tif (Pike_sp["+(string)n+"-args].type==T_OBJECT) {\n";
			s+="\t\tpar"+(string)n;
			s+="=static_cast<"+className+"*>(  STORAGE(Pike_sp["+(string)n+ "-args].u.object,"+className+")->cppobject);\n";			
			s+="\t} else\n";
			s+="\t\tpar"+(string)n+"=NULL;\n";
			if (defaultvalue)
				s+="\t}\n";
		} else {
			s+="\tif ( Pike_sp["+(string)n+"-args].type!=T_OBJECT";
			if (defaultvalue)
				s+=" && !(args<"+(string)(n+1)+")";
			s+=")\n";
			s+="\t\tSIMPLE_BAD_ARG_ERROR(\""+funcname+"\","+(string)n+",\"object\");\n";
			s+="\t"+className+"& par"+(string)n;
			if (defaultvalue) {
				s+="= (args<"+(string)(n+1)+")\n\t\t? const_cast<"+className+"&>("+defaultvalue+")\n\t\t:  *("+className+"*) STORAGE(Pike_sp["+(string)n+"-args].u.object,"+className+")->cppobject;\n";			
			} else
				s+="=*static_cast<"+className+"*>(STORAGE(Pike_sp["+(string)n+"-args].u.object,"+className+")->cppobject);\n";
		}
		if (directive=="addref") {
			s+="\tif (args>="+(string)(n+1)+")\n";
			s+="\t\tadd_ref(Pike_sp["+(string)n+"-args].u.object);\n";
		} else if (directive=="subref") {
			s+="\tif (args>="+(string)(n+1)+")\n";
			s+="\tfree_object(Pike_sp["+(string)n+"-args.u.object]);\n";
		}
		return s;
	}	

	string resultReturn(string scall, string modifier)
	{
		string s="";
		s+="\tstruct object *o=NULL;\n";

		BindingClass classObj=classIndex[className];
		int virtualClass = classObj ? classObj->virtual : 0;
		
		if (virtualClass && modifier=="*") {
			s+="\t"+className+"__pv* ptr=dynamic_cast<"+className+"__pv*>("+scall+");\n";
			s+="\tif (ptr) {\n";
			s+="\t\to=ptr->pike_object;\n";
			s+="\t\tpush_object( o );\n";
			s+="\t } else\n";
			s+="\t\tpush_undefined();\n";
		} else {
			s+="\to = low_clone( "+className+"_program );\n";
			s+="\tcall_c_initializers( o );\n";
			s+="\tSTORAGE(o,"+className+")->cppobject=";
			
			if (modifier=="*") {
				s+=scall+";\n";
				// object doesn't belong to the wrapper
				// hence it can't delete it
				s+="\tSTORAGE(o,"+className+")->foreign=true;\n";
			} else if (modifier=="&"){
				s+="&("+scall+");\n";
				s+="\tSTORAGE(o,"+className+")->foreign=true;\n";
			} else {// If returns by value, we copy it from the stack
				// and the object 
				s+="new "+className+"("+scall+");\n";
				s+="\tSTORAGE(o,"+className+")->foreign=false;\n";
			}
			s+="\tpush_object( o );\n";
		}
		
		return s;
	}
	string overrideReturn(string modifier)
	{
		string s="\t"+className+"* r=static_cast<"+className+"*>(STORAGE(Pike_sp[-1].u.object,"+className+")->cppobject);\n"
			+"\tpop_stack();\n";
			
		if (modifier=="*")
			s+="\treturn r;\n";
		else
			s+="\treturn *r;\n";
			
		return s;
	}		
}

/* Those currently are just for extern definitions */
class ProgramType
{
	inherit BindingType;

	static void create()
	{
		parameterMacro="tProgram(tObj)"; 
		ctype="struct program*";
		piketype="program";
	}
}

class FunctionType
{
	inherit BindingType;

	static void create()
	{
		parameterMacro="tFuncV(tNone,tMix,tVoid)"; 
		ctype="struct callable*";
		piketype="function";
	}
}

class ArrayIntType
{
	inherit BindingType;

	static void create()
	{
		parameterMacro="tOr(tArr(tInt),tZero)"; 
		ctype="int*";
		piketype="array(int)";
	}
}

class ArrayPCharType
{
	inherit BindingType;

	static void create()
	{
		parameterMacro="tOr(tArr(tString),tZero)"; 
		ctype="char**";
		piketype="array(string)";
	}
}

class ArraywxStringType
{
	inherit BindingType;

	static void create()
	{
		parameterMacro="tOr(tArr(tString),tZero)"; 
		ctype="wxString[]";
		piketype="array(string)";
	}
}


BindingType voidType=VoidType();

mapping(string:BindingType) bindingTypes = ([
	"void":VoidType(),
	"bool":BoolType(),
	"char":IntType(),
	"int":IntType(),
	"long":LongType(),	
	"float":FloatType(),
	"string":StringType(),
	"object":ObjectType("object"),
	"program":ProgramType(),
	"function":FunctionType(),
	"wxString":StringType(),
	"int[]":ArrayIntType(),
	"wxString[]":ArraywxStringType(),
	"*char[]":ArrayPCharType()
	]);

class BindingConstant
{
	string name;
	string value;
	
	void create(string _name, string _value)
	{
		name=_name;
		value=_value;
	}

}
class BindingIntConstant
{
	inherit BindingConstant;
	string pikeDeclaration()
	{
		string pikename=name;
		// Prefix stripping
		if (prefix)
			if (pikename[0..sizeof(prefix)-1]==prefix)
				pikename=pikename[sizeof(prefix)..];
		return "\tADD_INT_CONSTANT(\""+pikename+"\","+value+",0);\n";
	}
	
}

class BindingFloatConstant
{
	inherit BindingConstant;
	string pikeDeclaration()
	{
		string pikename=name;
		// Prefix stripping
		if (prefix)
			if (pikename[0..sizeof(prefix)-1]==prefix)
				pikename=pikename[sizeof(prefix)..];
		return "\tADD_FLOAT_CONSTANT(\""+pikename+"\","+value+",0);\n";
	}
	
}

class BindingStringConstant
{
	inherit BindingConstant;
	string pikeDeclaration()
	{
		string pikename=name;
		// Prefix stripping
		if (prefix)
			if (pikename[0..sizeof(prefix)-1]==prefix)
				pikename=pikename[sizeof(prefix)..];
		return "\tadd_string_constant(\""+pikename+"\","+value+",0);\n";
	}
	
}

class BindingObjectConstant
{
	inherit BindingConstant;
	string className;
	string name;
	string value;
	
	void create(string _className, string _name, string _value)
	{
		className=_className;
		name=_name;
		value=_value;
	}

	string pikeDeclaration()
	{
		string pikename=name;
		string s;
		// Prefix stripping
		if (prefix)
			if (pikename[0..sizeof(prefix)-1]==prefix)
				pikename=pikename[sizeof(prefix)..];
		s="\t{\n";
		s+="\t\tstruct object *o = low_clone( "+className+"_program );\n";
		s+="\t\tcall_c_initializers( o );\n";
		s+="\t\tSTORAGE(o,"+className+")->cppobject=const_cast<"+className+"*>(&"+name+");\n";
		s+="\t\tSTORAGE(o,"+className+")->foreign=true;\n";
		s+="\t\tadd_object_constant(\""+pikename+"\",o,0);\n";
		s+="\t}\n";
		return s;
	}
	
}


class Parameter
{
	BindingType type;
	string modifier;
	string defaultvalue;
	string directive; // addref/subref inc/dec object reference counter
}

class BindingFunction
{
	string name;		// Method Name
	string bfname;		// Binding Function name
	string cppname;		// C++ Method name (Different than Pike's 
				// when implementing a polymorphic C++ 
				// method)
	BindingType returnType;
	string returnMod; // '*' pointer, '&' reference
	array(Parameter) parameters;
	int minParam;
	multiset(string) modifiers;
	
		   // (Coded by hand)
		
	static void create(string _name, string _cppname, BindingType _rt, string _rm, array(BindingType) _params, multiset(string) _modifiers)
	{
		name=_name;
		cppname=_cppname;
		returnType=_rt;
		returnMod=_rm;
		parameters=_params;
		modifiers=_modifiers;
		bfname="f_"+name;
		minParam=sizeof(Array.filter(parameters, lambda(Parameter x) { return !(x->defaultvalue); } ));
	}
	
	string cppDeclaration()
	{
		return "void "+bfname+"(INT32 args)";
	}
	
	string parameterManagementDefinition()
	{
		string s="";
		// Param count check;
		if (minParam>0) {
			s+="\tif (args<"+(string)minParam+")\n";
			s+="\t\tSIMPLE_WRONG_NUM_ARGS_ERROR(\""+name+"\",1);\n";
		}
		// Param type check 
		int i=0;
		BindingType p;
		foreach(parameters, p) {
			s+=p->type->parameterRetrieving(name, i, p->defaultvalue, p->modifier,p->directive);
			i++;
		}
		return s;
	}
	
	string cppCallingDefinition()
	{
		// C++ method call
		string s=cppname+"(";
		int i=0;
		BindingType p;
		foreach(parameters, p) {
			// method call parameters
			if (i>0) s+=", ";
			s+="par"+(int)i;
			i++;
		}
		s+=")";
		return s;
	}
	
	string definition()
	{
		if (modifiers["extern"]) return "";
		// function head;
		string s="void "+bfname+"(INT32 args)\n";
		s+="{\n";
		
		s+=parameterManagementDefinition();
		
		string scall=cppCallingDefinition();
		
		// Discard parameters
		s+="\tpop_n_elems(args);\n";
				
		s+=returnType->resultReturn(scall, returnMod);
		s+="}\n"; 
		return s;
	}
	string pikeDeclaration()
	{
		string s="";
		string pikename=name;
		// Prefix stripping
		if (prefix)
			if (pikename[0..sizeof(prefix)-1]==prefix)
				pikename=pikename[sizeof(prefix)..];		
		s="ADD_FUNCTION(\""+pikename+"\", "+bfname+",tFunc(";
		if (sizeof(parameters)==0)
			s+="tNone";
		else {
			BindingType p;
			foreach(parameters, p) {
				if (p->defaultvalue!=0)
					s+=sprintf(" tOr(tVoid,%s)", p->type->parameterMacro);
				else
					s+=" "+p->type->parameterMacro;
			}
		}
		s+=","+returnType->parameterMacro;
		s+="), 0);";
		return s;	
	}

}

class BindingMethod
{
	inherit BindingFunction;
	string classname;	// Class Name	
		
	static void create(string _classname, string _name, string _cppname, BindingType _rt, string _rm, array(BindingType) _params, multiset(string) _modifiers)
	{
		BindingFunction::create(_name, _cppname, _rt, _rm, _params, _modifiers);
		classname=_classname;	
		bfname="f_"+classname+"__"+name;
	}
	// Declaration for binding's virtual methods override
	string bindingOverrideDeclaration()
	{
		string s="\t"+returnType->ctype+returnMod+" "+cppname+"(";
		s+=");\n";
		return s;
	}
	// Definition for binding's virtual methods override
	string bindingOverrideDefinition()
	{
		string s=returnType->ctype+returnMod+" "+classname+"__pv::"+cppname+"(";
		// Faltan los parametros
		s+=")\n";
		s+="{\n";
		s+="\tpush_method(\""+name+"\");\n";
		// Aca van los push de los parametros
		// el parametro de f_call_function es 1 por el
		// parametro funcion
		// + la cant de parametros que corresponda
		s+="\tf_call_function(1);\n";
		s+=returnType->overrideReturn(returnMod);
		s+="}\n";
		return s;
	}
	// C++ method Calling
	string cppCallingDefinition()
	{
		// C++ method call
		string s;
		if (modifiers["virtual"])
//			s="(("+classname+"*)(THIS->cppobject))->"c+name+"(";
			s="static_cast<"+classname+"*>(THIS->cppobject)->"+classname+"::"+cppname+"(";
		else
			s="static_cast<"+classname+"*>(THIS->cppobject)->"+cppname+"(";
		int i=0;
		BindingType p;
		foreach(parameters, p) {
			// method call parameters
			if (i>0) s+=", ";
			s+="par"+(int)i;
			i++;
		}
		s+=")";
		return s;
	}
	string definition()
	{
		if (modifiers["extern"]) return "";
		// function head;
		string s="void "+bfname+"(INT32 args)\n";
		s+="{\n";
		
		s+=parameterManagementDefinition();
		
		string scall=cppCallingDefinition();
		
		// Discard parameters
		s+="\tpop_n_elems(args);\n";
				
		s+=returnType->resultReturn(scall, returnMod);
		if (modifiers["addrefthis"])
			s+="\tadd_ref(Pike_fp->current_object);\n";
		else if (modifiers["subrefthis"])
			s+="\tfree_object(Pike_fp->current_object);\n";

		s+="}\n";
		return s;
	}
	
	string pikeDeclaration()
	{
		string s="";
		
		s="ADD_FUNCTION(\""+name+"\", "+bfname+",tFunc(";
		if (sizeof(parameters)==0)
			s+="tNone";
		else {
			BindingType p;
			foreach(parameters, p) {
				if (p->defaultvalue!=0)
					s+=sprintf(" tOr(tVoid,%s)", p->type->parameterMacro);
				else
					s+=" "+p->type->parameterMacro;
			}
		}
		s+=","+returnType->parameterMacro;
		s+="), 0);";
		return s;	
	}
	
}

class BindingCreate
{
	inherit BindingMethod;
	string pl;
	
	static void create(string _classname, array(BindingType) _params, multiset(string) _modifiers)
	{
		BindingMethod::create(_classname, "create", 0, voidType, 0, _params, _modifiers );
	}
	string cppDeclaration()
	{
		return "void f_"+classname+"__create(INT32 args)";
	}
	string definition()
	{
		if (modifiers["extern"]) return "";
		BindingType p;
		int i;
		
		// function head;
		string s="void f_"+classname+"__create(INT32 args)\n";
		s+="{\n";
		// Param count check;
		if (minParam>0) {
			s+="\tif (args<"+(string)minParam+")\n";
			s+="\t\tSIMPLE_WRONG_NUM_ARGS_ERROR(\""+name+"\",1);\n";	
		}
		// Param type check 
		i=0;
		foreach(parameters, p) {
			s+=p->type->parameterRetrieving(name, i ,p->defaultvalue, p->modifier,p->directive);
			i++;
		}
		// C++ method call
		string scall;
		if (classIndex[classname]->virtual)
			scall="THIS->cppobject = new "+classname+"__pv(";
		else
			scall="THIS->cppobject = new "+classname+"("; // Constructor
		
		i=0;
		foreach(parameters, p) {
			// method call parameters
			if (i>0) scall+=", ";
			scall+="par"+(int)i;
			i++;
		}
		scall+=")";	

		// Discard parameters
		s+="\tpop_n_elems(args);\n";
				
		// create functions are void, then there are no push returns
		s+="\t"+scall+";\n";
		if (modifiers["addrefthis"])
			s+="\tadd_ref(Pike_fp->current_object);\n";
		else if (classIndex[classname]->virtual)
		if (modifiers["nodestroywrapped"])
			s+="\tTHIS->foreign=true;\n";		
		else
			s+="\tTHIS->foreign=false;\n";
		if (classIndex[classname]->virtual)
		s+="\tstatic_cast<"+classname+"__pv*>(THIS->cppobject)->pike_object=Pike_fp->current_object;\n";
		s+="}\n";
		return s;
	}
	string parameterList()
	{
		if (!pl) {
			pl="";
			BindingType p;
			int i=0;
			foreach(parameters,p) {
				if (i!=0) pl+=", ";
				if (p->modifier)
					pl+=sprintf("%s%s par%d", p->type->ctype,p->modifier,i);
				else
					pl+=sprintf("%s par%d", p->type->ctype,i);
				i++;
			}
		}
		return pl;
	}
	string bindingOverrideDeclaration()
	{
		string s="\t"+classname+"__pv(";
		s+=parameterList();
		s+=");\n";
		return s;
	}
	string bindingOverrideDefinition() 
	{
		string s=classname+"__pv::"+classname+"__pv(";
		string pl=parameterList();
		s+=pl;
		s+=")\n";
		s+="\t: "+classname+"(";
		
		BindingType p;
		int i=0;
		foreach(parameters,p) {
			if (i!=0) s+=", ";
			s+="par"+(string)i;
				i++;
		}
		s+=")\n";
		s+="{\n";
		s+="}\n";
		return s;
	}

}
class BindingClass
{
	string name;
	string storagename;
	string include;
	BindingClass parent;
	array(BindingMethod) functions;

	int virtual; // The class have virtual methods?
	int abstract; // The class is abstract
	
	static void create(string _name, BindingClass|void _parent)
	{
		name=_name;
		parent=_parent;
		functions=({ });
	}
	void addFunction(BindingMethod f)
	{
		functions += ({ f });
	}	
	string cppDeclarations()
	{
		BindingMethod f;
		string s="";
		int hasConstructor=0;
		
		foreach(functions, f) 
			if (f->name=="create") hasConstructor=1;
		if (!hasConstructor && !abstract) {
			functions += ({ BindingCreate(name, ({ }), (< >) ) });
		} 
		foreach(functions, f) {
			s+=f->cppDeclaration()+";\n";
		}
		s+="static void "+name+"_exit_callback( struct object *o );\n";
		return s;
	}
	
	string storageDeclaration()
	{
		string s="";
		BindingMethod f;
		storagename=name;

		// Classes with virtual functions require the definition
		// of a subclass in order to bind those functions with
		// its possible Pike reimplementations.
		if (virtual) {
			storagename+="__pv";
			s+="class "+storagename+" : public "+name+"\n";
			s+="{\n";
			s+="\tpublic:\n";
			s+="\tobject* pike_object;\n";			
			foreach(functions, f) {
				if (f->modifiers["virtual"] || f->name=="create") {
					// Declarar overrides aqui
					s+=f->bindingOverrideDeclaration();
				}
			}
			s+="};\n";
				
		}

		return s;
	}
	
	string bindingOverrideDefinitions()
	{
		string s="";
		if (virtual) {		
			BindingMethod f;
			foreach(functions, f) {
				if (f->modifiers["virtual"] || f->name=="create") {
					// Declarar overrides aqui
					s+=f->bindingOverrideDefinition();
				}
			}
		}
		return s;
	}
	
	string functionsImplementation()
	{
		BindingMethod f;
		string s="";
			
		// method definitions
		foreach(functions, f) {
			s+=f->definition()+"\n\n";
		}
		// Delete C++ object along Pike object is necessary
		// Note: Using THIS seems ok (checked in std modules)
		s+="static void "+name+"_exit_callback( struct object *o )\n";
		s+="{\n";
		s+="\tif (o->prog == "+name+"_program)\n";
		s+="\tif (!THIS->foreign) {\n";
		s+="\t\tdelete static_cast<"+name+"*>(THIS->cppobject);\n";
		s+="\t\tTHIS->foreign=TRUE; // Inherited callbacks must not try to delete it again!\n";
		s+="\t}\n";
		s+="}\n\n";
		return s;
	}

	string pikeDeclarations()
	{
		BindingMethod f;
		
		string s="\tstart_new_program();\n";

		if (parent) {
			s+="\tlow_inherit("+parent->name+"_program, 0,0,0,0,0);\n";
		} else {
			s+="\tADD_STORAGE(wrapper_storage);\n";
		}
  		s+="\tset_exit_callback( "+name+"_exit_callback );\n";

		foreach(functions, f) {
			s+="\t"+f->pikeDeclaration()+"\n";
		}
//		s+="\t"+name+"_program=end_class(\""+name+"\", 0);\n";
		string pikename=name;
		// Prefix stripping
		if (prefix)
			if (pikename[0..sizeof(prefix)-1]==prefix)
				pikename=pikename[sizeof(prefix)..];

		s+="\tadd_program_constant(\""+pikename+"\", ("+name+"_program=end_program()), 0);\n";
		return s;
	}	
}

/*******************************************************************
  Main class here
*******************************************************************/

array(string) includes = ({ });

array(BindingConstant) bindingConstants = ({ });
array(BindingFunction) bindingFunctions = ({ });
array(BindingClass) bindingClasses = ({ });
mapping(string:BindingClass) classIndex = ([ ]);

string prefix;
int verbose;

void parse_const(array(string) words)
{
	// A constant with no value takes the C++
	// macro/const value
	string value=sizeof(words)>3 ? words[3] : words[2];
	BindingConstant c;
	switch (words[1]) {
	case "int":
		c=BindingIntConstant(words[2],value);
		break;
	case "float":
		c=BindingFloatConstant(words[2],value);
		break;
	case "char*":
		c=BindingStringConstant(words[2],value);
		break;
	case "string":
		 c=BindingStringConstant(words[2],value+".c_str");
		break;
	default:
		if (classIndex[words[1]])
			c=BindingObjectConstant(words[1],words[2],value);
		else
			throw("Error: Class not defined\n");	
	}
	bindingConstants += ({ c });
}

BindingClass parse_class(array(string) words, int abstract)
{		
	BindingClass c,p=0;
				
	if (verbose)
		write("Parsing class "+words[1]+"\n");
	if (c=classIndex[words[1]]) {
		write("Notice: class "+words[1]+" already defined\n");
		return c;
	}
	if (sizeof(words)>2) {
		p=classIndex[words[2]];
		if (!p) {
			throw("Error: parent class not defined\n");
		}
	}
	c=BindingClass(words[1],p);
	c->abstract=abstract;
	bindingClasses += ({ c });
	classIndex[words[1]]=c;
	// classes are types
	bindingTypes += ([ words[1] : ObjectType(words[1]) ]);
	return c;
}

void parse_typedef(array(string) words)
{
	if (!bindingTypes[words[1]]) {
		BindingType t=bindingTypes[words[2]];
		if (t) 
			bindingTypes[words[1]]=t;
		else {				
			throw("Error: type not defined\n");
		}
	} else 
		write("Warning: type already defined\n");
}

array(Parameter) parse_parameters(string paramstr)
{
	if (paramstr=="") {
		if (verbose) write("\n");
		return ({ });
	}
	array(string) pstrings=paramstr / ",";
	string p;
	array(Parameter) params = ({ });
	string head,tail;
	
	foreach (pstrings, p) {
		Parameter param=Parameter();
		
		p=String.trim_all_whites(p);
		head="";
		tail="";
		if (sscanf(p,"%s %s",head,tail)>=2) {
			param->directive=head;
		} else
			tail= head==""? p : head;
			
		tail=String.trim_all_whites(tail);
		if (sscanf(tail,"%s=%s",head,tail)>=2) {
			param->defaultvalue=String.trim_all_whites(tail);
		} else
			head=tail;

		string pm=" "; pm[0]=head[-1];
		if (pm=="*" || pm=="&") {
			param->modifier=pm;
			head=head[0..sizeof(head)-2];
		}
		param->type=bindingTypes[head];
		if (!param->type) {
			throw(head+"\nerror: type not defined\n");
		}
		
		params += ({ param });
	}
	if (verbose) write((string)sizeof(params)+" parameters\n");
	return params;
}

void parse_function(array(string) words, string paramstr, BindingClass c)
{
	multiset(string) modifiers = (< >);
	
	while ( (< "extern", "virtual", "sideeffect", "extdep",
			"addrefthis","subrefthis","destroywrapped",
			"nodestroywrapped" >)[words[0]] ) {
		modifiers[words[0]]=1;
		words=words[1..];
	}
	
	int efun = (words[0]=="function");

	if (efun)
		words=words[1..];

	BindingType rt;
	string rm=" ";
	string fname, cppname;
	
	if (words[0]=="create") {// constructor=>create
		if (verbose)
			write("Parsing constructor "+words[0]+"...");
	
		rt=bindingTypes["void"];
		fname="create";
		words=words[1..];
	} else {
		rm[0]=words[0][-1]; // last char;
		if (rm!="*" && rm!="&")
			rm="";
		else 
			words[0]=words[0][0..sizeof(words[0])-2];
			
		rt=bindingTypes[words[0]];

		if (verbose)
			write("Parsing "+(efun ? "function " : "method ")+words[1]+"...");
		if (efun && modifiers["virtual"])
			write("Warning: function "+words[-1]+ "can't be virtual\n");

		array names=words[1] / "#";
		if (sizeof(names)==1)
			fname=cppname=names[0];
		else {
			cppname=names[0];
			fname=names[1];
		}
		
		if (!rt) {
			throw("error: type not defined\n");
		}
		words=words[2..];
	}

	array(BindingType) params = parse_parameters(paramstr);

	BindingFunction f;
	if (efun) {
		f=BindingFunction(fname, cppname, rt, rm,
			params, modifiers);
		bindingFunctions += ({ f });
	} else {
		if (fname=="create")
			f=BindingCreate(c->name, params, modifiers);
		else
			f=BindingMethod(c->name,fname, cppname,
				rt, rm, params, modifiers);
		c->virtual |= modifiers["virtual"]; // ored between all the funcs
		c->addFunction(f);
	}

}
void parse_input(string filename)
{
	Stdio.FILE file=Stdio.FILE(filename);
	string s, wordstr, paramstr;
	BindingClass c;
	int i;
	while (s=file->gets())
	{
		s=String.trim_all_whites(s);

		i++;
		if (sizeof(s)==0) continue;
		if (s[0..1]=="//") continue;
		
		wordstr="";
		paramstr="";

		if (sscanf(s,"%s(%s)",wordstr,paramstr)==0) {
			wordstr=s;
		}
		wordstr=String.trim_all_whites(wordstr);
		
		array(string) words = wordstr / " ";

		mixed error=catch {
			if (words[0]=="#include") 
				includes += ({ words[1] });
			else if (words[0]=="strip_prefix") 
				prefix=words[1];
			else if (words[0]=="const") 
				parse_const(words);
			else if (words[0]=="class") {
				c=parse_class(words,0);
			} else if (words[0]=="abstract" && words[1]=="class") {
				words=words[1..];
				c=parse_class(words,1);
			} else if (words[0]=="typedef") {
				parse_typedef(words);
			} else {
				parse_function(words,paramstr,c);
			}
		};
		if (error) {
			write((string)i+":"+s+"\n");
			write("Error!\n");
			write(sprintf("%O\n",error));
			exit(0);
		}
	}
	file->close();	
}

string generic_headers()
{
	return  
#"/* Generated automatically */
#undef __UNICODE__

/*
    Pike headers are C
*/

extern \"C\"  {
#include \"global.h\"
#include \"stralloc.h\"
#include \"error.h\"
#include \"pike_macros.h\"
#include \"object.h\"
#include \"constants.h\"
#include \"interpret.h\"
#include \"svalue.h\"
#include \"mapping.h\"
#include \"builtin_functions.h\"
#include \"module_support.h\"
#include \"operators.h\"
}

struct wrapper_storage {
\tvoid* cppobject;
\tbool foreign;
};

#define THIS ((struct wrapper_storage *)Pike_fp->current_storage)

#define STORAGE(OBJ,CLASS) ( (struct wrapper_storage*)get_storage(OBJ,CLASS##_program))

";
}

string class_headers()
{
	string s, inc;
	
	s = "";

	foreach(includes, inc)
		s+="#include "+inc+"\n";
	s += "\n";	
	return s;
}

string function_declarations()
{
	BindingFunction f;
	BindingClass c;
	
	string s;
	
	s = "/*\n"
	  + "    Functions that interface with Pike needs C interfaces\n"
	  + "*/\n"
	  + "extern \"C\" {\n";
	// efuns
	foreach(bindingFunctions, f) {
		s+=f->cppDeclaration();
		s+=";\n";
	}
	// class methods
	foreach(bindingClasses, c) {
		s+=c->cppDeclarations();
	}
	s += "void pike_module_init(void);\n";
	s += "void pike_module_exit(void);\n";
	s += "}\n\n";	
	return s;
}

// Returns all the storage struct declarations
string class_storage()
{
	BindingClass c;
	string s="";
	
	foreach(bindingClasses, c) {
		s+=c->storageDeclaration();
	}
	s+="\n";	
	return s;
}

string override_definitions()
{
	BindingClass c;
	string s="";
			
	// This macro is used to call virtual methods
	s+="#define push_method(method) { \\\n";
	s+="\tref_push_object(this->pike_object);\\\n";
	s+="\tpush_text(method);\\\n";
	s+="\tf_index(2); } \n\n";
	
	foreach(bindingClasses, c) {
		s+=c->bindingOverrideDefinitions();
	}
	
	s+="#undef push_method\n\n\n";
	return s;
}

// Returns all pointer to Pike programs definitions
string class_programs()
{
	BindingClass c;
	string s="";
	
	foreach(bindingClasses, c) {
		s+="struct program* "+c->name+"_program;\n";
	}
	s+="\n";
	return s;
}

// Returns all the C++ function (Pike efuns) definitions

string efun_functions()
{
	BindingFunction f;
	string s="";

	foreach(bindingFunctions, f) {
		s+=f->definition()+"\n\n";
	}	
	s+="\n";
	return s;
}

// Returns all the C++ function (Pike methods) definitions
string class_functions()
{
	BindingClass c;
	string s="";
	
	foreach(bindingClasses, c) {
		s+=c->functionsImplementation();
	}
	s+="\n";
	return s;
}

// Returns the main module function 
string main_function()
{
	BindingConstant con;
	BindingFunction f;
	BindingClass c;
	
	string s;
	s="void pike_module_init(void)\n";
	s+="{\n";

	foreach(bindingFunctions, f) {
		s+="\t"+f->pikeDeclaration()+"\n";
	}
	
	foreach(bindingClasses, c) {
		s+=c->pikeDeclarations();
	}
	// Constants are defined after classes, so object
	// constants can be created.
	foreach(bindingConstants, con)
	{
		s+=con->pikeDeclaration();
	} 
	s+="}\n\n";
	
	s+="void pike_module_exit(void)\n";
	s+="{\n";
	s+="}\n";
	return s;
}

int main(int argc, array(string) argv)
{
	if (argc<3) {
		write("Syntax: bindgen [-v] inputfile outputfile\n");
		return 1;
	}
	if (argv[1]=="-v") {
		verbose=1;
		argv=argv[0..0]+argv[2..];
		write("Verbose mode\n");
	}
	write("Parsing...\n");
	parse_input(argv[1]);

	write("Generating...\n");
	Stdio.File o=Stdio.File();
	
	if(!o->open(argv[2]+".h","wct"))
	{
		write("Failed to open file.\n");
		return 2;
	}
	o->write(generic_headers());
	o->write(class_headers());
	o->write(class_storage());
	o->close();
	
	if(!o->open(argv[2]+".cc","wct"))
	{
		write("Failed to open file.\n");
		return 2;
	}
	o->write("/* Generated automatically */\n\n");
	o->write("#include \""+argv[2]+".h\"\n\n");	
	
	o->write(function_declarations());
	o->write(class_programs());
	o->write(override_definitions());
	o->write(efun_functions());
	o->write(class_functions());
	o->write(main_function());

	o->close();
	write("Done.\n");

	return 0;
}


gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University