// $Id: TModule.cxx.html,v 1.3 2002/04/17 23:18:29 fine Exp $
//
//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TModule is a  base class to define the member of the chain           //
// to perform some complex action                                       //
//                                                                      //
// ("Root" service within Athena framework, for example)                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>

#include <TSystem.h>
#include <TClass.h>
#include <TROOT.h>
#include <THtml.h>
#include <TH1.h>

#include <TChain.h>
#include <TTree.h>
#include <TList.h>
#include <TClonesArray.h>
#include <TBrowser.h>

#include "RootKernel/TTable.h"

#include "TModule.h"
#include "TMemoryInfo.h"

TModule *TModule::fgStChain = 0;
TModule *TModule::fgFailedModule = 0;
Int_t    TModule::fgTallyModule[kFatal+1] = {0,0,0,0,0};
Int_t MaxWarnings = 26;

ClassImp(TModule)

static void doPs(const char *who,const char *where);

//_____________________________________________________________________________
 TModule::TModule(const char *name,const char *):TDataSet(name,".maker"),fActive(kTRUE)
{
  // Steering TDataSet to control the program flow control
  // and pass data between program modules the standard way
   SetMode();
   m_DebugLevel=0;
   m_MakeReturn=0;
   m_Inputs = 0;
   if (!fgStChain) {	// it is first maker, it is chain
     fgStChain = this;
     AddData(0,".make");
   } else         {	// add this maker to chain  
     fgStChain->AddData(this,".make");
   }
   m_DataSet  = new TObjectSet(".data") ;Add(m_DataSet);
   m_ConstSet = new TObjectSet(".const");Add(m_ConstSet);
   m_GarbSet  = new TObjectSet(".garb" );Add(m_GarbSet);
   m_Inputs   = new TObjectSet(".aliases" );Add(m_Inputs);
   m_Runco  = new TObjectSet(".runco" );Add(m_Runco);
   AddHist(0); m_Histograms = GetHistList();
   ::doPs(GetName(),"constructor");
   m_Timer.Stop();
}

//_____________________________________________________________________________
 void TModule::AddModule(TModule *mk)
{
  TDataSet *dotmk = Find(".make");
  if (!dotmk) dotmk = new TDataSet(".make",this);
  mk->Shunt(dotmk);
}
//_____________________________________________________________________________
 TModule::~TModule()
{
if (fgStChain == this) fgStChain = 0;
}
//______________________________________________________________________________
 void TModule::SetNumber(Int_t number)
{
 TModule *par = GetParentModule();
 if (par) par->SetNumber(number);
 m_Number = number;
#ifdef RUN
 SetIventNumber(number);
#endif
}
//______________________________________________________________________________
 Int_t TModule::GetNumber() const
{
 TModule *par = GetParentModule();
 if (par) return par->GetNumber();
 return m_Number;
}
//______________________________________________________________________________
 TModule *TModule::GetParentModule() const
{ 
  TDataSet *par = GetParent(); if (!par) return 0;
  return (TModule*)par->GetParent();
}
//______________________________________________________________________________
 TModule *TModule::GetModule(const char *mkname) 
{ 
  TString path(".make/"); path+=mkname;
  return (TModule*)GetDataSet((const char*)path);
}
//______________________________________________________________________________
 TObject *TModule::GetDirObj(const char *dir) const
{
  TObjectSet *h = (TObjectSet*)Find(dir);
  if (!h) return 0;
  return h->GetObject();
}
//______________________________________________________________________________
 void TModule::SetDirObj(TObject *obj,const char *dir)
{ 
  TObjectSet *set = (TObjectSet *)Find(dir);
  if (!set) { // No dir, make it
    set = new TObjectSet(dir); Add(set);}
  set->SetObject(obj);
}
//______________________________________________________________________________
 TObjectSet *TModule::AddObj(TObject *obj,const char *dir)
{ 
  assert (dir[0]=='.');
  TObjectSet *set = (TObjectSet*)Find(dir);
  if (!set) { // No dir, make it
    set = new TObjectSet(dir); Add(set);}

  TList *list = (TList *)set->GetObject();
  if (!list) {// No list, make it
    list = new TList();
    set->SetObject((TObject*)list);}
  if (!obj) return set;
  if(!list->FindObject(obj)) list->Add(obj);
  return set;
}
//______________________________________________________________________________
  void TModule::AddHist(TH1 *h,const char *dir)
{  
  if (dir){/*unused*/}
  if (!h) {AddObj(0,".hist");return;}
  if (h->InheritsFrom(TH1::Class())) h->SetDirectory(0);
  AddObj(h,".hist");
}    
//______________________________________________________________________________
  void TModule::AddRunco (double par,const char* name,const char* comment)
{
   assert (name && name && comment[0]); 

   TDataSet *dp = new TDataSet(name,m_Runco);
   TString ts("  // "); ts += comment;
   char buf[40];
   sprintf(buf,"%f",par);
   ts.Replace(0,0,buf);
   dp->SetTitle((const char*)ts);
}
//______________________________________________________________________________
 TDataSet *TModule::AddData(TDataSet *ds, const char* dir)
{ 
  assert (dir); assert(dir[0]=='.');
  TDataSet *set = Find(dir);
  if (!set) { // No dir, make it
    set = new TObjectSet(dir); Add(set);}
  if (!ds) return set;
  TList *tl = set->GetList();
  if (!tl || !tl->FindObject(ds)) set->Add(ds);
  return set;
}
//______________________________________________________________________________
 TDataSet  *TModule::GetData(const char *name, const char* dir) const
{ 
  TDataSet *set = Find(dir);
  if (!set) return 0;
  return set->Find(name);
}
//______________________________________________________________________________
 void TModule::AddAlias(const char* log, const char* act,const char* dir)
{
  TDataSet *ali = new TDataSet(log); 
  ali->SetTitle(act);
  AddData(ali,dir);
}
//______________________________________________________________________________
 void TModule::SetAlias(const char* log, const char* act,const char* dir)
{ 
  TDataSet *ali = GetData(log,dir);
  if (ali) {
    if (!strcmp(act,ali->GetTitle())) return;
  } else {
    ali = new TDataSet(log); AddData(ali,dir);
  }
  ali->SetTitle(act);

  if (GetDebug()) 
    printf("<%s(%s)::SetAlias> %s = %sn",ClassName(),GetName(),log,act);
}
//______________________________________________________________________________
 void TModule::SetOutput(const char* log,TDataSet *ds)
{
  int idx;
  const char* logname = log;
  if (!logname || !logname[0]) logname = ds->GetName();
  TString act = ds->Path();
  while ((idx=act.Index(".make/"))>=0) act.Replace(0,idx+6,"");  
  SetOutput(logname,act); 
}

