ROOT logo
// @(#)root/base:$Id$
// Author: Fons Rademakers   26/1/2002

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPluginManager                                                       //
//                                                                      //
// This class implements a plugin library manager. It keeps track of    //
// a list of plugin handlers. A plugin handler knows which plugin       //
// library to load to get a specific class that is used to extend the   //
// functionality of a specific base class and how to create an object   //
// of this class. For example, to extend the base class TFile to be     //
// able to read RFIO files one needs to load the plugin library         //
// libRFIO.so which defines the TRFIOFile class. This loading should    //
// be triggered when a given URI contains a regular expression defined  //
// by the handler.                                                      //
// Plugin handlers can be defined via macros in a list of plugin        //
// directories. With $ROOTSYS/etc/plugins the default top plugin        //
// directory specified in $ROOTSYS/etc/system.rootrc. Additional        //
// directories can be specified by adding them to the end of the list.  //
// Macros for identical plugin handlers in later directories will       //
// override previous ones (the inverse of normal search path behavior). //
// The macros must have names like <BaseClass>/PX0_<PluginClass>.C,     //
// e.g.:                                                                //
//    TFile/P10_TRFIOFile.C, TSQLServer/P20_TMySQLServer.C, etc.        //
// to allow easy sorting and grouping. If the BaseClass is in a         //
// namespace the directory must have the name NameSpace@@BaseClass as   //
// : is a reserved pathname character on some operating systems.        //
// Macros not beginning with 'P' and ending with ".C" are ignored.      //
// These macros typically look like:                                    //
//                                                                      //
//   void P10_TDCacheFile()                                             //
//   {                                                                  //
//       gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile",      //
//          "DCache", "TDCacheFile(const char*,Option_t*)");            //
//   }                                                                  //
//                                                                      //
// Plugin handlers can also be defined via resources in the .rootrc     //
// file. Although now deprecated this method still works for backward   //
// compatibility, e.g.:                                                 //
//                                                                      //
//   Plugin.TFile:       ^rfio:   TRFIOFile    RFIO   "<constructor>"   //
//   Plugin.TSQLServer:  ^mysql:  TMySQLServer MySQL  "<constructor>"   //
//   +Plugin.TSQLServer: ^pgsql:  TPgSQLServer PgSQL  "<constructor>"   //
//   Plugin.TVirtualFitter: *     TFitter      Minuit "TFitter(Int_t)"  //
//                                                                      //
// Where the + in front of Plugin.TSQLServer says that it extends the   //
// existing definition of TSQLServer, useful when there is more than    //
// one plugin that can extend the same base class. The "<constructor>"  //
// should be the constructor or a static method that generates an       //
// instance of the specified class. Global methods should start with    //
// "::" in their name, like "::CreateFitter()".                         //
// Instead of being a shared library a plugin can also be a CINT        //
// script, so instead of libDialog.so one can have Dialog.C.            //
// The * is a placeholder in case there is no need for a URI to         //
// differentiate between different plugins for the same base class.     //
// For the default plugins see $ROOTSYS/etc/system.rootrc.              //
//                                                                      //
// Plugin handlers can also be registered at run time, e.g.:            //
//                                                                      //
//   gPluginMgr->AddHandler("TSQLServer", "^sapdb:",                    //
//                          "TSapDBServer", "SapDB",                    //
//             "TSapDBServer(const char*,const char*, const char*)");   //
//                                                                      //
// A list of currently defined handlers can be printed using:           //
//                                                                      //
//   gPluginMgr->Print(); // use option="a" to see ctors                //
//                                                                      //
// The use of the plugin library manager removes all textual references //
// to hard-coded class and library names and the resulting dependencies //
// in the base classes. The plugin manager is used to extend a.o.       //
// TFile, TSQLServer, TGrid, etc. functionality.                        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TPluginManager.h"
#include "Varargs.h"
#include "TEnv.h"
#include "TRegexp.h"
#include "TROOT.h"
#include "TSortedList.h"
#include "THashList.h"
#include "THashTable.h"
#include "Varargs.h"
#include "TClass.h"
#include "TInterpreter.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TDataType.h"
#include "TMethodCall.h"
#include "TVirtualMutex.h"
#include "TSystem.h"
#include "TObjString.h"
#include "ThreadLocalStorage.h"


TPluginManager *gPluginMgr;   // main plugin manager created in TROOT

static TVirtualMutex *gPluginManagerMutex;

static bool &TPH__IsReadingDirs() {
   TTHREAD_TLS(bool) readingDirs (false);
   return readingDirs;
}

ClassImp(TPluginHandler)

//______________________________________________________________________________
TPluginHandler::TPluginHandler(const char *base, const char *regexp,
                               const char *className, const char *pluginName,
                               const char *ctor, const char *origin):
   fBase(base),
   fRegexp(regexp),
   fClass(className),
   fPlugin(pluginName),
   fCtor(ctor),
   fOrigin(origin),
   fCallEnv(0),
   fMethod(0),
   fCanCall(0),
   fIsMacro(kFALSE),
   fIsGlobal(kFALSE)
{
   // Create a plugin handler. Called by TPluginManager.

   TString aclicMode, arguments, io;
   TString fname = gSystem->SplitAclicMode(fPlugin, aclicMode, arguments, io);
   Bool_t validMacro = kFALSE;
   if (fname.EndsWith(".C") || fname.EndsWith(".cxx") || fname.EndsWith(".cpp") ||
       fname.EndsWith(".cc"))
      validMacro = kTRUE;

   if (validMacro && gROOT->LoadMacro(fPlugin, 0, kTRUE) == 0)
      fIsMacro = kTRUE;

   if (fCtor.Contains("::")) {
      fIsGlobal = kTRUE;
      fCtor = fCtor.Strip(TString::kLeading, ':');
   }
}

//______________________________________________________________________________
TPluginHandler::~TPluginHandler()
{
   // Cleanup plugin handler object.

   delete fCallEnv;
}

