wrapper generator in progress

This commit is contained in:
Simon Morlat 2013-09-20 10:08:16 +02:00
parent ae764ae952
commit e990ea0cef
8 changed files with 612 additions and 74 deletions

12
COPYING
View file

@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -278,7 +278,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest

View file

@ -171,13 +171,15 @@ void linphone_address_destroy(LinphoneAddress *u){
sal_address_unref(u);
}
/**
* Get port number as an integer value.
*/
/**
* Get port number, 0 if not present.
*/
int linphone_address_get_port(const LinphoneAddress *u) {
#ifdef USE_BELLESIP
return sal_address_get_port(u);
#else
return sal_address_get_port_int(u);
#endif
}
/** @} */

View file

@ -190,7 +190,7 @@ EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH = .
INCLUDE_FILE_PATTERNS = *.h
PREDEFINED = DOXYGEN
PREDEFINED = DOXYGEN MS2_PUBLIC= LINPHONE_PUBLIC=
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------

View file

@ -1203,16 +1203,31 @@ void _linphone_call_params_copy(LinphoneCallParams *ncp, const LinphoneCallParam
if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers);
}
/**
* @ingroup call_control
* Set requested level of privacy for the call.
* \xmlonly <language-tags>javascript</language-tags> \endxmlonly
* @param params the call parameters to be modified
* @param LinphonePrivacy to configure privacy
* */
void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) {
params->privacy=privacy;
}
/**
* @ingroup call_control
* Get requested level of privacy for the call.
* @param params the call parameters
* @return Privacy mode
* */
LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) {
return params->privacy;
}
/**
* @ingroup call_control
* @return string value of LinphonePrivacy enum
**/
const char* linphone_privacy_to_string(LinphonePrivacy privacy) {
switch(privacy) {
case LinphonePrivacyDefault: return "LinphonePrivacyDefault";

View file

@ -182,9 +182,6 @@ const char *linphone_address_get_scheme(const LinphoneAddress *u);
LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u);
LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u);
LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u);
/**
* Get port number as an integer value, -1 if not set.
*/
LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u);
LINPHONE_PUBLIC void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name);
LINPHONE_PUBLIC void linphone_address_set_username(LinphoneAddress *uri, const char *username);
@ -371,24 +368,9 @@ typedef enum _LinphonePrivacy {
* */
typedef unsigned int LinphonePrivacyMask;
/**
* @ingroup call_control
* @return string value of LinphonePrivacy enum
* */
const char* linphone_privacy_to_string(LinphonePrivacy privacy);
/**
* @ingroup call_control
* Set requested level of privacy for the call.
* @param params the call parameters to be modified
* @param LinphonePrivacy to configure privacy
* */
LINPHONE_PUBLIC const char* linphone_privacy_to_string(LinphonePrivacy privacy);
LINPHONE_PUBLIC void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy);
/**
* @ingroup call_control
* Get requested level of privacy for the call.
* @param params the call parameters
* @return Privacy mode
* */
LINPHONE_PUBLIC LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params);

@ -1 +1 @@
Subproject commit ac5233ae16394d59cf4d9783a229f2adc2111b12
Subproject commit 56128aa7e5e613708cd8a35beb5d2643dc4dae67

View file

@ -12,7 +12,7 @@ COMMON_CFLAGS=\
$(STRICT_OPTIONS) \
$(LIBXML2_CFLAGS)
AM_CXXFLAGS=$(LIBXML2_CFLAGS)
AM_CXXFLAGS=$(LIBXML2_CFLAGS) $(STRICT_OPTIONS)
EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc

View file