//______________________________________________________________________________
 void TModule::SetOutputAll(TDataSet *ds, Int_t level)
{
  TDataSet *set;
  TDataSetIter next(ds,level);
  while ((set = next())) SetOutput(set);
}

//______________________________________________________________________________
 TList *TModule::GetMakeList() const
{ TDataSet *ds = Find(".make");
  if (!ds) return 0;
  return ds->GetList();
}
//______________________________________________________________________________
 TString TModule::GetAlias(const char* log,const char* dir) const
{
  TString act;
  int nspn = strcspn(log," /");
  act.Prepend(log,nspn);
  TDataSet *in = GetData(act,dir);
  act ="";
  if (in) {act = in->GetTitle(); act += log+nspn;}
  return act;
}
//______________________________________________________________________________
 TDataSet *TModule::GetDataSet(const char* logInput,
                                const TModule *uppMk,
                                const TModule *dowMk) const
{
TDataSetIter nextMk(0);
TString actInput,findString,tmp;
TDataSet *dataset,*dir;
TModule    *parent,*mk;
int icol,islas;
  
  actInput = GetInput(logInput);
  if (actInput.IsNull()) actInput = logInput;
  

//		Direct try
  dataset = 0;
  if (actInput.Contains("."))  dataset = Find(actInput);
  if (dataset) goto FOUND;
  
  if (actInput==GetName()) dataset = m_DataSet;
  if (dataset) goto FOUND;

//		Not so evident, do some editing
  
  
  icol = actInput.Index(":");
  if (icol>=0) {//there is maker name is hidden
    tmp = actInput; 
    tmp.Replace(0,0,".make/"); icol +=6;
    tmp.Replace(icol,1,"/.data/");
    dataset = Find((const char*)tmp);  		// .make/MAKER/.data/...
    if (dataset) goto FOUND;
    dataset = Find((const char*)tmp+6);		//       MAKER/.data/...
    if (dataset) goto FOUND;
    tmp.Replace(icol,7,"/.const/");
    dataset = Find((const char*)tmp);		// .make/MAKER/.const/...
    if (dataset) goto FOUND;
    dataset = Find((const char*)tmp+6);		//       MAKER/.const/...
    if (dataset) goto FOUND;
    goto DOWN;
  }

  assert(m_DataSet);
  islas = actInput.Index("/");
  if (islas>0) {
    tmp.Replace(0,999,actInput,islas);
    if (tmp == GetName()) { // 
      tmp = actInput;
      tmp.Replace(0,islas+1,"");
      dataset = m_DataSet->Find(tmp);
      if (dataset) goto FOUND;
      dataset = m_ConstSet->Find(tmp);
      if (dataset) goto FOUND;
    }
  }

  dataset = m_DataSet->Find(actInput);
  if (dataset) goto FOUND;
  dataset = m_ConstSet->Find(actInput);
  if (dataset) goto FOUND;


//	Try to search DOWN
DOWN: if (!(dir = Find(".make"))) goto UP;

  nextMk.Reset(dir);
  while ((mk = (TModule*)nextMk()))
  {
    if (mk==dowMk) continue;
    dataset = mk->GetDataSet(actInput,this,0);
    if (dataset) goto FOUND;
  }

//     Try to search UP
UP: if (uppMk) return 0;

  parent = GetModule(this); if (!parent) goto NOTFOUND;
  dataset = parent->GetDataSet(actInput,0,this);
  if (dataset) goto FOUND;

//		Not FOUND
NOTFOUND:
  if (!dowMk && GetDebug()) //Print Warning message
    if ((MaxWarnings--) > 0) Warning("GetDataSet"," "%s" Not Found ***n",(const char*)actInput);
  return 0;

//		DataSet FOUND
FOUND: if (uppMk || dowMk) 	return dataset;
       if (GetDebug()<2) 	return dataset;
  printf("Remark: <%s::%s> DataSet %s FOUND in %sn"
  ,ClassName(),"GetDataSet",logInput,(const char*)dataset->Path());

  return dataset;

}
//______________________________________________________________________________
 TDataSet *TModule::GetDataBase(const char* logInput)
{
  TDataSet *ds=0;
  TModule *mk;
  //loop over makers
  TModuleIter mkiter(this);
  while ((mk = mkiter.NextModule())) {
    if (  (ds = mk->UpdateDB(logInput)) ) break;
  }
  return ds;
}
//_____________________________________________________________________________
 TDataSet *TModule::UpdateDB(const char* logInput)
{   return 0; }

