
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;
}