//______________________________________________________________________________
Bool_t TPluginHandler::CanHandle(const char *base, const char *uri)
{
   // Check if regular expression appears in the URI, if so return kTRUE.
   // If URI = 0 always return kTRUE.

   if (fBase != base)
      return kFALSE;

   if (!uri || fRegexp == "*")
      return kTRUE;

   Bool_t wildcard = kFALSE;
   if (!fRegexp.MaybeRegexp())
      wildcard = kTRUE;

   TRegexp re(fRegexp, wildcard);
   TString ruri = uri;

   if (ruri.Index(re) != kNPOS)
      return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
void TPluginHandler::SetupCallEnv()
{
   // Setup ctor or static method call environment.

   fCanCall = -1;

   // check if class exists
   TClass *cl = TClass::GetClass(fClass);
   if (!cl && !fIsGlobal) {
      Error("SetupCallEnv", "class %s not found in plugin %s", fClass.Data(),
            fPlugin.Data());
      return;
   }

   // split method and prototype strings
   TString method = fCtor(0, fCtor.Index("("));
   TString proto  = fCtor(fCtor.Index("(")+1, fCtor.Index(")")-fCtor.Index("(")-1);

   if (fIsGlobal) {
      cl = 0;
      fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kTRUE);
   } else {
      fMethod = cl->GetMethodWithPrototype(method, proto);
   }

   if (!fMethod) {
      if (fIsGlobal)
         Error("SetupCallEnv", "global function %s not found", method.Data());
      else
         Error("SetupCallEnv", "method %s not found in class %s", method.Data(),
               fClass.Data());
      return;
   }

   if (!fIsGlobal && !(fMethod->Property() & kIsPublic)) {
      Error("SetupCallEnv", "method %s is not public", method.Data());
      return;
   }

   fCallEnv = new TMethodCall;
   fCallEnv->InitWithPrototype(cl, method, proto);

   fCanCall = 1;

   return;
}

//______________________________________________________________________________
Int_t TPluginHandler::CheckPlugin() const
{
   // Check if the plugin library for this handler exits. Returns 0
   // when it exists and -1 in case the plugin does not exist.

   if (fIsMacro) {
      if (TClass::GetClass(fClass)) return 0;
      return gROOT->LoadMacro(fPlugin, 0, kTRUE);
   } else
      return gROOT->LoadClass(fClass, fPlugin, kTRUE);
}

//______________________________________________________________________________
Int_t TPluginHandler::LoadPlugin()
{
   // Load the plugin library for this handler. Returns 0 on successful loading
   // and -1 in case the library does not exist or in case of error.

   if (fIsMacro) {
      if (TClass::GetClass(fClass)) return 0;
      return gROOT->LoadMacro(fPlugin);
   } else {
      // first call also loads dependent libraries declared via the rootmap file
      if (gROOT->LoadClass(fClass)) return 0;
      return gROOT->LoadClass(fClass, fPlugin);
   }
}

//______________________________________________________________________________
Long_t TPluginHandler::ExecPlugin(Int_t va_(nargs), ...)
{
   // Execute ctor for this plugin and return pointer to object of specific
   // class. User must cast the returned long to the correct class.
   // This method accepts a variable number of arguments to be passed
   // to the ctor, where nargs is the number of arguments, followed
   // by nargs arguments. Returns 0 in case of error.

   if (fCtor.IsNull()) {
      Error("ExecPlugin", "no ctor specified for this handler %s", fClass.Data());
      return 0;
   }

   if (!fCallEnv && !fCanCall)
      SetupCallEnv();

   if (fCanCall == -1)
      return 0;

   if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
       nargs > fMethod->GetNargs()) {
      Error("ExecPlugin", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
            nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
            fMethod->GetNargs());
      return 0;
   }

   R__LOCKGUARD2(gCINTMutex);

   fCallEnv->ResetParam();

   if (nargs > 0) {
      TIter next(fMethod->GetListOfMethodArgs());
      TMethodArg *arg;

      va_list ap;
      va_start(ap, va_(nargs));

      for (int i = 0; i < nargs; i++) {
         arg = (TMethodArg*) next();
         TString type = arg->GetFullTypeName();
         TDataType *dt = gROOT->GetType(type);
         if (dt)
            type = dt->GetFullTypeName();
         if (arg->Property() & (kIsPointer | kIsArray | kIsReference))
            fCallEnv->SetParam((Long_t) va_arg(ap, void*));
         else if (type == "bool")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // bool is promoted to int
         else if (type == "char" || type == "unsigned char")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // char is promoted to int
         else if (type == "short" || type == "unsigned short")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // short is promoted to int
         else if (type == "int" || type == "unsigned int")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));
         else if (type == "long" || type == "unsigned long")
            fCallEnv->SetParam((Long_t) va_arg(ap, long));
         else if (type == "long long")
            fCallEnv->SetParam((Long64_t) va_arg(ap, Long64_t));
         else if (type == "unsigned long long")
            fCallEnv->SetParam((ULong64_t) va_arg(ap, ULong64_t));
         else if (type == "float")
            fCallEnv->SetParam((Double_t) va_arg(ap, double));  // float is promoted to double
         else if (type == "double")
            fCallEnv->SetParam((Double_t) va_arg(ap, double));
      }

      va_end(ap);
   }

   Long_t ret;
   fCallEnv->Execute(ret);

   return ret;
}

//______________________________________________________________________________
void TPluginHandler::Print(Option_t *opt) const
{
   // Print info about the plugin handler. If option is "a" print
   // also the ctor's that will be used.

   const char *exist = "";
   if (CheckPlugin() == -1)
      exist = " [*]";

   Printf("%-20s %-13s %-18s %s%s", fBase.Data(), fRegexp.Data(),
          fClass.Data(), fPlugin.Data(), exist);
   if (strchr(opt, 'a')) {
      if (strlen(exist) == 0) {
         TString lib = fPlugin;
         if (!lib.BeginsWith("lib"))
            lib = "lib" + lib;
         char *path = gSystem->DynamicPathName(lib, kTRUE);
         if (path) Printf("  [Lib:  %s]", path);
         delete [] path;
      }
      Printf("  [Ctor: %s]", fCtor.Data());
      Printf("  [origin: %s]", fOrigin.Data());
   }
}


ClassImp(TPluginManager)

//______________________________________________________________________________
TPluginManager::~TPluginManager()
{
   // Clean up the plugin manager.

   delete fHandlers;
   delete fBasesLoaded;
}

//______________________________________________________________________________
void TPluginManager::LoadHandlersFromEnv(TEnv *env)
{
   // Load plugin handlers specified in config file, like:
   //    Plugin.TFile:       ^rfio:    TRFIOFile      RFIO  "TRFIOFile(...)"
   //    Plugin.TSQLServer:  ^mysql:   TMySQLServer   MySQL "TMySQLServer(...)"
   //    +Plugin.TSQLServer: ^pgsql:   TPgSQLServer   PgSQL "TPgSQLServer(...)"
   // The + allows the extension of an already defined resource (see TEnv).

   if (!env) return;

   TIter next(env->GetTable());
   TEnvRec *er;

   while ((er = (TEnvRec*) next())) {
      const char *s;
      if ((s = strstr(er->GetName(), "Plugin."))) {
         // use s, i.e. skip possible OS and application prefix to Plugin.
         // so that GetValue() takes properly care of returning the value
         // for the specified OS and/or application
         const char *val = env->GetValue(s, (const char*)0);
         if (val) {
            Int_t cnt = 0;
            char *v = StrDup(val);
            s += 7;
            while (1) {
               TString regexp = strtok(!cnt ? v : 0, "; ");
               if (regexp.IsNull()) break;
               TString clss   = strtok(0, "; ");
               if (clss.IsNull()) break;
               TString plugin = strtok(0, "; ");
               if (plugin.IsNull()) break;
               TString ctor = strtok(0, ";\"");
               if (!ctor.Contains("("))
                  ctor = strtok(0, ";\"");
               AddHandler(s, regexp, clss, plugin, ctor, "TEnv");
               cnt++;
            }
            delete [] v;
         }
      }
   }
}