#if 0
//______________________________________________________________________________
Int_t   TModule::GetValidity(const TTable *tb, TDatime *val) const
{
   TModule *mk = GetModule(tb);
   if (!mk) 					return 10;
   if (!mk->IsDbProvider())	return 11;
   return mk->GetValidity(tb,val);
}
 #endif 

//_____________________________________________________________________________
 void TModule::Clear(Option_t *option)
{
  m_MakeReturn = 0;
  if(option){};
  if (m_DataSet) m_DataSet->Delete();
//    Reset lists of event objects
   
   TIter next(GetMakeList());
   TModule *maker;
   while ((maker = (TModule*)next())) {
      maker->StartTimer();
      maker->Clear(option);
      maker->StopTimer();
   }
   return;

}
//_____________________________________________________________________________
 Int_t TModule::Init()
{   
   TObject  *objLast,*objHist;
   TList *tl = GetMakeList();
   if (!tl) return kOK;
   
   TIter nextModule(tl);
   TModule *maker;

   while ((maker = (TModule*)nextModule())) {

     // save last created histogram in current Root directory
      gROOT->cd();
      objLast = gDirectory->GetList()->Last();

// 		Initialise maker

      maker->StartTimer();
      if (GetDebug()) printf("n*** Call %s::Init() ***n\n",maker->ClassName());
      if ( maker->Init()) return kErr;
      maker->StopTimer();

// 		Add the Module histograms in the Module histograms list
// 		and remove it from the ROOT system directory
      gROOT->cd();
      TIter nextHist(gDirectory->GetList());
      int ready = !objLast;
      while((objHist=nextHist())) {// loop over gDirectory
        if (!ready && objHist!=objLast)		continue;
        ready = 1999;
        if (objHist==objLast)			continue;
        if (!objHist->InheritsFrom("TH1")) 	continue;

// 		Move the histogram from the ROOT list into the "maker's" list
        ((TH1*)objHist)->SetDirectory(0);
        maker->AddHist((TH1*)objHist);
      }
    ::doPs(maker->GetName(),"Init");
    }
  return kOK; 
}
//_____________________________________________________________________________
 void TModule::StartModule()
{
  if (!m_DataSet) {//Keep legacy code
    m_DataSet = Find(".data");
    if (!m_DataSet) {m_DataSet = new TObjectSet(".data"); Add(m_DataSet);}
  }
  if (GetDebug()>1) {
    printf("n*** Call %s::Make() ***n\n", ClassName());
    TMemoryInfo* info = TMemoryInfo::Instance();
    info->Snapshot(); info->Print();
  }
  StartTimer();
}
//_____________________________________________________________________________
 void TModule::EndModule(int ierr)
{
  SetMakeReturn(ierr);
  if (m_DataSet) m_DataSet->Pass(ClearDS,0);
  if (m_GarbSet) m_GarbSet->Delete();
  ::doPs(GetName(),"EndModule");
  
  if (GetDebug()>1) {
    printf("n*** End of %s::Make() ***n\n", ClassName());
    TMemoryInfo* info = TMemoryInfo::Instance();
    info->Snapshot(); info->Print();
  }
  StopTimer();
}

