// @(#)root/meta:$Id$
// 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 <iostream>
#include "TVirtualMutex.h"

ClassImp(TFunction)

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

   fInfo       = info;
   fMethodArgs = 0;
   if (fInfo) {
      SetName(gCling->MethodInfo_Name(fInfo));
      SetTitle(gCling->MethodInfo_Title(fInfo));
      fMangledName = gCling->MethodInfo_GetMangledName(fInfo);
   }
}

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

   if (orig.fInfo) {
      R__LOCKGUARD(gInterpreterMutex);
      fInfo = gCling->MethodInfo_FactoryCopy(orig.fInfo);
      fMangledName = orig.fMangledName;
   } else
      fInfo = 0;
   fMethodArgs = 0;
}

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

   if (this != &rhs) {
      R__LOCKGUARD(gInterpreterMutex);
      gCling->MethodInfo_Delete(fInfo);
      if (fMethodArgs) fMethodArgs->Delete();
      delete fMethodArgs;
      if (rhs.fInfo) {
         fInfo = gCling->MethodInfo_FactoryCopy(rhs.fInfo);
         SetName(gCling->MethodInfo_Name(fInfo));
         SetTitle(gCling->MethodInfo_Title(fInfo));
         fMangledName = gCling->MethodInfo_GetMangledName(fInfo);
      } else
         fInfo = 0;
      fMethodArgs = 0;
   }
   return *this;
}

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

   R__LOCKGUARD(gInterpreterMutex);
   gCling->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.

   R__LOCKGUARD(gInterpreterMutex);
   gCling->MethodInfo_CreateSignature(fInfo, 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 && fInfo) {
      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*".

   R__LOCKGUARD2(gInterpreterMutex);
   if (fInfo == 0 || gCling->MethodInfo_Type(fInfo) == 0) return "Unknown";
   return gCling->MethodInfo_TypeName(fInfo);
}

//______________________________________________________________________________
std::string TFunction::GetReturnTypeNormalizedName() const
{
   // Get the normalized name of the return type.  A normalized name is fully
   // qualified and has all typedef desugared except for the 'special' typedef
   // which include Double32_t, Float16_t, [U]Long64_t and std::string.  It
   // also has std:: removed [This is subject to change].
   //

   R__LOCKGUARD2(gInterpreterMutex);
   if (fInfo == 0 || gCling->MethodInfo_Type(fInfo) == 0) return "Unknown";
   return gCling->MethodInfo_TypeNormalizedName(fInfo);
}

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

   if (fInfo) return gCling->MethodInfo_NArg(fInfo);
   else if (fMethodArgs) return fMethodArgs->GetEntries();
   else return 0;
}

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

   // FIXME: when unload this is an over-estimate.
   return fInfo ? gCling->MethodInfo_NDefaultArg(fInfo) : GetNargs();
}

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

   return fInfo ? gCling->MethodInfo_Property(fInfo) : 0;
}

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

   return fInfo ? gCling->MethodInfo_ExtraProperty(fInfo) : 0;
}

//______________________________________________________________________________
TDictionary::DeclId_t TFunction::GetDeclId() const
{
   return gInterpreter->GetDeclId(fInfo);
}

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

   return fInfo ? gCling->MethodInfo_InterfaceMethod(fInfo) : 0;
}

//______________________________________________________________________________
Bool_t TFunction::IsValid()
{
   // Return true if this function object is pointing to a currently
   // loaded function.  If a function is unloaded after the TFunction
   // is created, the TFunction will be set to be invalid.

   // Register the transaction when checking the validity of the object.
   if (!fInfo && UpdateInterpreterStateMarker()) {
      // Only for global functions. For data member functions TMethod does it.
      DeclId_t newId = gInterpreter->GetFunction(0, fName);
      if (newId) {
         MethodInfo_t *info = gInterpreter->MethodInfo_Factory(newId);
         Update(info);
      }
      return newId != 0;
   }
   return fInfo != 0;
}

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

   return fMangledName;
}

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

   if (fInfo) {
      R__LOCKGUARD2(gInterpreterMutex);
      return gCling->MethodInfo_GetPrototype(fInfo);
   } else
      return 0;
}