//______________________________________________________________________________
void TPluginManager::LoadHandlerMacros(const char *path)
{
   // Load all plugin macros from the specified path/base directory.

   void *dirp = gSystem->OpenDirectory(path);
   if (dirp) {
      if (gDebug > 0)
         Info("LoadHandlerMacros", "%s", path);
      TSortedList macros;
      macros.SetOwner();
      const char *f1;
      while ((f1 = gSystem->GetDirEntry(dirp))) {
         TString f = f1;
         if (f[0] == 'P' && f.EndsWith(".C")) {
            const char *p = gSystem->ConcatFileName(path, f);
            if (!gSystem->AccessPathName(p, kReadPermission)) {
               macros.Add(new TObjString(p));
            }
            delete [] p;
         }
      }
      // load macros in alphabetical order
      TIter next(&macros);
      TObjString *s;
      while ((s = (TObjString*)next())) {
         if (gDebug > 1)
            Info("LoadHandlerMacros", "   plugin macro: %s", s->String().Data());
         Long_t res;
         if ((res = gROOT->Macro(s->String(), 0, kFALSE)) < 0) {
            Error("LoadHandlerMacros", "pluging macro %s returned %ld",
                  s->String().Data(), res);
         }
      }
   }
   gSystem->FreeDirectory(dirp);
}

//______________________________________________________________________________
void TPluginManager::LoadHandlersFromPluginDirs(const char *base)
{
   // Load plugin handlers specified via macros in a list of plugin
   // directories. The $ROOTSYS/etc/plugins is the default top plugin directory
   // specified in $ROOTSYS/etc/system.rootrc. The macros must have names
   // like <BaseClass>/PX0_<PluginClass>.C, e.g.:
   //    TFile/P10_TRFIOFile.C, TSQLServer/P20_TMySQLServer.C, etc.
   // to allow easy sorting and grouping. If the BaseClass is in a namespace
   // the directory must have the name NameSpace@@BaseClass as : is a reserved
   // pathname character on some operating systems. Macros not beginning with
   // 'P' and ending with ".C" are ignored. If base is specified only plugin
   // macros for that base class are loaded. The macros typically
   // should look like:
   //   void P10_TDCacheFile()
   //   {
   //       gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile",
   //          "DCache", "TDCacheFile(const char*,Option_t*,const char*,Int_t)");
   //   }
   // In general these macros should not cause side effects, by changing global
   // ROOT state via, e.g. gSystem calls, etc. However, in specific cases
   // this might be useful, e.g. adding a library search path, adding a specific
   // dependency, check on some OS or ROOT capability or downloading
   // of the plugin.

   //The destructor of TObjArray takes the gROOTMutex lock so we want to
   // delete the object after release the gCINTMutex lock
   TObjArray *dirs = nullptr;
   {
      R__LOCKGUARD2(gCINTMutex);
      if (!fBasesLoaded) {
         fBasesLoaded = new THashTable();
         fBasesLoaded->SetOwner();
      
         // make sure we have gPluginMgr availble in the plugin macros
         gInterpreter->InitializeDictionaries();
      }
      TString sbase = base;
      if (sbase != "") {
         sbase.ReplaceAll("::", "@@");
         if (fBasesLoaded->FindObject(sbase))
            return;
         fBasesLoaded->Add(new TObjString(sbase));
      }

      TPH__IsReadingDirs() = kTRUE;

      TString plugindirs = gEnv->GetValue("Root.PluginPath", (char*)0);
#ifdef WIN32
      dirs = plugindirs.Tokenize(";");
#else
      dirs = plugindirs.Tokenize(":");
#endif
      TString d;
      for (Int_t i = 0; i < dirs->GetEntriesFast(); i++) {
         d = ((TObjString*)dirs->At(i))->GetString();
         // check if directory already scanned
         Int_t skip = 0;
         for (Int_t j = 0; j < i; j++) {
            TString pd = ((TObjString*)dirs->At(j))->GetString();
            if (pd == d) {
               skip++;
               break;
            }
         }
         if (!skip) {
            if (sbase != "") {
               const char *p = gSystem->ConcatFileName(d, sbase);
               LoadHandlerMacros(p);
               delete [] p;
            } else {
               void *dirp = gSystem->OpenDirectory(d);
               if (dirp) {
                  if (gDebug > 0)
                     Info("LoadHandlersFromPluginDirs", "%s", d.Data());
                  const char *f1;
                  while ((f1 = gSystem->GetDirEntry(dirp))) {
                     TString f = f1;
                     const char *p = gSystem->ConcatFileName(d, f);
                     LoadHandlerMacros(p);
                     fBasesLoaded->Add(new TObjString(f));
                     delete [] p;
                  }
               }
               gSystem->FreeDirectory(dirp);
            }
         }
      }
      TPH__IsReadingDirs() = kFALSE;
   }
   delete dirs;
}

//______________________________________________________________________________
void TPluginManager::AddHandler(const char *base, const char *regexp,
                                const char *className, const char *pluginName,
                                const char *ctor, const char *origin)
{
   // Add plugin handler to the list of handlers. If there is already a
   // handler defined for the same base and regexp it will be replaced.

   {
      R__LOCKGUARD2(gPluginManagerMutex);
      if (!fHandlers) {
         fHandlers = new TList;
         fHandlers->SetOwner();
      }
   }
   // make sure there is no previous handler for the same case
   RemoveHandler(base, regexp);

   if (TPH__IsReadingDirs())
      origin = gInterpreter->GetCurrentMacroName();

   TPluginHandler *h = new TPluginHandler(base, regexp, className,
                                          pluginName, ctor, origin);
   {
      R__LOCKGUARD2(gPluginManagerMutex);
      fHandlers->Add(h);
   }
}

//______________________________________________________________________________
void TPluginManager::RemoveHandler(const char *base, const char *regexp)
{
   // Remove handler for the specified base class and the specified
   // regexp. If regexp=0 remove all handlers for the specified base.
   R__LOCKGUARD2(gPluginManagerMutex);
   if (!fHandlers) return;

   TIter next(fHandlers);
   TPluginHandler *h;

   while ((h = (TPluginHandler*) next())) {
      if (h->fBase == base) {
         if (!regexp || h->fRegexp == regexp) {
            fHandlers->Remove(h);
            delete h;
         }
      }
   }
}