//_____________________________________________________________________________
 Int_t TModule::Finish()
{
//    Terminate a run
//   place to make operations on histograms, normalization,etc.
   int nerr = 0;
#ifdef RUN
   int run = GetRunNumber();
   if (run>-1) FinishRun(run);   
#endif

   TIter next(GetMakeList());
   TModule *maker;
   Double_t totalCpuTime = 0;
   Double_t totalRealTime = 0;   
   while ((maker = (TModule*)next())) 
   {
      if ( maker->Finish() ) nerr++;
      maker->PrintTimer();
      totalCpuTime  += maker->CpuTime();
      totalRealTime += maker->RealTime();
   }

   // Print relative time
   if (totalCpuTime && totalRealTime) {
     Printf("n---------------------------------------------------------------------------------");
     Printf("QAInfo: Total: %-12s: Real Time = %6.2f seconds Cpu Time = %6.2f seconds"
                               ,GetName(),totalRealTime,totalCpuTime);
     Printf("---------------------------------------------------------------------------------");
     next.Reset();
     while ((maker = (TModule*)next())) {
        Printf("QAInfo:%-20s: Real Time = %5.1f %%        Cpu Time = %5.1f %% "
               ,maker->GetName()
               ,100*maker->RealTime()/totalRealTime
               ,100*maker->CpuTime()/totalCpuTime);
     }
     if (!GetParent()) {// Only for top maker

       printf("n--------------Error Codes-------------------------n");
       printf("     nStOK   nStWarn    nStEOF    nStErr  nStFatal  n");
       for( int i=0; i<=kFatal; i++) printf("%10d",fgTallyModule[i]); 
       printf("n--------------------------------------------------n");
     }  
     Printf("=================================================================================n");
   }
   
   Clear();
   return nerr;
}

//_____________________________________________________________________________
 Int_t TModule::Make()
{
//   Loop on all makers
   Int_t ret;
#ifdef RUN
   Int_t run=-1;
#endif
   TList *tl = GetMakeList();
   if (!tl) return kOK;
#ifdef RUN
   StEvtHddr *hd = (StEvtHddr*)GetDataSet("EvtHddr");   
#endif
   TIter nextModule(tl);
   TModule *maker;
   fgFailedModule = 0;
   while ((maker = (TModule*)nextModule())) {
     if (!maker->IsActive()) continue;
#ifdef RUN
     if (hd && hd->IsNewRun()) {
       run = hd->GetOldRunNumber();  
       if (run>-1) maker->FinishRun(run);
       run = hd->GetRunNumber();  
       maker->InitRun(run);
     }
#endif
// 		Call Module
     maker->StartModule();
     ret = maker->Make();
     assert(ret>=0 && ret<=kFatal);     
     fgTallyModule[ret]++;
     maker->EndModule(ret);

     if (Debug() || ret) printf("*** %s::Make() == %d ***n",maker->ClassName(),ret);

     if (ret>kWarn) { 
       maker->ls(3); fgFailedModule = maker; return ret;}
     
   }
   return kOK;
}
//_____________________________________________________________________________
 void TModule::Fatal(int Ierr, const char *com)
{
   printf("QAInfo:%s::Fatal: Error %d %sn",GetName(),Ierr,com);
   TModule *parent = (TModule *)GetParent();
   if (parent) ((TModule*)parent)->Fatal(Ierr,com);
   fflush(stdout);
}
//_____________________________________________________________________________
 TModule *TModule::GetModule(const TDataSet *ds) 
{ 
  const TDataSet *par = ds;
  while (par && (par = par->GetParent()) && strncmp(".maker",par->GetTitle(),6)) {}
  return (TModule*)par;
}
//_____________________________________________________________________________
 EDataSetPass TModule::ClearDS (TDataSet* ds,void * )
{
  // Reduce the size of the table to the used rows + 1
  // and filll the last empty row awith a special pattern
  // Check the table for NaN floating cells if any

  if (ds->InheritsFrom(TTable::Class())){
     TTable *table = (TTable *)ds;
     Int_t setSize =  table->GetTableSize();
     table->ReAllocate();
     memset((void *)table->At(table->GetNRows()),127,table->GetRowSize());
     //yf     if (setSize && (setSize - table->GetTableSize() > 100))
     if (setSize && table->GetTableSize() == 0)
        table->Warning("ReAllocate"," Table %s has purged from %d to %d "
               ,table->GetName(),setSize,table->GetTableSize());
     table->NaN();
  }
  return kContinue; 
}
//_____________________________________________________________________________
 void TModule::PrintInfo() const
{
   const char *cvs = GetCVS();
   const char *built = strstr(cvs,"built");
   printf("QAInfo:%-20s %s from %.*sn",ClassName(),built,built-cvs,cvs);
//     Print info for all defined Modules
   TIter next(GetMakeList());
   TModule *maker;
   while ((maker = (TModule*)next())) {
      maker->PrintInfo();
   }
}
#ifdef RUN
//_____________________________________________________________________________
Int_t        TModule::GetIventNumber() const 
{
   StEvtHddr *hd = (StEvtHddr*)GetDataSet("EvtHddr");
   if (!hd) return -1;
   return hd->GetIventNumber();
}
//_____________________________________________________________________________
void         TModule::SetIventNumber(Int_t iv)  
{
   StEvtHddr *hd = (StEvtHddr*)GetDataSet("EvtHddr");
   if (!hd) return;
   hd->SetIventNumber(iv);
}
//_____________________________________________________________________________
Int_t        TModule::GetEventNumber() const 
{
   StEvtHddr *hd = (StEvtHddr*)GetDataSet("EvtHddr");
   if (!hd) return -1;
   return hd->GetEventNumber();
}
//_____________________________________________________________________________
Int_t        TModule::GetRunNumber() const 
{
   StEvtHddr *hd = (StEvtHddr*)GetDataSet("EvtHddr");
   if (!hd) return -1;
   return hd->GetRunNumber();
}
#endif

