    // @(#)root/meta:$Name:  $:$Id: TFunction.cxx,v 1.13 2005/06/07 16:18:32 brun Exp $
    // Author: Fons Rademakers   07/02/97

    /*************************************************************************
     * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
     * All rights reserved.                                                  *
     *                                                                       *
     * For the licensing terms see $ROOTSYS/LICENSE.                         *
     * For the list of contributors see $ROOTSYS/README/CREDITS.             *
     *************************************************************************/

    //////////////////////////////////////////////////////////////////////////
    //                                                                      //
    // Global functions class (global functions are obtaine from CINT).     //
    // This class describes one single global function.                     //
    // The TROOT class contains a list of all currently defined global      //
    // functions (accessible via TROOT::GetListOfGlobalFunctions()).        //
    //                                                                      //
    //////////////////////////////////////////////////////////////////////////

    #include "TFunction.h"
    #include "TMethodArg.h"
    #include "TROOT.h"
    #include "TInterpreter.h"
    #include "Strlen.h"
    #include "Api.h"

    ClassImp(TFunction)

    //______________________________________________________________________________
     TFunction::TFunction(G__MethodInfo *info) : TDictionary()
    {
       // Default TFunction ctor. TFunctions are constructed in TROOT via
       // a call to TCint::UpdateListOfGlobalFunctions().

       fInfo       = info;
       fMethodArgs = 0;
       if (fInfo) {
          SetName(fInfo->Name());
          SetTitle(fInfo->Title());
          fMangledName = fInfo->GetMangledName();
       }
    }

    //______________________________________________________________________________
     TFunction::TFunction(const TFunction &orig) : TDictionary(orig)
    {
       // Copy operator.

       if (orig.fInfo) {
          fInfo = new G__MethodInfo(*orig.fInfo);
          fMangledName = fInfo->GetMangledName();
       } else
          fInfo = 0;
       fMethodArgs = 0;
    }

    //______________________________________________________________________________
    TFunction& TFunction::operator=(const TFunction &rhs)
    {
       // Assignment operator.

       if (this != &rhs) {
          delete fInfo;
          if (fMethodArgs) fMethodArgs->Delete();
          delete fMethodArgs;
          if (rhs.fInfo) {
             fInfo = new G__MethodInfo(*rhs.fInfo);
             SetName(fInfo->Name());
             SetTitle(fInfo->Title());
             fMangledName = fInfo->GetMangledName();
          } else
             fInfo = 0;
          fMethodArgs = 0;
       }
       return *this;
    }

    //______________________________________________________________________________
     TFunction::~TFunction()
    {
       // TFunction dtor deletes adopted G__MethodInfo.

       delete fInfo;

       if (fMethodArgs) fMethodArgs->Delete();
       delete fMethodArgs;
    }

    //______________________________________________________________________________
     TObject *TFunction::Clone(const char *newname) const
    {
       // Clone method.

       TNamed *newobj = new TFunction(*this);
       if (newname && strlen(newname)) newobj->SetName(newname);
       return newobj;
    }

    //______________________________________________________________________________
     void TFunction::CreateSignature()
    {
       // Using the CINT method arg information to create a complete signature string.

       G__MethodArgInfo arg(*fInfo);

       int ifirst = 0;
       fSignature = "(";
       while (arg.Next()) {
          if (ifirst) fSignature += ", ";
          if (arg.Type() == 0) break;
          //if (arg.Property() & G__BIT_ISCONSTANT)   // is returned as part of the name
          //   fSignature += "const ";
          fSignature += arg.Type()->Name();
          if (arg.Name() && strlen(arg.Name())) {
             fSignature += " ";
             fSignature += arg.Name();
          }
          if (arg.DefaultValue()) {
             fSignature += " = ";
             const char *charstar = strstr(arg.Type()->TrueName(),"char*");
             if (charstar) fSignature += "\"";
             fSignature += arg.DefaultValue();
             if (charstar) fSignature += "\"";
          }
          ifirst++;
       }
       fSignature += ")";
    }

    //______________________________________________________________________________
     const char *TFunction::GetSignature()
    {
       // Return signature of function.

       if (fInfo && fSignature.IsNull())
          CreateSignature();

       return fSignature.Data();
    }

    //______________________________________________________________________________
     TList *TFunction::GetListOfMethodArgs()
    {
       // Return list containing the TMethodArgs of a TFunction.

       if (!fMethodArgs) {
          if (!gInterpreter)
             Fatal("GetListOfMethodArgs", "gInterpreter not initialized");

          gInterpreter->CreateListOfMethodArgs(this);
       }
       return fMethodArgs;
    }

    //______________________________________________________________________________
     const char *TFunction::GetReturnTypeName() const
    {
       // Get full type description of function return type, e,g.: "class TDirectory*".

       if (fInfo->Type() == 0) return "Unknown";
       return fInfo->Type()->Name();
    }

    //______________________________________________________________________________
     Int_t TFunction::GetNargs() const
    {
       // Number of function arguments.

       return fInfo->NArg();
    }

    //______________________________________________________________________________
     Int_t TFunction::GetNargsOpt() const
    {
       // Number of function optional (default) arguments.

       return fInfo->NDefaultArg();
    }

    //______________________________________________________________________________
     Long_t TFunction::Property() const
    {
       // Get property description word. For meaning of bits see EProperty.

       return fInfo->Property();
    }

    //______________________________________________________________________________
     void *TFunction::InterfaceMethod() const
    {
       // Return pointer to the interface method. Using this pointer we
       // can find which TFunction belongs to a G__MethodInfo object.
       // Both need to have the same InterfaceMethod pointer.

       G__InterfaceMethod pfunc = fInfo->InterfaceMethod();
       if (!pfunc) {
          struct G__bytecodefunc *bytecode = fInfo->GetBytecode();

          if(bytecode) pfunc = (G__InterfaceMethod)G__exec_bytecode;
          else {
            pfunc = (G__InterfaceMethod)NULL;
          }
       }
       return (void*)pfunc;
    }

    //______________________________________________________________________________
     const char *TFunction::GetMangledName() const
    {
       // Returns the mangled name as defined by CINT, or 0 in case of error.

       // This function is being used by TROOT to determine the full identity of
       // of the function.  It has to work even if the function has been
       // unloaded by cint (in which case fInfo is actually hold reference to
       // memory that is (likely) not valid anymore.  So we cache the information.
       // Maybe we should also cache the rest of the informations .. but this might
       // be too much duplication of information.
       if (fInfo)
          return fMangledName;
       else
          return 0;
    }

    //______________________________________________________________________________
     const char *TFunction::GetPrototype() const
    {
       // Returns the prototype of a function as defined by CINT, or 0 in
       // case of error.

       if (fInfo)
          return fInfo->GetPrototype();
       else
          return 0;
    }