//______________________________________________________________________________
TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri)
{
   // Returns the handler if there exists a handler for the specified URI.
   // The uri can be 0 in which case the first matching plugin handler
   // will be returned. Returns 0 in case handler is not found.

   LoadHandlersFromPluginDirs(base);

   R__LOCKGUARD2(gPluginManagerMutex);
   TIter next(fHandlers);
   TPluginHandler *h;

   while ((h = (TPluginHandler*) next())) {
      if (h->CanHandle(base, uri)) {
         if (gDebug > 0)
            Info("FindHandler", "found plugin for %s", h->GetClass());
         return h;
      }
   }

   if (gDebug > 2) {
      if (uri)
         Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri);
      else
         Info("FindHandler", "did not find plugin for class %s", base);
   }

   return 0;
}

//______________________________________________________________________________
void TPluginManager::Print(Option_t *opt) const
{
   // Print list of registered plugin handlers. If option is "a" print
   // also the ctor's that will be used.

   if (!fHandlers) return;

   TIter next(fHandlers);
   TPluginHandler *h;
   Int_t cnt = 0, cntmiss = 0;

   Printf("=====================================================================");
   Printf("Base                 Regexp        Class              Plugin");
   Printf("=====================================================================");

   while ((h = (TPluginHandler*) next())) {
      cnt++;
      h->Print(opt);
      if (h->CheckPlugin() == -1)
         cntmiss++;
   }
   Printf("=====================================================================");
   Printf("%d plugin handlers registered", cnt);
   Printf("[*] %d %s not available", cntmiss, cntmiss==1 ? "plugin" : "plugins");
   Printf("=====================================================================\n");
}

//______________________________________________________________________________
Int_t TPluginManager::WritePluginMacros(const char *dir, const char *plugin) const
{
   // Write in the specified directory the plugin macros. If plugin is specified
   // and if it is a base class all macros for that base will be written. If it
   // is a plugin class name, only that one macro will be written. If plugin
   // is 0 all macros are written. Returns -1 if dir does not exist, 0 otherwise.

   const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();

   if (!fHandlers) return 0;

   TString d;
   if (!dir || !dir[0])
      d = ".";
   else
      d = dir;

   if (gSystem->AccessPathName(d, kWritePermission)) {
      Error("WritePluginMacros", "cannot write in directory %s", d.Data());
      return -1;
   }

   TString base;
   Int_t   idx = 0;

   TObjLink *lnk = fHandlers->FirstLink();
   while (lnk) {
      TPluginHandler *h = (TPluginHandler *) lnk->GetObject();
      if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
         lnk = lnk->Next();
         continue;
      }
      if (base != h->fBase) {
         idx = 10;
         base = h->fBase;
      } else
         idx += 10;
      const char *dd = gSystem->ConcatFileName(d, h->fBase);
      TString sdd = dd;
      sdd.ReplaceAll("::", "@@");
      delete [] dd;
      if (gSystem->AccessPathName(sdd, kWritePermission)) {
         if (gSystem->MakeDirectory(sdd) < 0) {
            Error("WritePluginMacros", "cannot create directory %s", sdd.Data());
            return -1;
         }
      }
      TString fn;
      fn.Form("P%03d_%s.C", idx, h->fClass.Data());
      const char *fd = gSystem->ConcatFileName(sdd, fn);
      FILE *f = fopen(fd, "w");
      if (f) {
         fprintf(f, "void P%03d_%s()\n{\n", idx, h->fClass.Data());
         fprintf(f, "   gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
                 h->fBase.Data(), h->fRegexp.Data(), h->fClass.Data());
         fprintf(f, "      \"%s\", \"%s\");\n", h->fPlugin.Data(), h->fCtor.Data());
         
         // check for different regexps cases for the same base + class and
         // put them all in the same macro
         TObjLink *lnk2 = lnk->Next();
         while (lnk2) {
            TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
            if (h->fBase != h2->fBase || h->fClass != h2->fClass)
               break;
            
            fprintf(f, "   gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
                    h2->fBase.Data(), h2->fRegexp.Data(), h2->fClass.Data());
            fprintf(f, "      \"%s\", \"%s\");\n", h2->fPlugin.Data(), h2->fCtor.Data());
            
            lnk  = lnk2;
            lnk2 = lnk2->Next();
         }
         fprintf(f, "}\n");
         fclose(f);
      }
      delete [] fd;
      lnk = lnk->Next();
   }
   return 0;
}