//_____________________________________________________________________________
 TModule     *TModule::GetParentChain() const 
{
    const TModule *mk = GetParentModule();
    while(mk && !mk->IsChain()) {mk = mk->GetParentModule();}
    return (TModule*)mk;
}
//_____________________________________________________________________________
 TDatime  TModule::GetDateTime() const 
{    
   TDatime td;    
#ifdef RUN
   StEvtHddr *hd = (StEvtHddr*)GetDataSet("EvtHddr");
   if (!hd) return td;
   return hd->GetDateTime();
#else
   return td;
#endif 
}
//_____________________________________________________________________________
 Int_t    TModule::GetDate()  const {return GetDateTime().GetDate();}
//_____________________________________________________________________________
 Int_t    TModule::GetTime()  const {return GetDateTime().GetTime();}

#ifdef RUN
//_____________________________________________________________________________
const Char_t *TModule::GetEventType() const
{
   StEvtHddr *hd = (StEvtHddr*)GetDataSet("EvtHddr");
   if (!hd) return 0;
   return hd->GetEventType();
}
#endif

//_____________________________________________________________________________
 void TModule::PrintTimer(Option_t *option) 
{
  // Print timer information of this maker
  // Entries counts how many times the methods:
  //    Init(), Make() and Finish () 
  // were called
   if(option){};
   Printf("QAInfo:%-20s: Real Time = %6.2f seconds Cpu Time = %6.2f seconds, Entries = %d",GetName()
           ,m_Timer.RealTime(),m_Timer.CpuTime(),m_Timer.Counter());
}