@ -23,9 +23,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <string.h>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
#include <map>
#include <algorithm>
#include <sys/types.h>
#include <sys/stat.h>
using namespace::std;
@ -33,19 +38,41 @@ using namespace::std;
class Type{
public:
enum BasicType{
Void,
Boolean,
Integer,
Float,
String,
Klass
Enum,
Class
};
static Type* addType(BasicType bt, const string &name){
Type* ret;
if ((ret=mTypes[name])==0){
cout<<"Adding new "<<(bt==Enum ? "enum" : "class")<<" type '"<<name<<"'"<<endl;
ret=mTypes[name]=new Type(bt,name);
}else if (bt==Enum){
ret->mBasic=Enum;
}
return ret;
}
static Type *getType(const std::string &tname){
if (strstr(tname.c_str(),"char")!=0 && strchr(tname.c_str(),'*')!=0){
return &sStringType;
}else if (strcmp(tname.c_str(),"int")==0){
}else if (tname.find("int")==0){
return &sIntegerType;
}else{
Type* ret;
}else if (tname.find("float")==0){
return &sFloatType;
}else if (tname.find("bool_t")==0){
return &sBooleanType;
}else if (tname.find("void")!=string::npos){
return &sVoidType;
}else if (tname.find("enum")==0){
return addType(Enum,tname.c_str()+strlen("enum "));
}else{/*an object?*/
string tmp=tname;
ssize_t pos;
size_t pos;
/*really ugly and slow*/
@ -60,19 +87,17 @@ public:
while ((pos=tmp.find(' '))!=string::npos){
tmp.erase(pos,1);
}
if ((ret=mTypes[tmp])==0){
cout<<"Adding new class type '"<<tmp<<"'"<<endl;
ret=mTypes[tmp]=new Type(Type::Klass,tmp);
}
return ret;
return addType(Class,tmp);
}
cout<<"Unhandled type name"<<tname<<endl;
cerr<<"Unhandled type name"<<tname<<endl;
return NULL;
}
const string &getName()const{
return mName;
}
BasicType getBasicType()const{
return mBasic;
}
private:
BasicType mBasic;
string mName;
@ -80,64 +105,241 @@ private:
}
static Type sStringType;
static Type sIntegerType;
static Type sVoidType;
static Type sBooleanType;
static Type sFloatType;
static std::map<string,Type*> mTypes;
};
Type Type::sStringType(Type::String);
Type Type::sIntegerType(Type::Integer);
Type Type::sVoidType(Type::Void);
Type Type::sBooleanType(Type::Boolean);
Type Type::sFloatType(Type::Float);
std::map<string,Type*> Type::mTypes;
class Argument{
public:
Argument(Type *type, const string &argname, bool isConst) : mType(type), mName(argname), mConst(isConst){
Argument(Type *type, const string &argname, bool isConst, bool isPointer) : mType(type), mName(argname), mConst(isConst), mPointer(isPointer){
if (!isPointer) mConst=false;
}
Type *getType()const{
return mType;
}
bool isConst()const{
return mConst;
}
const string &getName()const{
return mName;
}
bool isPointer()const{
return mPointer;
}
const string &getHelp()const{
return mHelp;
}
private:
bool mConst;
Type *mType;
string mName;
string mHelp;
bool mConst;
bool mPointer;
};
class Method{
public:
Method(const std::string &uid, Argument* return_arg, const std::string &name, const list<Argument*> &args){
enum PropertyBehaviour{
None,
Read,
Write
};
Method(const std::string &uid, Argument* return_arg, const std::string &name, const list<Argument*> &args, bool isConst, bool isStatic){
mUid=uid;
mReturn=return_arg;
mName=name;
mArgs=args;
mConst=isConst;
mStatic=isStatic;
analyseProperties();
}
void setHelp(const std::string &help){
mHelp=help;
}
Argument *getReturnArg()const{
return mReturn;
}
const string &getName()const{
return mName;
}
const list<Argument*> &getArgs()const {
return mArgs;
}
bool isConst()const{
return mConst;
}
bool isStatic()const{
return mStatic;
}
const string &getHelp(){
return mHelp;
}
PropertyBehaviour getPropertyBehaviour()const{
return mPropertyBehaviour;
}
const string &getPropertyName()const{
return mPropertyName;
}
private:
void analyseProperties(){
size_t enabled_pos;
mPropertyBehaviour=None;
if (mName.find("get")==0 && mArgs.size()==0){
mPropertyName=mName.substr(3,string::npos);
if (!mPropertyName.empty()){
mPropertyName[0]=tolower(mPropertyName[0]);
mPropertyBehaviour=Read;
}
}else if (mName.find("enable")==0 && mArgs.size()==1){
mPropertyName=mName.substr(6,string::npos);
if (!mPropertyName.empty()){
mPropertyName[0]=tolower(mPropertyName[0]);
mPropertyBehaviour=Write;
}
}else if (mName.find("set")==0 && mArgs.size()==1){
mPropertyName=mName.substr(3,string::npos);
if (!mPropertyName.empty()){
mPropertyName[0]=tolower(mPropertyName[0]);
mPropertyBehaviour=Write;
}
}else if ((enabled_pos=mName.rfind("Enabled"))!=string::npos && mArgs.size()==0){
size_t goodpos=mName.size()-7;
if (enabled_pos==goodpos){
mPropertyName=mName.substr(0,goodpos);
if (!mPropertyName.empty()){
mPropertyBehaviour=Read;
}
}
}
if (mPropertyBehaviour==None)
mPropertyName="";
}
string mUid;
Argument *mReturn;
string mName;
list<Argument*> mArgs;
string mHelp;
string mPropertyName; /*if it can be a property*/
PropertyBehaviour mPropertyBehaviour;
bool mConst;
bool mStatic;
};
class Property{
public:
enum Attribute{
ReadOnly,
ReadWrite
};
Property(Attribute attr, const string &name, Type *type, const string &help) : mAttr(attr), mName(name), mType(type), mHelp(help){
}
const string &getName()const{
return mName;
}
const string &getHelp()const{
return mHelp;
}
void setHelp(const string &help){
mHelp=help;
}
Attribute getAttribute()const{
return mAttr;
}
void setAttribute(Attribute attr){
mAttr=attr;
}
Type* getType()const{
return mType;
}
private:
Attribute mAttr;
string mName;
Type *mType;
string mHelp;
};
/*actually a class or an enum*/
class Class{
public:
Class(const std::string &name): mName(name){
}
Type::BasicType getType(){
return Type::getType(mName)->getBasicType();
}
void addMethod(Method *method){
mMethods.push_back(method);
if (mMethods.find(method->getName())==mMethods.end())
mMethods.insert(make_pair(method->getName(),method));
}
void setHelp(const std::string &help){
mHelp=help;
}
const list<Method*> getMethods()const{
list<Method*> ret;
map<string,Method*>::const_iterator it;
for(it=mMethods.begin();it!=mMethods.end();++it){
ret.push_back((*it).second);
}
return ret;
}
const string &getName()const{
return mName;
}
const string &getHelp()const{
return mHelp;
}
const list<Property*> getProperties(){
list<Property*> ret;
map<string,Property*>::const_iterator it;
for(it=mProperties.begin();it!=mProperties.end();++it){
ret.push_back((*it).second);
}
return ret;
}
void computeProperties(){
map<string,Method*>::const_iterator it;
Property *prop;
for (it=mMethods.begin();it!=mMethods.end();++it){
Method *m=(*it).second;
if (m->getPropertyBehaviour()==Method::Read){
prop=mProperties[m->getPropertyName()];
if (prop==NULL){
prop=new Property(Property::ReadOnly,m->getPropertyName(),m->getReturnArg()->getType(), m->getHelp());
mProperties[m->getPropertyName()]=prop;
}
}else if (m->getPropertyBehaviour()==Method::Write){
prop=mProperties[m->getPropertyName()];
if (prop==NULL){
prop=new Property(Property::ReadWrite,m->getPropertyName(),m->getArgs().front()->getType(), m->getHelp());
mProperties[m->getPropertyName()]=prop;
}else{
prop->setHelp(m->getHelp());
prop->setAttribute(Property::ReadWrite);
}
}
}
}
private:
list<Method*> mMethods;
map<string,Method*> mMethods;
map<string,Property*> mProperties;
string mName;
string mHelp;
};
class Project{
public:
Project(const string &name="wrapper") : mName(name){
}
Class *getClass(const std::string &name){
Class *ret;
if ((ret=mClasses[name])==NULL){
@ -145,8 +347,280 @@ public:
}
return ret;
}
list<Class*> getClasses()const{
list<Class*> ret;
map<string,Class*>::const_iterator it;
for(it=mClasses.begin();it!=mClasses.end();++it){
ret.push_back((*it).second);
}
return ret;
}
const string &getName()const{
return mName;
}
void analyse(){
list<Class*> classes=getClasses();
for_each(classes.begin(),classes.end(),mem_fun(&Class::computeProperties));
}
private:
map<string,Class*> mClasses;
string mName;
};
class OutputGenerator{
public:
virtual void generate(Project *proj)=0;
};
class CplusplusGenerator : public OutputGenerator{
public:
CplusplusGenerator(){
}
virtual void generate(Project *proj){
list<Class*> classes=proj->getClasses();
mCurProj=proj;
#ifndef WIN32
mkdir(proj->getName().c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH);
#else
_mkdir(proj->getName().c_str());
#endif
for_each(classes.begin(),classes.end(),bind1st(mem_fun(&CplusplusGenerator::writeClass),this));
}
private:
void writeClass(Class *klass){
ostringstream filename;
if (klass->getType()!=Type::Class) return;
filename<<mCurProj->getName()<<"/"<<klass->getName()<<".hh";
mOutfile.open(filename.str().c_str());
if (!mOutfile.is_open()){
cerr<<"Could not write into "<<filename.str()<<endl;
return;
}
const list<Method*> &methods=klass->getMethods();
mCurClass=klass;
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl;
mOutfile<<endl;
mOutfile<<"#include <string>"<<endl;
mOutfile<<endl;
if (!mCurProj->getName().empty())
mOutfile<<"namespace "<<mCurProj->getName()<<"{"<<endl<<endl;
mOutfile<<"class "<<klass->getName()<<"{"<<endl;
mOutfile<<"public:"<<endl;
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&CplusplusGenerator::writeMethod),this));
mOutfile<<"}"<<endl<<endl;
if (!mCurProj->getName().empty())
mOutfile<<"} //end of namespace "<<mCurProj->getName()<<endl;
mOutfile<<endl;
mOutfile.close();
}
void writeArgument(Argument *arg, bool isReturn=false){
Type *type=arg->getType();
if (type->getBasicType()==Type::Class){
if (arg->isConst()){
mOutfile<<"const ";
}
mOutfile<<type->getName();
if (arg->isPointer())
mOutfile<<"*";
}else if (type->getBasicType()==Type::Integer){
mOutfile<<"int";
}else if (type->getBasicType()==Type::Enum){
mOutfile<<type->getName();
}else if (type->getBasicType()==Type::String){
if (!isReturn)
mOutfile<<"const std::string &";
else
mOutfile<<"std::string";
}else if (type->getBasicType()==Type::Void){
mOutfile<<"void";
}else if (type->getBasicType()==Type::Boolean){
mOutfile<<"bool";
}
if (!isReturn && !arg->getName().empty())
mOutfile<<" "<<arg->getName();
}
void writeTabs(int ntabs){
int i;
for(i=0;i<ntabs;++i)
mOutfile<<"\t";
}
void writeHelpComment(const std::string &comment, int ntabs){
size_t i;
int curindex=0;
writeTabs(ntabs);
mOutfile<<" * ";
for(i=0;i<comment.size();i++,curindex++){
if (comment[i]=='\n' || (curindex>100 && comment[i]==' ')){
mOutfile<<endl;
writeTabs(ntabs);
mOutfile<<" * ";
curindex=0;
}else mOutfile<<comment[i];
}
}
void writeMethod(Method *method){
Argument *retarg=method->getReturnArg();
const list<Argument*> &args=method->getArgs();
list<Argument*>::const_iterator it;
writeTabs(1);
mOutfile<<"/**"<<endl;
writeHelpComment(method->getHelp(),1);
mOutfile<<endl;
writeTabs(1);
mOutfile<<"**/"<<endl;
writeTabs(1);
writeArgument(retarg,true);
mOutfile<<" "<<method->getName()<<"(";
for(it=args.begin();it!=args.end();++it){
if (it!=args.begin()) mOutfile<<", ";
writeArgument(*it);
}
mOutfile<<")";
if (method->isConst()) mOutfile<<"const";
mOutfile<<";"<<endl;
mOutfile<<endl;
}
ofstream mOutfile;
Project *mCurProj;
Class *mCurClass;
};
class JavascriptGenerator : public OutputGenerator{
public:
JavascriptGenerator(){
}
virtual void generate(Project *proj){
list<Class*> classes=proj->getClasses();
mCurProj=proj;
#ifndef WIN32
mkdir(proj->getName().c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH);
#else
_mkdir(proj->getName().c_str());
#endif
for_each(classes.begin(),classes.end(),bind1st(mem_fun(&JavascriptGenerator::writeClass),this));
}
private:
void writeClass(Class *klass){
ostringstream filename;
if (klass->getType()!=Type::Class) return;
filename<<mCurProj->getName()<<"/"<<klass->getName()<<".js";
mOutfile.open(filename.str().c_str());
if (!mOutfile.is_open()){
cerr<<"Could not write into "<<filename.str()<<endl;
return;
}
const list<Method*> &methods=klass->getMethods();
mCurClass=klass;
mOutfile<<"/* Wrapper generated by lp-gen-wrappers, do not edit*/"<<endl;
mOutfile<<endl;
//if (!mCurProj->getName().empty())
// mOutfile<<"namespace "<<mCurProj->getName()<<"{"<<endl<<endl;
mOutfile<<"/**"<<endl;
mOutfile<<" * @external "<<klass->getName()<<endl;
mOutfile<<" * "<<klass->getHelp()<<endl;
mOutfile<<"**/"<<endl;
list<Property*> properties=klass->getProperties();
for_each(properties.begin(),properties.end(),bind1st(mem_fun(&JavascriptGenerator::writeProperty),this));
mOutfile<<endl;
for_each(methods.begin(),methods.end(),bind1st(mem_fun(&JavascriptGenerator::writeMethod),this));
//if (!mCurProj->getName().empty())
// mOutfile<<"} //end of namespace "<<mCurProj->getName()<<endl;
mOutfile<<endl;
mOutfile.close();
}
void writeType(Type *type){
switch(type->getBasicType()){
case Type::Float:
case Type::Integer:
mOutfile<<"number";
break;
case Type::String:
mOutfile<<"string";
break;
case Type::Boolean:
mOutfile<<"boolean";
break;
case Type::Class:
case Type::Enum:
mOutfile<<"external:"<<type->getName();
break;
case Type::Void:
mOutfile<<"void";
break;
}
}
void writeArgument(Argument *arg, bool isReturn=false){
if (!isReturn){
mOutfile<<" * @param {";
writeType(arg->getType());
mOutfile<<"} "<<arg->getName()<<" - "<<arg->getHelp()<<endl;
}else{
mOutfile<<" * @returns {";
writeType(arg->getType());
mOutfile<<"} "<<arg->getHelp()<<endl;
}
}
void writeTabs(int ntabs){
int i;
for(i=0;i<ntabs;++i)
mOutfile<<"\t";
}
void writeHelpComment(const std::string &comment, int ntabs){
size_t i;
int curindex=0;
mOutfile<<" * ";
for(i=0;i<comment.size();i++,curindex++){
if (comment[i]=='\n' || (curindex>100 && comment[i]==' ')){
mOutfile<<endl;
mOutfile<<" * ";
curindex=0;
}else mOutfile<<comment[i];
}
}
void writeProperty(Property *prop){
mOutfile<<"/**"<<endl;
writeHelpComment(prop->getHelp(),0);
mOutfile<<endl;
mOutfile<<" * @member {";
writeType(prop->getType());
mOutfile<<"} external:"<<mCurClass->getName()<<"#"<<prop->getName()<<endl;
if (prop->getAttribute()==Property::ReadOnly)
mOutfile<<" * @readonly"<<endl;
mOutfile<<"**/"<<endl;
}
void writeMethod(Method *method){
Argument *retarg=method->getReturnArg();
const list<Argument*> &args=method->getArgs();
list<Argument*>::const_iterator it;
if (method->getPropertyBehaviour()!=Method::None) return;
if (method->getName()=="ref" || method->getName()=="unref") return;
mOutfile<<"/**"<<endl;
writeHelpComment(method->getHelp(),1);
mOutfile<<endl;
mOutfile<<" * @function external:"<<mCurClass->getName()<<"#"<<method->getName()<<endl;
for(it=args.begin();it!=args.end();++it){
writeArgument(*it);
}
writeArgument(retarg,true);
mOutfile<<"**/"<<endl;
mOutfile<<endl;
}
ofstream mOutfile;
Project *mCurProj;
Class *mCurClass;
};
static xmlNode * findChild(xmlNode *a_node, const char *element_name){
@ -181,31 +655,43 @@ static string findChildContent(xmlNode *a_node, const char *element_name){
#define nullOrEmpty(p) (p==NULL || *p=='\0')
static Argument *parseArgument(xmlNode *node){
string name=findChildContent(node,"name");
static Argument *parseArgument(xmlNode *node, bool isReturn){
string name=findChildContent(node,"declname");
Type *type=NULL;
xmlNode *typenode=findChild(node,"type");
string typecontent=findChildContent(node,"type");
bool isConst=false;
bool isPointer=false;
if (!typenode) {
cout<<"Cannot find type from node."<<endl;
return NULL;
}
//find documented type if any
string tname=findChildContent(typenode,"ref");
if (tname.empty()){
return NULL;
}
Type *type=Type::getType(tname);
if (!tname.empty()){
type=Type::getType(tname);
}else type=Type::getType(typecontent);
//find const attribute if any
if (typecontent.find("const")!=string::npos)
isConst=true;
if (typecontent.find("*")!=string::npos)
isPointer=true;
if (type==NULL) {
return NULL;
}
return new Argument(type,name,false);
cout<<"Parsed argument "<<name<<" with type "<<type->getBasicType()<<" "<<type->getName()<<endl;
return new Argument(type,!isReturn ? name : "",isConst,isPointer);
}
static string classNameToPrefix(const std::string &classname){
char tmp[classname.size()*2];
char *w=tmp;
ssize_t i;
size_t i;
for(i=0;i<classname.size();i++){
char p=classname[i];
@ -223,7 +709,7 @@ static string classNameToPrefix(const std::string &classname){
static string makeMethodName(const string & suffix){
char tmp[suffix.size()];
char *w=tmp;
ssize_t i;
size_t i;
bool useUpper=false;
for(i=0;i<suffix.size();i++){
@ -258,6 +744,9 @@ static void parseFunction(Project *proj, xmlNode *node){
xmlNode *cur_node;
string className;
string methodName;
Argument *retarg=NULL;
list<Argument*> args;
string help;
for (cur_node = node->children; cur_node != NULL ; cur_node = cur_node->next){
if (strcmp((const char*)cur_node->name,"name")==0){
@ -265,19 +754,42 @@ static void parseFunction(Project *proj, xmlNode *node){
name=(const char*)content;
xmlFree(content);
}else if (strcmp((const char*)cur_node->name,"param")==0){
if (first_arg==NULL){
first_arg=parseArgument(cur_node);
}
Argument *a=parseArgument(cur_node,false);
if (a) args.push_back(a);
else return;
}else if (strcmp((const char*)cur_node->name,"detaileddescription")==0){
help=findChildContent(cur_node,"para");
}
}
retarg=parseArgument(node,true);
if (!retarg){
cerr<<"Could not parse return argument of function "<<name<<endl;
return;
}
if (!args.empty()) first_arg=args.front();
if (!first_arg){
cout<<"Could not determine first argument of "<<name<<endl;
return;
}
if (first_arg->getType()->getBasicType()!=Type::Class) return;
className=first_arg->getType()->getName();
methodName=extractMethodName(name,className);
if (!methodName.empty()){
if (!methodName.empty() && methodName!="destroy"){
cout<<"Found "<<className<<"."<<methodName<<"()"<<endl;
args.pop_front();
Method *method=new Method("",retarg,methodName,args,first_arg->isConst(),false);
method->setHelp(help);
proj->getClass(className)->addMethod(method);
delete first_arg;
}
}
static void parseTypedef(Project *proj, xmlNode *node){
string typecontent=findChildContent(node,"type");
string name=findChildContent(node,"name");
if (typecontent.find("enum")==0){
Type::addType(Type::Enum,name);
}
}
@ -293,9 +805,13 @@ static void parseMemberDef(Project *proj, xmlNode *node){
return;
kind=xmlGetProp(node,(const xmlChar*)"kind");
//cout<<"Kind="<<(const char*)kind<<endl;
if (kind && xmlStrcmp(kind,(const xmlChar*)"function")==0){
parseFunction(proj,node);
if (kind){
//cout<<"Kind="<<(const char*)kind<<endl;
if (xmlStrcmp(kind,(const xmlChar*)"function")==0){
parseFunction(proj,node);
}else if (xmlStrcmp(kind,(const xmlChar*)"typedef")==0){
parseTypedef(proj,node);
}
}
}
@ -334,23 +850,46 @@ static int parse_file(Project *proj, const char *filename){
/*free the document */
xmlFreeDoc(doc);
return 0;
}
int main(int argc, char *argv[]){
int i;
Project *proj=new Project();
OutputGenerator *gen=NULL;
list<string> files;
list<string>::iterator it;
LIBXML_TEST_VERSION
for(i=1;i<argc;i++){
if (strcmp(argv[i],"--help")==0){
fprintf(stderr,"%s: [--help] file1 file2...\nParses xml files generated by doxygen to output wrappers in a specified language.\n",argv[0]);
fprintf(stderr,"%s: [--help] --output (c++) file1 file2...\nParses xml files generated by doxygen to output wrappers in a specified language.\n",argv[0]);
return -1;
}if (strcmp(argv[i],"--output")==0){
i++;
if (strcmp(argv[i],"c++")==0){
gen=new CplusplusGenerator();
}else if (strcmp(argv[i],"javascript")==0){
gen=new JavascriptGenerator();
}
}else{
if (parse_file(proj,argv[i])==-1)
break;
files.push_back(argv[i]);
}
}
if (gen==NULL) {
cerr<<"No output generator selected !"<<endl;
return -1;
}
for(it=files.begin();it!=files.end();it++){
if (parse_file(proj,(*it).c_str())==-1){
cerr<<"Parsing aborted."<<endl;
return -1;
}
}
proj->analyse();
gen->generate(proj);
return 0;
}
}