//______________________________________________________________________________
Int_t TPluginManager::WritePluginRecords(const char *envFile, const char *plugin) const
{
   // Write in the specified environment config file the plugin records. If
   // plugin is specified and if it is a base class all records for that
   // base will be written. If it is a plugin class name, only that one
   // record will be written. If plugin is 0 all macros are written.
   // If envFile is 0 or "" the records are written to stdout.
   // Returns -1 if envFile cannot be created or opened, 0 otherwise.

   const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();

   if (!fHandlers) return 0;

   FILE *fd;
   if (!envFile || !envFile[0])
      fd = stdout;
   else
      fd = fopen(envFile, "w+");

   if (!fd) {
      Error("WritePluginRecords", "error opening file %s", envFile);
      return -1;
   }

   TString base, base2;
   Int_t   idx = 0;

   TObjLink *lnk = fHandlers->FirstLink();
   while (lnk) {
      TPluginHandler *h = (TPluginHandler *) lnk->GetObject();
      if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
         lnk = lnk->Next();
         continue;
      }
      if (base != h->fBase) {
         idx = 1;
         base = h->fBase;
         base2 = base;
         base2.ReplaceAll("::", "@@");
      } else
         idx += 1;

      if (idx == 1)
         fprintf(fd, "Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
                 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
      else
         fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
                 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());

      // check for different regexps cases for the same base + class and
      // put them all in the same macro
      TObjLink *lnk2 = lnk->Next();
      while (lnk2) {
         TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
         if (h->fBase != h2->fBase || h->fClass != h2->fClass)
            break;

         fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h2->fRegexp.Data(),
                 h2->fClass.Data(), h2->fPlugin.Data(), h2->fCtor.Data());

         lnk  = lnk2;
         lnk2 = lnk2->Next();
      }
      lnk = lnk->Next();
   }

   if (envFile && envFile[0])
      fclose(fd);

   return 0;
}
 TPluginManager.cxx:1
 TPluginManager.cxx:2
 TPluginManager.cxx:3
 TPluginManager.cxx:4
 TPluginManager.cxx:5
 TPluginManager.cxx:6
 TPluginManager.cxx:7
 TPluginManager.cxx:8
 TPluginManager.cxx:9
 TPluginManager.cxx:10
 TPluginManager.cxx:11
 TPluginManager.cxx:12
 TPluginManager.cxx:13
 TPluginManager.cxx:14
 TPluginManager.cxx:15
 TPluginManager.cxx:16
 TPluginManager.cxx:17
 TPluginManager.cxx:18
 TPluginManager.cxx:19
 TPluginManager.cxx:20
 TPluginManager.cxx:21
 TPluginManager.cxx:22
 TPluginManager.cxx:23
 TPluginManager.cxx:24
 TPluginManager.cxx:25
 TPluginManager.cxx:26
 TPluginManager.cxx:27
 TPluginManager.cxx:28
 TPluginManager.cxx:29
 TPluginManager.cxx:30
 TPluginManager.cxx:31
 TPluginManager.cxx:32
 TPluginManager.cxx:33
 TPluginManager.cxx:34
 TPluginManager.cxx:35
 TPluginManager.cxx:36
 TPluginManager.cxx:37
 TPluginManager.cxx:38
 TPluginManager.cxx:39
 TPluginManager.cxx:40
 TPluginManager.cxx:41
 TPluginManager.cxx:42
 TPluginManager.cxx:43
 TPluginManager.cxx:44
 TPluginManager.cxx:45
 TPluginManager.cxx:46
 TPluginManager.cxx:47
 TPluginManager.cxx:48
 TPluginManager.cxx:49
 TPluginManager.cxx:50
 TPluginManager.cxx:51
 TPluginManager.cxx:52
 TPluginManager.cxx:53
 TPluginManager.cxx:54
 TPluginManager.cxx:55
 TPluginManager.cxx:56
 TPluginManager.cxx:57
 TPluginManager.cxx:58
 TPluginManager.cxx:59
 TPluginManager.cxx:60
 TPluginManager.cxx:61
 TPluginManager.cxx:62
 TPluginManager.cxx:63
 TPluginManager.cxx:64
 TPluginManager.cxx:65
 TPluginManager.cxx:66
 TPluginManager.cxx:67
 TPluginManager.cxx:68
 TPluginManager.cxx:69
 TPluginManager.cxx:70
 TPluginManager.cxx:71
 TPluginManager.cxx:72
 TPluginManager.cxx:73
 TPluginManager.cxx:74
 TPluginManager.cxx:75
 TPluginManager.cxx:76
 TPluginManager.cxx:77
 TPluginManager.cxx:78
 TPluginManager.cxx:79
 TPluginManager.cxx:80
 TPluginManager.cxx:81
 TPluginManager.cxx:82
 TPluginManager.cxx:83
 TPluginManager.cxx:84
 TPluginManager.cxx:85
 TPluginManager.cxx:86
 TPluginManager.cxx:87
 TPluginManager.cxx:88
 TPluginManager.cxx:89
 TPluginManager.cxx:90
 TPluginManager.cxx:91
 TPluginManager.cxx:92
 TPluginManager.cxx:93
 TPluginManager.cxx:94
 TPluginManager.cxx:95
 TPluginManager.cxx:96
 TPluginManager.cxx:97
 TPluginManager.cxx:98
 TPluginManager.cxx:99
 TPluginManager.cxx:100
 TPluginManager.cxx:101
 TPluginManager.cxx:102
 TPluginManager.cxx:103
 TPluginManager.cxx:104
 TPluginManager.cxx:105
 TPluginManager.cxx:106
 TPluginManager.cxx:107
 TPluginManager.cxx:108
 TPluginManager.cxx:109
 TPluginManager.cxx:110
 TPluginManager.cxx:111
 TPluginManager.cxx:112
 TPluginManager.cxx:113
 TPluginManager.cxx:114
 TPluginManager.cxx:115
 TPluginManager.cxx:116
 TPluginManager.cxx:117
 TPluginManager.cxx:118
 TPluginManager.cxx:119
 TPluginManager.cxx:120
 TPluginManager.cxx:121
 TPluginManager.cxx:122
 TPluginManager.cxx:123
 TPluginManager.cxx:124
 TPluginManager.cxx:125
 TPluginManager.cxx:126
 TPluginManager.cxx:127
 TPluginManager.cxx:128
 TPluginManager.cxx:129
 TPluginManager.cxx:130
 TPluginManager.cxx:131
 TPluginManager.cxx:132
 TPluginManager.cxx:133
 TPluginManager.cxx:134
 TPluginManager.cxx:135
 TPluginManager.cxx:136
 TPluginManager.cxx:137
 TPluginManager.cxx:138
 TPluginManager.cxx:139
 TPluginManager.cxx:140
 TPluginManager.cxx:141
 TPluginManager.cxx:142
 TPluginManager.cxx:143
 TPluginManager.cxx:144
 TPluginManager.cxx:145
 TPluginManager.cxx:146
 TPluginManager.cxx:147
 TPluginManager.cxx:148
 TPluginManager.cxx:149
 TPluginManager.cxx:150
 TPluginManager.cxx:151
 TPluginManager.cxx:152
 TPluginManager.cxx:153
 TPluginManager.cxx:154
 TPluginManager.cxx:155
 TPluginManager.cxx:156
 TPluginManager.cxx:157
 TPluginManager.cxx:158
 TPluginManager.cxx:159
 TPluginManager.cxx:160
 TPluginManager.cxx:161
 TPluginManager.cxx:162
 TPluginManager.cxx:163
 TPluginManager.cxx:164
 TPluginManager.cxx:165
 TPluginManager.cxx:166
 TPluginManager.cxx:167
 TPluginManager.cxx:168
 TPluginManager.cxx:169
 TPluginManager.cxx:170
 TPluginManager.cxx:171
 TPluginManager.cxx:172
 TPluginManager.cxx:173
 TPluginManager.cxx:174
 TPluginManager.cxx:175
 TPluginManager.cxx:176
 TPluginManager.cxx:177
 TPluginManager.cxx:178
 TPluginManager.cxx:179
 TPluginManager.cxx:180
 TPluginManager.cxx:181
 TPluginManager.cxx:182
 TPluginManager.cxx:183
 TPluginManager.cxx:184
 TPluginManager.cxx:185
 TPluginManager.cxx:186
 TPluginManager.cxx:187
 TPluginManager.cxx:188
 TPluginManager.cxx:189
 TPluginManager.cxx:190
 TPluginManager.cxx:191
 TPluginManager.cxx:192
 TPluginManager.cxx:193
 TPluginManager.cxx:194
 TPluginManager.cxx:195
 TPluginManager.cxx:196
 TPluginManager.cxx:197
 TPluginManager.cxx:198
 TPluginManager.cxx:199
 TPluginManager.cxx:200
 TPluginManager.cxx:201
 TPluginManager.cxx:202
 TPluginManager.cxx:203
 TPluginManager.cxx:204
 TPluginManager.cxx:205
 TPluginManager.cxx:206
 TPluginManager.cxx:207
 TPluginManager.cxx:208
 TPluginManager.cxx:209
 TPluginManager.cxx:210
 TPluginManager.cxx:211
 TPluginManager.cxx:212
 TPluginManager.cxx:213
 TPluginManager.cxx:214
 TPluginManager.cxx:215
 TPluginManager.cxx:216
 TPluginManager.cxx:217
 TPluginManager.cxx:218
 TPluginManager.cxx:219
 TPluginManager.cxx:220
 TPluginManager.cxx:221
 TPluginManager.cxx:222
 TPluginManager.cxx:223
 TPluginManager.cxx:224
 TPluginManager.cxx:225
 TPluginManager.cxx:226
 TPluginManager.cxx:227
 TPluginManager.cxx:228
 TPluginManager.cxx:229
 TPluginManager.cxx:230
 TPluginManager.cxx:231
 TPluginManager.cxx:232
 TPluginManager.cxx:233
 TPluginManager.cxx:234
 TPluginManager.cxx:235
 TPluginManager.cxx:236
 TPluginManager.cxx:237
 TPluginManager.cxx:238
 TPluginManager.cxx:239
 TPluginManager.cxx:240
 TPluginManager.cxx:241
 TPluginManager.cxx:242
 TPluginManager.cxx:243
 TPluginManager.cxx:244
 TPluginManager.cxx:245
 TPluginManager.cxx:246
 TPluginManager.cxx:247
 TPluginManager.cxx:248
 TPluginManager.cxx:249
 TPluginManager.cxx:250
 TPluginManager.cxx:251
 TPluginManager.cxx:252
 TPluginManager.cxx:253
 TPluginManager.cxx:254
 TPluginManager.cxx:255
 TPluginManager.cxx:256
 TPluginManager.cxx:257
 TPluginManager.cxx:258
 TPluginManager.cxx:259
 TPluginManager.cxx:260
 TPluginManager.cxx:261
 TPluginManager.cxx:262
 TPluginManager.cxx:263
 TPluginManager.cxx:264
 TPluginManager.cxx:265
 TPluginManager.cxx:266
 TPluginManager.cxx:267
 TPluginManager.cxx:268
 TPluginManager.cxx:269
 TPluginManager.cxx:270
 TPluginManager.cxx:271
 TPluginManager.cxx:272
 TPluginManager.cxx:273
 TPluginManager.cxx:274
 TPluginManager.cxx:275
 TPluginManager.cxx:276
 TPluginManager.cxx:277
 TPluginManager.cxx:278
 TPluginManager.cxx:279
 TPluginManager.cxx:280
 TPluginManager.cxx:281
 TPluginManager.cxx:282
 TPluginManager.cxx:283
 TPluginManager.cxx:284
 TPluginManager.cxx:285
 TPluginManager.cxx:286
 TPluginManager.cxx:287
 TPluginManager.cxx:288
 TPluginManager.cxx:289
 TPluginManager.cxx:290
 TPluginManager.cxx:291
 TPluginManager.cxx:292
 TPluginManager.cxx:293
 TPluginManager.cxx:294
 TPluginManager.cxx:295
 TPluginManager.cxx:296
 TPluginManager.cxx:297
 TPluginManager.cxx:298
 TPluginManager.cxx:299
 TPluginManager.cxx:300
 TPluginManager.cxx:301
 TPluginManager.cxx:302
 TPluginManager.cxx:303
 TPluginManager.cxx:304
 TPluginManager.cxx:305
 TPluginManager.cxx:306
 TPluginManager.cxx:307
 TPluginManager.cxx:308
 TPluginManager.cxx:309
 TPluginManager.cxx:310
 TPluginManager.cxx:311
 TPluginManager.cxx:312
 TPluginManager.cxx:313
 TPluginManager.cxx:314
 TPluginManager.cxx:315
 TPluginManager.cxx:316
 TPluginManager.cxx:317
 TPluginManager.cxx:318
 TPluginManager.cxx:319
 TPluginManager.cxx:320
 TPluginManager.cxx:321
 TPluginManager.cxx:322
 TPluginManager.cxx:323
 TPluginManager.cxx:324
 TPluginManager.cxx:325
 TPluginManager.cxx:326
 TPluginManager.cxx:327
 TPluginManager.cxx:328
 TPluginManager.cxx:329
 TPluginManager.cxx:330
 TPluginManager.cxx:331
 TPluginManager.cxx:332
 TPluginManager.cxx:333
 TPluginManager.cxx:334
 TPluginManager.cxx:335
 TPluginManager.cxx:336
 TPluginManager.cxx:337
 TPluginManager.cxx:338
 TPluginManager.cxx:339
 TPluginManager.cxx:340
 TPluginManager.cxx:341
 TPluginManager.cxx:342
 TPluginManager.cxx:343
 TPluginManager.cxx:344
 TPluginManager.cxx:345
 TPluginManager.cxx:346
 TPluginManager.cxx:347
 TPluginManager.cxx:348
 TPluginManager.cxx:349
 TPluginManager.cxx:350
 TPluginManager.cxx:351
 TPluginManager.cxx:352
 TPluginManager.cxx:353
 TPluginManager.cxx:354
 TPluginManager.cxx:355
 TPluginManager.cxx:356
 TPluginManager.cxx:357
 TPluginManager.cxx:358
 TPluginManager.cxx:359
 TPluginManager.cxx:360
 TPluginManager.cxx:361
 TPluginManager.cxx:362
 TPluginManager.cxx:363
 TPluginManager.cxx:364
 TPluginManager.cxx:365
 TPluginManager.cxx:366
 TPluginManager.cxx:367
 TPluginManager.cxx:368
 TPluginManager.cxx:369
 TPluginManager.cxx:370
 TPluginManager.cxx:371
 TPluginManager.cxx:372
 TPluginManager.cxx:373
 TPluginManager.cxx:374
 TPluginManager.cxx:375
 TPluginManager.cxx:376
 TPluginManager.cxx:377
 TPluginManager.cxx:378
 TPluginManager.cxx:379
 TPluginManager.cxx:380
 TPluginManager.cxx:381
 TPluginManager.cxx:382
 TPluginManager.cxx:383
 TPluginManager.cxx:384
 TPluginManager.cxx:385
 TPluginManager.cxx:386
 TPluginManager.cxx:387
 TPluginManager.cxx:388
 TPluginManager.cxx:389
 TPluginManager.cxx:390
 TPluginManager.cxx:391
 TPluginManager.cxx:392
 TPluginManager.cxx:393
 TPluginManager.cxx:394
 TPluginManager.cxx:395
 TPluginManager.cxx:396
 TPluginManager.cxx:397
 TPluginManager.cxx:398
 TPluginManager.cxx:399
 TPluginManager.cxx:400
 TPluginManager.cxx:401
 TPluginManager.cxx:402
 TPluginManager.cxx:403
 TPluginManager.cxx:404
 TPluginManager.cxx:405
 TPluginManager.cxx:406
 TPluginManager.cxx:407
 TPluginManager.cxx:408
 TPluginManager.cxx:409
 TPluginManager.cxx:410
 TPluginManager.cxx:411
 TPluginManager.cxx:412
 TPluginManager.cxx:413
 TPluginManager.cxx:414
 TPluginManager.cxx:415
 TPluginManager.cxx:416
 TPluginManager.cxx:417
 TPluginManager.cxx:418
 TPluginManager.cxx:419
 TPluginManager.cxx:420
 TPluginManager.cxx:421
 TPluginManager.cxx:422
 TPluginManager.cxx:423
 TPluginManager.cxx:424
 TPluginManager.cxx:425
 TPluginManager.cxx:426
 TPluginManager.cxx:427
 TPluginManager.cxx:428
 TPluginManager.cxx:429
 TPluginManager.cxx:430
 TPluginManager.cxx:431
 TPluginManager.cxx:432
 TPluginManager.cxx:433
 TPluginManager.cxx:434
 TPluginManager.cxx:435
 TPluginManager.cxx:436
 TPluginManager.cxx:437
 TPluginManager.cxx:438
 TPluginManager.cxx:439
 TPluginManager.cxx:440
 TPluginManager.cxx:441
 TPluginManager.cxx:442
 TPluginManager.cxx:443
 TPluginManager.cxx:444
 TPluginManager.cxx:445
 TPluginManager.cxx:446
 TPluginManager.cxx:447
 TPluginManager.cxx:448
 TPluginManager.cxx:449
 TPluginManager.cxx:450
 TPluginManager.cxx:451
 TPluginManager.cxx:452
 TPluginManager.cxx:453
 TPluginManager.cxx:454
 TPluginManager.cxx:455
 TPluginManager.cxx:456
 TPluginManager.cxx:457
 TPluginManager.cxx:458
 TPluginManager.cxx:459
 TPluginManager.cxx:460
 TPluginManager.cxx:461
 TPluginManager.cxx:462
 TPluginManager.cxx:463
 TPluginManager.cxx:464
 TPluginManager.cxx:465
 TPluginManager.cxx:466
 TPluginManager.cxx:467
 TPluginManager.cxx:468
 TPluginManager.cxx:469
 TPluginManager.cxx:470
 TPluginManager.cxx:471
 TPluginManager.cxx:472
 TPluginManager.cxx:473
 TPluginManager.cxx:474
 TPluginManager.cxx:475
 TPluginManager.cxx:476
 TPluginManager.cxx:477
 TPluginManager.cxx:478
 TPluginManager.cxx:479
 TPluginManager.cxx:480
 TPluginManager.cxx:481
 TPluginManager.cxx:482
 TPluginManager.cxx:483
 TPluginManager.cxx:484
 TPluginManager.cxx:485
 TPluginManager.cxx:486
 TPluginManager.cxx:487
 TPluginManager.cxx:488
 TPluginManager.cxx:489
 TPluginManager.cxx:490
 TPluginManager.cxx:491
 TPluginManager.cxx:492
 TPluginManager.cxx:493
 TPluginManager.cxx:494
 TPluginManager.cxx:495
 TPluginManager.cxx:496
 TPluginManager.cxx:497
 TPluginManager.cxx:498
 TPluginManager.cxx:499
 TPluginManager.cxx:500
 TPluginManager.cxx:501
 TPluginManager.cxx:502
 TPluginManager.cxx:503
 TPluginManager.cxx:504
 TPluginManager.cxx:505
 TPluginManager.cxx:506
 TPluginManager.cxx:507
 TPluginManager.cxx:508
 TPluginManager.cxx:509
 TPluginManager.cxx:510
 TPluginManager.cxx:511
 TPluginManager.cxx:512
 TPluginManager.cxx:513
 TPluginManager.cxx:514
 TPluginManager.cxx:515
 TPluginManager.cxx:516
 TPluginManager.cxx:517
 TPluginManager.cxx:518
 TPluginManager.cxx:519
 TPluginManager.cxx:520
 TPluginManager.cxx:521
 TPluginManager.cxx:522
 TPluginManager.cxx:523
 TPluginManager.cxx:524
 TPluginManager.cxx:525
 TPluginManager.cxx:526
 TPluginManager.cxx:527
 TPluginManager.cxx:528
 TPluginManager.cxx:529
 TPluginManager.cxx:530
 TPluginManager.cxx:531
 TPluginManager.cxx:532
 TPluginManager.cxx:533
 TPluginManager.cxx:534
 TPluginManager.cxx:535
 TPluginManager.cxx:536
 TPluginManager.cxx:537
 TPluginManager.cxx:538
 TPluginManager.cxx:539
 TPluginManager.cxx:540
 TPluginManager.cxx:541
 TPluginManager.cxx:542
 TPluginManager.cxx:543
 TPluginManager.cxx:544
 TPluginManager.cxx:545
 TPluginManager.cxx:546
 TPluginManager.cxx:547
 TPluginManager.cxx:548
 TPluginManager.cxx:549
 TPluginManager.cxx:550
 TPluginManager.cxx:551
 TPluginManager.cxx:552
 TPluginManager.cxx:553
 TPluginManager.cxx:554
 TPluginManager.cxx:555
 TPluginManager.cxx:556
 TPluginManager.cxx:557
 TPluginManager.cxx:558
 TPluginManager.cxx:559
 TPluginManager.cxx:560
 TPluginManager.cxx:561
 TPluginManager.cxx:562
 TPluginManager.cxx:563
 TPluginManager.cxx:564
 TPluginManager.cxx:565
 TPluginManager.cxx:566
 TPluginManager.cxx:567
 TPluginManager.cxx:568
 TPluginManager.cxx:569
 TPluginManager.cxx:570
 TPluginManager.cxx:571
 TPluginManager.cxx:572
 TPluginManager.cxx:573
 TPluginManager.cxx:574
 TPluginManager.cxx:575
 TPluginManager.cxx:576
 TPluginManager.cxx:577
 TPluginManager.cxx:578
 TPluginManager.cxx:579
 TPluginManager.cxx:580
 TPluginManager.cxx:581
 TPluginManager.cxx:582
 TPluginManager.cxx:583
 TPluginManager.cxx:584
 TPluginManager.cxx:585
 TPluginManager.cxx:586
 TPluginManager.cxx:587
 TPluginManager.cxx:588
 TPluginManager.cxx:589
 TPluginManager.cxx:590
 TPluginManager.cxx:591
 TPluginManager.cxx:592
 TPluginManager.cxx:593
 TPluginManager.cxx:594
 TPluginManager.cxx:595
 TPluginManager.cxx:596
 TPluginManager.cxx:597
 TPluginManager.cxx:598
 TPluginManager.cxx:599
 TPluginManager.cxx:600
 TPluginManager.cxx:601
 TPluginManager.cxx:602
 TPluginManager.cxx:603
 TPluginManager.cxx:604
 TPluginManager.cxx:605
 TPluginManager.cxx:606
 TPluginManager.cxx:607
 TPluginManager.cxx:608
 TPluginManager.cxx:609
 TPluginManager.cxx:610
 TPluginManager.cxx:611
 TPluginManager.cxx:612
 TPluginManager.cxx:613
 TPluginManager.cxx:614
 TPluginManager.cxx:615
 TPluginManager.cxx:616
 TPluginManager.cxx:617
 TPluginManager.cxx:618
 TPluginManager.cxx:619
 TPluginManager.cxx:620
 TPluginManager.cxx:621
 TPluginManager.cxx:622
 TPluginManager.cxx:623
 TPluginManager.cxx:624
 TPluginManager.cxx:625
 TPluginManager.cxx:626
 TPluginManager.cxx:627
 TPluginManager.cxx:628
 TPluginManager.cxx:629
 TPluginManager.cxx:630
 TPluginManager.cxx:631
 TPluginManager.cxx:632
 TPluginManager.cxx:633
 TPluginManager.cxx:634
 TPluginManager.cxx:635
 TPluginManager.cxx:636
 TPluginManager.cxx:637
 TPluginManager.cxx:638
 TPluginManager.cxx:639
 TPluginManager.cxx:640
 TPluginManager.cxx:641
 TPluginManager.cxx:642
 TPluginManager.cxx:643
 TPluginManager.cxx:644
 TPluginManager.cxx:645
 TPluginManager.cxx:646
 TPluginManager.cxx:647
 TPluginManager.cxx:648
 TPluginManager.cxx:649
 TPluginManager.cxx:650
 TPluginManager.cxx:651
 TPluginManager.cxx:652
 TPluginManager.cxx:653
 TPluginManager.cxx:654
 TPluginManager.cxx:655
 TPluginManager.cxx:656
 TPluginManager.cxx:657
 TPluginManager.cxx:658
 TPluginManager.cxx:659
 TPluginManager.cxx:660
 TPluginManager.cxx:661
 TPluginManager.cxx:662
 TPluginManager.cxx:663
 TPluginManager.cxx:664
 TPluginManager.cxx:665
 TPluginManager.cxx:666
 TPluginManager.cxx:667
 TPluginManager.cxx:668
 TPluginManager.cxx:669
 TPluginManager.cxx:670
 TPluginManager.cxx:671
 TPluginManager.cxx:672
 TPluginManager.cxx:673
 TPluginManager.cxx:674
 TPluginManager.cxx:675
 TPluginManager.cxx:676
 TPluginManager.cxx:677
 TPluginManager.cxx:678
 TPluginManager.cxx:679
 TPluginManager.cxx:680
 TPluginManager.cxx:681
 TPluginManager.cxx:682
 TPluginManager.cxx:683
 TPluginManager.cxx:684
 TPluginManager.cxx:685
 TPluginManager.cxx:686
 TPluginManager.cxx:687
 TPluginManager.cxx:688
 TPluginManager.cxx:689
 TPluginManager.cxx:690
 TPluginManager.cxx:691
 TPluginManager.cxx:692
 TPluginManager.cxx:693
 TPluginManager.cxx:694
 TPluginManager.cxx:695
 TPluginManager.cxx:696
 TPluginManager.cxx:697
 TPluginManager.cxx:698
 TPluginManager.cxx:699
 TPluginManager.cxx:700
 TPluginManager.cxx:701
 TPluginManager.cxx:702
 TPluginManager.cxx:703
 TPluginManager.cxx:704
 TPluginManager.cxx:705
 TPluginManager.cxx:706
 TPluginManager.cxx:707
 TPluginManager.cxx:708
 TPluginManager.cxx:709
 TPluginManager.cxx:710
 TPluginManager.cxx:711
 TPluginManager.cxx:712
 TPluginManager.cxx:713
 TPluginManager.cxx:714
 TPluginManager.cxx:715
 TPluginManager.cxx:716
 TPluginManager.cxx:717
 TPluginManager.cxx:718
 TPluginManager.cxx:719
 TPluginManager.cxx:720
 TPluginManager.cxx:721
 TPluginManager.cxx:722
 TPluginManager.cxx:723
 TPluginManager.cxx:724
 TPluginManager.cxx:725
 TPluginManager.cxx:726
 TPluginManager.cxx:727
 TPluginManager.cxx:728
 TPluginManager.cxx:729
 TPluginManager.cxx:730
 TPluginManager.cxx:731
 TPluginManager.cxx:732
 TPluginManager.cxx:733
 TPluginManager.cxx:734
 TPluginManager.cxx:735
 TPluginManager.cxx:736
 TPluginManager.cxx:737
 TPluginManager.cxx:738
 TPluginManager.cxx:739
 TPluginManager.cxx:740
 TPluginManager.cxx:741
 TPluginManager.cxx:742
 TPluginManager.cxx:743
 TPluginManager.cxx:744
 TPluginManager.cxx:745
 TPluginManager.cxx:746
 TPluginManager.cxx:747
 TPluginManager.cxx:748
 TPluginManager.cxx:749
 TPluginManager.cxx:750
 TPluginManager.cxx:751
 TPluginManager.cxx:752
 TPluginManager.cxx:753
 TPluginManager.cxx:754
 TPluginManager.cxx:755
 TPluginManager.cxx:756
 TPluginManager.cxx:757
 TPluginManager.cxx:758
 TPluginManager.cxx:759
 TPluginManager.cxx:760
 TPluginManager.cxx:761
 TPluginManager.cxx:762
 TPluginManager.cxx:763
 TPluginManager.cxx:764
 TPluginManager.cxx:765
 TPluginManager.cxx:766
 TPluginManager.cxx:767
 TPluginManager.cxx:768
 TPluginManager.cxx:769
 TPluginManager.cxx:770
 TPluginManager.cxx:771
 TPluginManager.cxx:772
 TPluginManager.cxx:773
 TPluginManager.cxx:774
 TPluginManager.cxx:775
 TPluginManager.cxx:776
 TPluginManager.cxx:777
 TPluginManager.cxx:778
 TPluginManager.cxx:779
 TPluginManager.cxx:780
 TPluginManager.cxx:781
 TPluginManager.cxx:782
 TPluginManager.cxx:783
 TPluginManager.cxx:784
 TPluginManager.cxx:785
 TPluginManager.cxx:786
 TPluginManager.cxx:787
 TPluginManager.cxx:788
 TPluginManager.cxx:789
 TPluginManager.cxx:790
 TPluginManager.cxx:791
 TPluginManager.cxx:792
 TPluginManager.cxx:793
 TPluginManager.cxx:794
 TPluginManager.cxx:795
 TPluginManager.cxx:796
 TPluginManager.cxx:797
 TPluginManager.cxx:798
 TPluginManager.cxx:799
 TPluginManager.cxx:800
 TPluginManager.cxx:801
 TPluginManager.cxx:802
 TPluginManager.cxx:803
 TPluginManager.cxx:804
 TPluginManager.cxx:805
 TPluginManager.cxx:806
 TPluginManager.cxx:807
 TPluginManager.cxx:808
 TPluginManager.cxx:809
 TPluginManager.cxx:810