//_____________________________________________________________________________
static void MakeAssociatedClassList(const TObject *obj, const Char_t *classDir=0)
{
 //
 // This function creates the html docs of the classes pointed within
 // <obj> class source directory
 //
 // classDir - the name of the directory to search in
 //
 // Search C++ class declarations like:
 //
 //   class <className> : 
 //   class <className> { 
 //   class <className> ;
 //
 // looping over all *.h within the "classDir" directory 
 // if provided
 // otherwise within "this" class source directory
 //

  if (!obj) return;
  const Char_t *thisDir = classDir;
  if (thisDir == 0 || thisDir[0] == 0) 
       thisDir = gSystem->DirName(obj->IsA()->GetImplFileName());
  const Char_t *thisClassName = obj->IsA()->GetName();
  // Loop over all *.h files within <thisDir> to find
  // C++ class declarations
  void *dirhandle = 0;
  TString className;
  if ( (dirhandle = gSystem->OpenDirectory(thisDir)) ) 
  {
    const Char_t *n = 0;
    ifstream headerFile;
    Char_t inBuffer[128] = {0};
    Int_t lBuf = sizeof(inBuffer);
    Char_t *nextSym = inBuffer;
    Int_t status = 0;
    const Char_t keyWord[] = "class";
    const Int_t lKeyWord = sizeof(keyWord);

    while ( (n = gSystem->GetDirEntry(dirhandle)) ) {
      // look for *.h* files but *Cint.h
      if (!strstr(n,".h") || strstr(n,"Cint.h") ) continue; 
      Char_t *fullFile = gSystem->ConcatFileName(thisDir,n);
      headerFile.open(fullFile);
      if (headerFile.fail()) continue;
      while (headerFile.getline(inBuffer,lBuf) && !headerFile.eof()) {
        nextSym = inBuffer;
        if (status==0)  status = 1;
        do {
 /* 
  ************************************************************
  *
  *      |<===========================================+
  *      |                                            |
  * $-->(1)<===+                                      |
  *      | ' ' |                                      |
  *      |---->|                                      |
  *      |"class"   ' '                               |
  *      |------>(2)--->(3)<===+                      |
  *                      | ' ' |                      |
  *                      |---->|                      | 
  *                      | name                       |
  *                      |------>(4)<===+             |
  *                               | ' ' |             | 
  *                               |---->|             | 
  *                               | ";"               | 
  *                               |------>(5)-------->|
  *                               |        | add2list    
  *                               |  ":"   |
  *                               |------->|
  *
  ************************************************************
  */
          switch (status) {
            case 1: {
                if (*nextSym == ' ' || *nextSym == 't') break;    
                const Char_t *classFound = strstr(nextSym,keyWord);
                if ( classFound && classFound == nextSym){
                                                        status = 2;
                   nextSym += lKeyWord-2;
                }
                else                         status = 0;             
                break;
              }
            case 2:                       status = 0;
              if (*nextSym == ' ' || *nextSym == 't')  status = 3;
              break;
            case 3:
              if (*nextSym == ' ' || *nextSym == 't') break;    
                                           status = 0;
              if (isalpha(*nextSym)) {
                 className = *nextSym;
                 nextSym++;
                 while (isalnum(*nextSym) || *nextSym == '_' ) { 
                    className += *nextSym++;            status = 4;
                 }
                 nextSym--;
              }
              break;
            case 4:
              if (*nextSym == ' ' || *nextSym == 't') break;    
                                          status = 0;
              if (*nextSym == 0 || *nextSym == ':' || *nextSym == '{' ||
                  ( *nextSym == '/' && 
                    (*(nextSym+1) == '/' || *(nextSym+1) == '*') 
                  )
                 )                                      status = 5;                 
              break;
            case 5:
              if (strcmp(thisClassName,className.Data())) {
                printf(" MakeDoc: %sn", className.Data());
                TClass *cl = gROOT->GetClass(className.Data());
                if (cl && !cl->InheritsFrom("TModule") ) {
                    gHtml->MakeClass((Text_t *)className.Data());
                }
              }
            default:                                    status = 1;
               break;
          };
        }   while (*(++nextSym) && status ); // end of buffer
      } // eof()
      headerFile.close();
      delete [] fullFile;
    } 
  }  
}
//_____________________________________________________________________________
 void TModule::MakeDoc(const TString &stardir,const TString &outdir, Bool_t baseClasses)
{
 //
 // MakeDoc - creates the HTML doc for this class and for the base classes
 //           (if baseClasses == kTRUE):
 //
 //         *  St_XDFFile   St_Module      TTable       *
 //         *  TDataSet   St_DataSetIter St_FileSet     *
 //         *  TModule      StChain        StEvent        *
 //         *  St_TLA_Module                               *
 //
 // stardir - the "root" directory to lookup the subdirectories as follows.
 //           = "$(STAR)"             by default
 // outdir  - directory to write the generated HTML and Postscript files into
 //           = "$(STAR)/StRoot/html" by default
 //
 //            The following subdirectories are used to look it up:
 //            $(stardir)
 //            $(stardir) + "StRoot/St_base"
 //            $(stardir) + "StRoot/StChain"
 //            $(stardir) + "StRoot/xdf2root"
 //            $(stardir) + "StRoot/StarClassLibrary"
 //            $(stardir) + "StRoot/StEvent"
 //            $(stardir) + ".share/tables"
 //            $(stardir) + "include",
 //            $(stardir) + "include/tables",
 //            $(stardir) + "StRoot/<this class name>",
 //
 //   where $(stardir) is the input parameter (by default = "$STAR")
 //
 // baseClasses - flag to mark whether the base classes HTML docs will be created as well
 //               = kTRUE by default

 // Define the type of the OS
  TString STAR = stardir;
  TString delim = ":";
  Bool_t NT=kFALSE;

  if (strcmp(gSystem->GetName(),"WinNT") == 0 ) {
     NT=kTRUE;
     delim = ";";
     STAR.ReplaceAll("$(afs)","//sol/afs");
  }
  else 
     STAR.ReplaceAll("$(afs)","/afs");

  TString classname = IsA()->GetName();

  THtml thisHtml;

//  if (!gHtml) gHtml = new THtml;

  // Define the set of the subdirectories with the STAR class sources
  //                       | ----------------------  | ------------  | ------------------ |
  //                       | Directory name             Class name     Share library name |
  //                       | ----------------------  | ------------  | ------------------ |
  const Char_t *source[] = {"StRoot/St_base"         , "St_DataSet"  ,    "St_base"
                           ,"StRoot/StChain"         , "TModule"     ,    "StChain"
                           ,"StRoot/xdf2root"        , "St_XDFFile"  ,    "xdf2root"
//                           ,"StRoot/StUtilities"     , "StMessage"   ,    "StUtilities"
                           ,"StRoot/StarClassLibrary", ""            ,    ""
                           ,"StRoot/StEvent"         , "StEvent"     ,    "StEvent"
                           ,"StRoot/St_TLA_Module"    , "St_TLA_Module",    "St_TLA_Module"
                           ,".share/tables"          , ""            ,     ""
                           ,"include"                , ""            ,     ""
                           ,"include/tables"         , ""            ,     ""
                           };

  const Int_t lsource = sizeof(source)/sizeof(const Char_t *);
 
  TString classDir = gSystem->DirName(IsA()->GetImplFileName());
  TString lookup = STAR;
  lookup += delim;

  lookup += STAR;
  lookup += "/";
  lookup += classDir;
  lookup += delim;

  lookup += STAR;
  lookup += "/StRoot/";
  lookup += classname;

  // Add class name base
  
  Int_t i = 0;
  for (i=0;i<lsource-3;i+=3) {
    lookup += delim;
    lookup += STAR;
    lookup += "/";
    lookup += source[i];
    // Load extra share library if any
    const Char_t *cl = source[i+1];
    const Char_t *so = source[i+2];
    if (cl && cl[0] && so && so[0] && !gROOT->GetClass(cl)) 
    {
       if (gSystem->Load(so)) 
           printf(" Failed to load the share library %s for class %sn",so,cl);
    }
  }

//  cout << lookup.Data() << endl << endl;
  
//  const Char_t *c = ClassName();  // This trick has to be done since a bug within ROOT

  lookup.ReplaceAll("//StRoot/","/StRoot/");
  thisHtml.SetSourceDir(lookup);

  TString odir = outdir;
//  odir.ReplaceAll("$(STAR)",STAR);
  gSystem->ExpandPathName(odir);
  thisHtml.SetOutputDir(odir);

  // Create the list of the classes defined with the loaded DLL's to be documented

  const Char_t *classes[] = { "St_XDFFile",  "St_Module",      "St_Table"
                              ,"St_DataSet",  "St_DataSetIter", "St_FileSet"
                              ,"TModule",     "StChain"
                              ,"table_head_st"
                            };
  Int_t nclass = sizeof(classes)/4;
  // Create the definitions of the classes not derived from TObjects
  TString header = "$STAF/inc/table_header.h";

  gSystem->ExpandPathName(header);
  header.ReplaceAll("//inc/","/inc/");
  gROOT->LoadMacro(header);

  TClass header1("table_head_st",1,"table_header.h","table_header.h");

  // Update the docs of the base classes
  static Bool_t makeAllAtOnce = kTRUE;
  if (makeAllAtOnce && baseClasses) { 
      makeAllAtOnce = kFALSE;
      //  thisHtml.MakeAll();  // VF 10/09/99
      for (i=0;i<nclass;i++) thisHtml.MakeClass(classes[i]);
      thisHtml.MakeIndex();
//      MakeAssociatedClassList(this, classDir.Data());
  }

  if (baseClasses) {gHtml= &thisHtml;  MakeAssociatedClassList(this, classDir.Data()); }
  // Create the doc for this class
  printf(" Making html for <%s>n",classname.Data());
  thisHtml.MakeClass((Char_t *)classname.Data());
  // Create the associated classes docs
  //   Loop on all makers
   TList *tl = GetMakeList();
   if (tl) {
     TIter nextModule(tl);
     TModule *maker;
     while ((maker = (TModule*)nextModule())) 
         maker->MakeDoc(stardir,outdir,kFALSE);
   }
}

