#include "TClass.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TMethodCall.h"
#include "TROOT.h"
#include "TApplication.h"
#include "TInterpreter.h"
#include "Strlen.h"
#include "TDataMember.h"
ClassImp(TMethod)
TMethod::TMethod(MethodInfo_t *info, TClass *cl) : TFunction(info)
{
fClass = cl;
fGetterMethod = 0;
fSetterMethod = 0;
fMenuItem = kMenuNoMenu;
if (fInfo) {
SetMenuItem(gCling->MethodInfo_Title(fInfo));
}
}
TMethod::TMethod(const TMethod& orig) : TFunction(orig)
{
fClass = orig.fClass;
fMenuItem = orig.fMenuItem;
fGetter = orig.fGetter;
fGetterMethod = 0;
fSetterMethod = 0;
}
TMethod& TMethod::operator=(const TMethod& rhs)
{
if (this != &rhs) {
TFunction::operator=(rhs);
fClass = rhs.fClass;
fMenuItem = rhs.fMenuItem;
fGetter = rhs.fGetter;
if (fGetterMethod)
delete fGetterMethod;
fGetterMethod = 0;
if (fSetterMethod)
delete fSetterMethod;
fSetterMethod = 0;
}
return *this;
}
TMethod::~TMethod()
{
delete fGetterMethod;
delete fSetterMethod;
}
TObject *TMethod::Clone(const char *newname) const
{
TNamed *newobj = new TMethod(*this);
if (newname && strlen(newname)) newobj->SetName(newname);
return newobj;
}
const char *TMethod::GetCommentString()
{
return fInfo ? gCling->MethodInfo_Title(fInfo) : "";
}
void TMethod::CreateSignature()
{
TFunction::CreateSignature();
if (Property() & kIsConstMethod) fSignature += " const";
}
TDataMember *TMethod::FindDataMember()
{
Char_t *argstring = (char*)strstr(GetCommentString(),"*ARGS={");
if (argstring) {
if (!fMethodArgs) return 0;
Int_t nchs = strlen(argstring);
char *argstr = new char[nchs+1];
char *ptr1 = 0;
char *tok = 0;
char *ptr2 = 0;
Int_t i;
strlcpy(argstr,argstring,nchs+1);
ptr2 = strtok(argstr,"{}");
if (ptr2 == 0) {
Fatal("FindDataMember","Internal error found '*ARGS=\"' but not \"{}\" in %s",GetCommentString());
delete [] argstr;
return 0;
}
ptr2 = strtok((char*)0,"{}");
char *tokens[20];
Int_t cnt = 0;
Int_t token_cnt = 0;
do {
ptr1 = strtok((char*) (cnt++ ? 0:ptr2),",;");
if (ptr1) {
Int_t nch = strlen(ptr1);
tok = new char[nch+1];
strlcpy(tok,ptr1,nch+1);
tokens[token_cnt] = tok;
token_cnt++;
}
} while (ptr1);
TClass *cl = 0;
TMethodArg *a = 0;
TMethodArg *ar = 0;
TDataMember *member = 0;
for (i=0; i<token_cnt;i++) {
cnt = 0;
ptr1 = strtok(tokens[i],"=>");
ptr2 = strtok((char*)0,"=>");
a = 0;
ar = 0;
member = 0;
TIter nextarg(fMethodArgs);
while ((ar = (TMethodArg*)nextarg())) {
if (!strcmp(ptr1,ar->GetName())) {
a = ar;
break;
}
}
cl = GetClass()->GetBaseDataMember(ptr2);
if (cl) {
member = cl->GetDataMember(ptr2);
if (a) a->fDataMember = member;
}
delete [] tokens[i];
}
delete [] argstr;
return member;
} else {
if (fMethodArgs)
if (fMethodArgs->GetSize() != 1) return 0;
TMethodArg *a = 0;
if (fMethodArgs) a = (TMethodArg*)(fMethodArgs->First());
char dataname[64] = "";
char basename[64] = "";
const char *funcname = GetName();
if ( strncmp(funcname,"Get",3) == 0 || strncmp(funcname,"Set",3) == 0 )
snprintf(basename,64,"%s",funcname+3);
else if ( strncmp(funcname,"Is",2) == 0 )
snprintf(basename,64,"%s",funcname+2);
else if (strncmp(funcname, "Has", 3) == 0)
snprintf(basename,64,"%s", funcname+3);
else
return 0;
snprintf(dataname,64,"f%s",basename);
TClass *cl = GetClass()->GetBaseDataMember(dataname);
if (cl) {
TDataMember *member = cl->GetDataMember(dataname);
if (a) a->fDataMember = member;
return member;
} else {
snprintf(dataname,64,"fIs%s",basename);
cl = GetClass()->GetBaseDataMember(dataname);
if (cl) {
TDataMember *member = cl->GetDataMember(dataname);
if (a) a->fDataMember = member;
return member;
}
}
}
return 0;
}
TMethodCall *TMethod::GetterMethod()
{
if (!fGetterMethod && fMenuItem == kMenuToggle && fGetter != "" && fClass) {
fGetterMethod = new TMethodCall(fClass, Getter(), "");
}
return fGetterMethod;
}
Bool_t TMethod::IsValid()
{
if (!fInfo && UpdateInterpreterStateMarker()) {
DeclId_t newId = gInterpreter->GetFunction(fClass->GetClassInfo(), fName);
if (newId) {
MethodInfo_t *info = gInterpreter->MethodInfo_Factory(newId);
Update(info);
}
return newId != 0;
}
return fInfo != 0;
}
TMethodCall *TMethod::SetterMethod()
{
if (!fSetterMethod && fMenuItem == kMenuToggle && fClass) {
fSetterMethod = new TMethodCall(fClass, GetName(), "1");
}
return fSetterMethod;
}
TList *TMethod::GetListOfMethodArgs()
{
if (!fMethodArgs){
TFunction::GetListOfMethodArgs();
FindDataMember();
}
return fMethodArgs;
}
void TMethod::SetMenuItem(const char *docstring)
{
if (docstring && strstr(docstring, "*TOGGLE")) {
fMenuItem = kMenuToggle;
const char *s;
if ((s = strstr(docstring, "*GETTER="))) {
fGetter = s+8;
fGetter = fGetter.Strip(TString::kBoth);
}
} else
if (docstring && strstr(docstring, "*MENU"))
fMenuItem = kMenuDialog;
else
if (docstring && strstr(docstring, "*SUBMENU"))
fMenuItem = kMenuSubMenu;
else
fMenuItem = kMenuNoMenu;
}
Bool_t TMethod::Update(MethodInfo_t *info)
{
if (TFunction::Update(info)) {
delete fGetterMethod; fGetterMethod = 0;
delete fSetterMethod; fSetterMethod = 0;
if (fInfo) {
SetMenuItem(gCling->MethodInfo_Title(fInfo));
}
return kTRUE;
} else {
return kFALSE;
}
}