//______________________________________________________________________________
void TFunction::ls(Option_t *options /* ="" */) const
{
   // List TFunction name and title.

   TDictionary::ls(options);
   TROOT::IndentLevel();
   std::cout << "     " << GetPrototype() << '\n';
}

//______________________________________________________________________________
void TFunction::Print(Option_t *options /* ="" */) const
{
   // Print TFunction name and title.

   TDictionary::Print(options);
}

//______________________________________________________________________________
Bool_t TFunction::Update(MethodInfo_t *info)
{
   // Update the TFunction to reflect the new info.
   //
   // This can be used to implement unloading (info == 0) and then reloading
   // (info being the 'new' decl address).

   if (info == 0) {

      if (fInfo) {
         R__LOCKGUARD(gInterpreterMutex);
         gCling->MethodInfo_Delete(fInfo);
      }
      fInfo = 0;
      if (fMethodArgs) {
        for (Int_t i = 0; i < fMethodArgs->LastIndex() + 1; i ++) {
           TMethodArg *arg = (TMethodArg *) fMethodArgs->At( i );
           arg->Update(0);
        }
      }
      return kTRUE;
   } else {
      if (fInfo) {
         R__LOCKGUARD(gInterpreterMutex);
         gCling->MethodInfo_Delete(fInfo);
      }
      fInfo = info;
      TString newMangledName = gCling->MethodInfo_GetMangledName(fInfo);
      if (newMangledName != fMangledName) {
         Error("Update","TFunction object updated with the 'wrong' MethodInfo (%s vs %s).",
               fMangledName.Data(),newMangledName.Data());
         fInfo = 0;
         return false;
      }
      SetTitle(gCling->MethodInfo_Title(fInfo));
      if (fMethodArgs) {
         MethodArgInfo_t *arg = gCling->MethodArgInfo_Factory(fInfo);
         Int_t i = 0;
         R__LOCKGUARD(gInterpreterMutex);
         while (gCling->MethodArgInfo_Next(arg)) {
            if (gCling->MethodArgInfo_IsValid(arg)) {
               MethodArgInfo_t *new_arg = gCling->MethodArgInfo_FactoryCopy(arg);
               ((TMethodArg *) fMethodArgs->At( i ))->Update(new_arg);
               ++i;
            }
         }
      }
      return kTRUE;
   }
}
 TFunction.cxx:1
 TFunction.cxx:2
 TFunction.cxx:3
 TFunction.cxx:4
 TFunction.cxx:5
 TFunction.cxx:6
 TFunction.cxx:7
 TFunction.cxx:8
 TFunction.cxx:9
 TFunction.cxx:10
 TFunction.cxx:11
 TFunction.cxx:12
 TFunction.cxx:13
 TFunction.cxx:14
 TFunction.cxx:15
 TFunction.cxx:16
 TFunction.cxx:17
 TFunction.cxx:18
 TFunction.cxx:19
 TFunction.cxx:20
 TFunction.cxx:21
 TFunction.cxx:22
 TFunction.cxx:23
 TFunction.cxx:24
 TFunction.cxx:25
 TFunction.cxx:26
 TFunction.cxx:27
 TFunction.cxx:28
 TFunction.cxx:29
 TFunction.cxx:30
 TFunction.cxx:31
 TFunction.cxx:32
 TFunction.cxx:33
 TFunction.cxx:34
 TFunction.cxx:35
 TFunction.cxx:36
 TFunction.cxx:37
 TFunction.cxx:38
 TFunction.cxx:39
 TFunction.cxx:40
 TFunction.cxx:41
 TFunction.cxx:42
 TFunction.cxx:43
 TFunction.cxx:44
 TFunction.cxx:45
 TFunction.cxx:46
 TFunction.cxx:47
 TFunction.cxx:48
 TFunction.cxx:49
 TFunction.cxx:50
 TFunction.cxx:51
 TFunction.cxx:52
 TFunction.cxx:53
 TFunction.cxx:54
 TFunction.cxx:55
 TFunction.cxx:56
 TFunction.cxx:57
 TFunction.cxx:58
 TFunction.cxx:59
 TFunction.cxx:60
 TFunction.cxx:61
 TFunction.cxx:62
 TFunction.cxx:63
 TFunction.cxx:64
 TFunction.cxx:65
 TFunction.cxx:66
 TFunction.cxx:67
 TFunction.cxx:68
 TFunction.cxx:69
 TFunction.cxx:70
 TFunction.cxx:71
 TFunction.cxx:72
 TFunction.cxx:73
 TFunction.cxx:74
 TFunction.cxx:75
 TFunction.cxx:76
 TFunction.cxx:77
 TFunction.cxx:78
 TFunction.cxx:79
 TFunction.cxx:80
 TFunction.cxx:81
 TFunction.cxx:82
 TFunction.cxx:83
 TFunction.cxx:84
 TFunction.cxx:85
 TFunction.cxx:86
 TFunction.cxx:87
 TFunction.cxx:88
 TFunction.cxx:89
 TFunction.cxx:90
 TFunction.cxx:91
 TFunction.cxx:92
 TFunction.cxx:93
 TFunction.cxx:94
 TFunction.cxx:95
 TFunction.cxx:96
 TFunction.cxx:97
 TFunction.cxx:98
 TFunction.cxx:99
 TFunction.cxx:100
 TFunction.cxx:101
 TFunction.cxx:102
 TFunction.cxx:103
 TFunction.cxx:104
 TFunction.cxx:105
 TFunction.cxx:106
 TFunction.cxx:107
 TFunction.cxx:108
 TFunction.cxx:109
 TFunction.cxx:110
 TFunction.cxx:111
 TFunction.cxx:112
 TFunction.cxx:113
 TFunction.cxx:114
 TFunction.cxx:115
 TFunction.cxx:116
 TFunction.cxx:117
 TFunction.cxx:118
 TFunction.cxx:119
 TFunction.cxx:120
 TFunction.cxx:121
 TFunction.cxx:122
 TFunction.cxx:123
 TFunction.cxx:124
 TFunction.cxx:125
 TFunction.cxx:126
 TFunction.cxx:127
 TFunction.cxx:128
 TFunction.cxx:129
 TFunction.cxx:130
 TFunction.cxx:131
 TFunction.cxx:132
 TFunction.cxx:133
 TFunction.cxx:134
 TFunction.cxx:135
 TFunction.cxx:136
 TFunction.cxx:137
 TFunction.cxx:138
 TFunction.cxx:139
 TFunction.cxx:140
 TFunction.cxx:141
 TFunction.cxx:142
 TFunction.cxx:143
 TFunction.cxx:144
 TFunction.cxx:145
 TFunction.cxx:146
 TFunction.cxx:147
 TFunction.cxx:148
 TFunction.cxx:149
 TFunction.cxx:150
 TFunction.cxx:151
 TFunction.cxx:152
 TFunction.cxx:153
 TFunction.cxx:154
 TFunction.cxx:155
 TFunction.cxx:156
 TFunction.cxx:157
 TFunction.cxx:158
 TFunction.cxx:159
 TFunction.cxx:160
 TFunction.cxx:161
 TFunction.cxx:162
 TFunction.cxx:163
 TFunction.cxx:164
 TFunction.cxx:165
 TFunction.cxx:166
 TFunction.cxx:167
 TFunction.cxx:168
 TFunction.cxx:169
 TFunction.cxx:170
 TFunction.cxx:171
 TFunction.cxx:172
 TFunction.cxx:173
 TFunction.cxx:174
 TFunction.cxx:175
 TFunction.cxx:176
 TFunction.cxx:177
 TFunction.cxx:178
 TFunction.cxx:179
 TFunction.cxx:180
 TFunction.cxx:181
 TFunction.cxx:182
 TFunction.cxx:183
 TFunction.cxx:184
 TFunction.cxx:185
 TFunction.cxx:186
 TFunction.cxx:187
 TFunction.cxx:188
 TFunction.cxx:189
 TFunction.cxx:190
 TFunction.cxx:191
 TFunction.cxx:192
 TFunction.cxx:193
 TFunction.cxx:194
 TFunction.cxx:195
 TFunction.cxx:196
 TFunction.cxx:197
 TFunction.cxx:198
 TFunction.cxx:199
 TFunction.cxx:200
 TFunction.cxx:201
 TFunction.cxx:202
 TFunction.cxx:203
 TFunction.cxx:204
 TFunction.cxx:205
 TFunction.cxx:206
 TFunction.cxx:207
 TFunction.cxx:208
 TFunction.cxx:209
 TFunction.cxx:210
 TFunction.cxx:211
 TFunction.cxx:212
 TFunction.cxx:213
 TFunction.cxx:214
 TFunction.cxx:215
 TFunction.cxx:216
 TFunction.cxx:217
 TFunction.cxx:218
 TFunction.cxx:219
 TFunction.cxx:220
 TFunction.cxx:221
 TFunction.cxx:222
 TFunction.cxx:223
 TFunction.cxx:224
 TFunction.cxx:225
 TFunction.cxx:226
 TFunction.cxx:227
 TFunction.cxx:228
 TFunction.cxx:229
 TFunction.cxx:230
 TFunction.cxx:231
 TFunction.cxx:232
 TFunction.cxx:233
 TFunction.cxx:234
 TFunction.cxx:235
 TFunction.cxx:236
 TFunction.cxx:237
 TFunction.cxx:238
 TFunction.cxx:239
 TFunction.cxx:240
 TFunction.cxx:241
 TFunction.cxx:242
 TFunction.cxx:243
 TFunction.cxx:244
 TFunction.cxx:245
 TFunction.cxx:246
 TFunction.cxx:247
 TFunction.cxx:248
 TFunction.cxx:249
 TFunction.cxx:250
 TFunction.cxx:251
 TFunction.cxx:252
 TFunction.cxx:253
 TFunction.cxx:254
 TFunction.cxx:255
 TFunction.cxx:256
 TFunction.cxx:257
 TFunction.cxx:258
 TFunction.cxx:259
 TFunction.cxx:260
 TFunction.cxx:261
 TFunction.cxx:262
 TFunction.cxx:263
 TFunction.cxx:264
 TFunction.cxx:265
 TFunction.cxx:266
 TFunction.cxx:267
 TFunction.cxx:268
 TFunction.cxx:269
 TFunction.cxx:270
 TFunction.cxx:271
 TFunction.cxx:272
 TFunction.cxx:273
 TFunction.cxx:274
 TFunction.cxx:275
 TFunction.cxx:276
 TFunction.cxx:277
 TFunction.cxx:278
 TFunction.cxx:279
 TFunction.cxx:280
 TFunction.cxx:281
 TFunction.cxx:282
 TFunction.cxx:283
 TFunction.cxx:284
 TFunction.cxx:285
 TFunction.cxx:286
 TFunction.cxx:287
 TFunction.cxx:288
 TFunction.cxx:289
 TFunction.cxx:290
 TFunction.cxx:291
 TFunction.cxx:292
 TFunction.cxx:293
 TFunction.cxx:294
 TFunction.cxx:295
 TFunction.cxx:296
 TFunction.cxx:297
 TFunction.cxx:298
 TFunction.cxx:299
 TFunction.cxx:300
 TFunction.cxx:301
 TFunction.cxx:302
 TFunction.cxx:303
 TFunction.cxx:304
 TFunction.cxx:305
 TFunction.cxx:306
 TFunction.cxx:307
 TFunction.cxx:308
 TFunction.cxx:309
 TFunction.cxx:310
 TFunction.cxx:311
 TFunction.cxx:312
 TFunction.cxx:313
 TFunction.cxx:314
 TFunction.cxx:315
 TFunction.cxx:316
 TFunction.cxx:317
 TFunction.cxx:318
 TFunction.cxx:319
 TFunction.cxx:320
 TFunction.cxx:321
 TFunction.cxx:322
 TFunction.cxx:323