//_____________________________________________________________________________
static void doPs(const char *who, const char *where)
{
  static const char *ps =0;
  TString *ts = 0;
  if (!ps) {
//		execute shell      
    ps = gSystem->Getenv("StarEndModuleShell"); 
    if (ps) {
      char buf[12]; sprintf(buf,"%d",gSystem->GetPid());
      if (!ps[0]) {
#if defined(__linux)
	ps = "ps up $$";
#elif defined(__sun)
	ps = "ps -o user -o pid -o pcpu -o pmem -o osz -o rss -o stime -o time -o comm -p $$";
#elif defined(__hpux)
	ps = "ps -lP -p $$";
#endif
      }
      ts = new  TString(ps); // keep ts
      ts->ReplaceAll("$$",buf);
      ps = ts->Data();
    } else { ps ="";}
  }
  if (ps[0]) { //Execute shell
    //    fflush(stdout);
    //    if (gSystem->Exec(ps)) ps="";
    char   psBuffer[128];
    FILE   *pipe;
    if( (pipe = gSystem->OpenPipe(ps, "r" )) == NULL ) ps = "";
    else {
      while( !feof( pipe ) ) {
	if( fgets( psBuffer, 128, pipe ) != NULL ) {
	  printf("QAInfo: doPs for %20s:%12s t%s",who,where,psBuffer);
	}
      }
    }
    gSystem->ClosePipe( pipe );
  }
}

//_____________________________________________________________________________
 void TModule::Streamer(TBuffer &)
{ Error("Streamer"," attempt to write %sn ",GetName());
  assert(0);
}
//______________________________________________________________________________
 TModule *TModule::New(const Char_t *classname, const Char_t *name, void *title)
{
  // This static method creates a new TModule object if provided 
  
  TModule *maker = 0;
  if (classname) 
  {
    TClass *cl = gROOT->GetClass(classname);
    if (cl) {
      maker = (TModule *)cl->New();
      if (maker) {
	if (name && strlen(name)) maker->SetName(name);
	if (title) maker->SetTitle((Char_t *) title);
      }
    } 
  }
  return maker; 
}

//_____________________________________________________________________________
 void TModule::SetDEBUG(Int_t l)
{
  m_DebugLevel = l;
//   Loop on all makers
   TList *tl = GetMakeList();
   if (!tl) return;
   
   TIter nextModule(tl);
   TModule *maker;
   while ((maker = (TModule*)nextModule())) maker->SetDEBUG(l);
}
//_____________________________________________________________________________
 Int_t TModule::InitRun(int runumber) {return 0;}
//_____________________________________________________________________________
 Int_t TModule::FinishRun(int runumber) {return 0;}

//_____________________________________________________________________________
TModuleIter::TModuleIter(TModule *mk,int secondary)
{
  fState = 0;
  fModule = mk;
  fModuleIter = 0;
  fIter  = new TDataSetIter(fModule->Find(".make"));
  fItWas = (TDataSet*)(-1);
  fSecond = secondary;
   
}
//_____________________________________________________________________________
TModuleIter::~TModuleIter()
{
  delete fIter; 	fIter = 0; 
  delete fModuleIter;	fModuleIter = 0;
  fModule=0; fState = 0;
}
//_____________________________________________________________________________
TModule  *TModuleIter::NextModule()
{
  TDataSet *ds;
  if (!fModule)	return 0;

AGAIN: switch (fState) {

    case 0: 					//current maker 
      ds = fIter->Next();
      if (ds == fItWas) 	goto AGAIN;	//used already, go to Next
      fState = 2;  if (!ds) 	goto AGAIN;	//no more,      go to UP
      fState = 1;				//go to Down
      delete fModuleIter; 
      fModuleIter = new TModuleIter((TModule*)ds,1);
      goto AGAIN;

    case 1: 	// Recursive iteration
      ds = fModuleIter->NextModule();
      if (ds) return (TModule*)ds;
      fState = 0;		goto AGAIN;	//no more in downstaires,go curren
     
    case 2:
      delete fModuleIter; fModuleIter=0;
      delete fIter; 	 fIter = 0;
      fState = 3;
      return fModule;

    case 3:					// go upper when started
      if (fSecond) return 0;
      TDataSet *par = fModule->GetParent();
      fItWas = fModule; fModule = 0;
      if (!par) 				return 0;
      if (strcmp(".make",par->GetName()))	return 0;
      fModule = (TModule*)par->GetParent();
      if (!fModule)				return 0;
      delete fIter; fIter = new TDataSetIter(par);
      fState = 0; goto AGAIN;
  }
  assert(0); return 0;
}


//_____________________________________________________________________________
// $Log: TModule.cxx.html,v $
// Revision 1.3  2002/04/17 23:18:29  fine
// new documentation
//
// Revision 1.3  2002/04/15 20:23:39  fine
// NEw naming schema for RootKErnel classes and a set of classes to back geometry OO
//
// Revision 1.2  2002/04/15 17:54:31  fine
// Perl utilities have been moved to the separate Utils subdir
//
// Revision 1.1.1.1  2001/09/21 02:57:49  hma
// initial version
//
// Revision 1.3  2001/09/16 03:21:44  fine
// compilation warning removed
//
// Revision 1.2  2001/09/15 22:45:09  fine
// documentaion make up
//
// Revision 1.1  2001/09/09 03:32:44  fine
//  new class TModule
//
// Revision 1.5  2001/05/14 23:58:59  fine
// Some corrections
//
// Revision 1.4  2001/04/13 01:33:24  fine
// Databse stream update: some fixes
//
// Revision 1.2  2001/04/10 22:53:29  fine
// multi-stream inout version
//
// Revision 1.1  2001/03/28 15:53:42  fine
// TModule class has been included
//
// Revision 1.1.1.2  2000/09/11 19:43:08  fisyak
// Complete release of Emtb
//
// Revision 1.1.1.1  2000/08/11 19:25:36  fisyak
// Valery's version
//
// Revision 1.1  2000/08/11 19:23:36  fisyak
// Valery's version
//
//--


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.