THtml.cxx

Go to the documentation of this file.
00001 // @(#)root/html:$Id: THtml.cxx 37484 2010-12-10 10:06:11Z axel $
00002 // Author: Nenad Buncic (18/10/95), Axel Naumann (09/28/01)
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "THtml.h"
00013 #include "RConfigure.h"
00014 #include "Riostream.h"
00015 #include "TBaseClass.h"
00016 #include "TClass.h"
00017 #include "TClassDocOutput.h"
00018 #include "TClassEdit.h"
00019 #include "TClassTable.h"
00020 #include "TDataType.h"
00021 #include "TDocInfo.h"
00022 #include "TDocOutput.h"
00023 #include "TEnv.h"
00024 #include "TInterpreter.h"
00025 #include "TObjString.h"
00026 #include "TPRegexp.h"
00027 #include "TRegexp.h"
00028 #include "TROOT.h"
00029 #include "TSystem.h"
00030 #include "TThread.h"
00031 
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <ctype.h>
00035 #include <set>
00036 #include <fstream>
00037 
00038 THtml *gHtml = 0;
00039 
00040 //______________________________________________________________________________
00041 //______________________________________________________________________________
00042 namespace {
00043    class THtmlThreadInfo {
00044    public:
00045       THtmlThreadInfo(THtml* html, bool force): fHtml(html), fForce(force) {}
00046       Bool_t GetForce() const {return fForce;}
00047       THtml* GetHtml() const {return fHtml;}
00048 
00049    private:
00050       THtml* fHtml;
00051       Bool_t fForce;
00052    };
00053 };
00054 
00055 
00056 //______________________________________________________________________________
00057 THtml::THelperBase::~THelperBase()
00058 {
00059    // Helper's destructor.
00060    // Check that no THtml object is attached to the helper - it might still need it!
00061    if (fHtml) {
00062       fHtml->HelperDeleted(this);
00063    }
00064 }
00065 
00066 
00067 //______________________________________________________________________________
00068 void THtml::THelperBase::SetOwner(THtml* html) {
00069    // Set the THtml object owning this object; if it's already set to
00070    // a different THtml object than issue an error message and signal to
00071    // the currently set object that we are not belonging to it anymore.
00072    if (fHtml && html && html != fHtml) {
00073       Error("SetOwner()", "Object already owned by an THtml instance!");
00074       fHtml->HelperDeleted(this);
00075    }
00076    fHtml = html;
00077 }
00078 
00079 
00080 //______________________________________________________________________________
00081 bool THtml::TModuleDefinition::GetModule(TClass* cl, TFileSysEntry* fse,
00082                                          TString& out_modulename) const
00083 {
00084    // Set out_modulename to cl's module name; return true if it's valid.
00085    // If applicable, the module contains super modules separated by "/".
00086    //
00087    // ROOT takes the directory part of cl's implementation file name
00088    // (or declaration file name, if the implementation file name is empty),
00089    // removes the last subdirectory if it is "src/" or "inc/", and interprets
00090    // the remaining path as the module hierarchy, converting it to upper case.
00091    // hist/histpainter/src/THistPainter.cxx thus becomes the module
00092    // HIST/HISTPAINTER. (Node: some ROOT packages get special treatment.)
00093    // If the file cannot be mapped into this scheme, the class's library
00094    // name (without directories, leading "lib" prefix or file extensions)
00095    // ius taken as the module name. If the module cannot be determined it is
00096    // set to "USER" and false is returned.
00097    //
00098    // If your software cannot be mapped into this scheme then derive your
00099    // own class from TModuleDefinition and pass it to THtml::SetModuleDefinition().
00100    //
00101    // The fse parameter is used to determine the relevant part of the path, i.e.
00102    // to not include parent directories of a TFileSysRoot.
00103 
00104    out_modulename = "USER";
00105    if (!cl) return false;
00106 
00107    // Filename: impl or decl?
00108    TString filename;
00109    if (fse) fse->GetFullName(filename, kFALSE);
00110    else {
00111       if (!GetOwner()->GetImplFileName(cl, kFALSE, filename))
00112          if (!GetOwner()->GetDeclFileName(cl, kFALSE, filename))
00113             return false;
00114    }
00115    TString inputdir = GetOwner()->GetInputPath();
00116    TString tok;
00117    Ssiz_t start = 0;
00118    // For -Idir/sub and A.h in dir/sub/A.h, use sub as module name if
00119    // it would eb empty otehrwise.
00120    TString trailingInclude;
00121    while (inputdir.Tokenize(tok, start, THtml::GetDirDelimiter())) {
00122       if (filename.BeginsWith(tok)) {
00123          if (tok.EndsWith("/") || tok.EndsWith("\\"))
00124             tok.Remove(tok.Length() - 1);
00125          trailingInclude = gSystem->BaseName(tok);
00126          filename.Remove(0, tok.Length());
00127          break;
00128       }
00129    }
00130 
00131    // take the directory name without "/" or leading "."
00132    out_modulename = gSystem->DirName(filename);
00133 
00134    while (out_modulename[0] == '.')
00135       out_modulename.Remove(0, 1);
00136    out_modulename.ReplaceAll("\\", "/");
00137    while (out_modulename[0] == '/')
00138       out_modulename.Remove(0, 1);
00139    while (out_modulename.EndsWith("/"))
00140       out_modulename.Remove(out_modulename.Length() - 1);
00141 
00142    if (!out_modulename[0])
00143       out_modulename = trailingInclude;
00144 
00145    if (!out_modulename[0])
00146       out_modulename = trailingInclude;
00147 
00148    // remove "/src", "/inc"
00149    if (out_modulename.EndsWith("/src")
00150       || out_modulename.EndsWith("/inc"))
00151       out_modulename.Remove(out_modulename.Length() - 4, 4);
00152    else {
00153    // remove "/src/whatever", "/inc/whatever"
00154       Ssiz_t pos = out_modulename.Index("/src/");
00155       if (pos == kNPOS)
00156          pos = out_modulename.Index("/inc/");
00157       if (pos != kNPOS)
00158          out_modulename.Remove(pos);
00159    }
00160 
00161    while (out_modulename.EndsWith("/"))
00162       out_modulename.Remove(out_modulename.Length() - 1);
00163 
00164    // special treatment:
00165    if (out_modulename == "MATH/GENVECTOR")
00166       out_modulename = "MATHCORE";
00167    else if (out_modulename == "MATH/MATRIX")
00168       out_modulename = "SMATRIX";
00169    else if (!out_modulename.Length()) {
00170       const char* cname= cl->GetName();
00171       if (strstr(cname, "::SMatrix<") || strstr(cname, "::SVector<"))
00172          out_modulename = "SMATRIX";
00173       else if (strstr(cname, "::TArrayProxy<") || strstr(cname, "::TClaArrayProxy<")
00174                || strstr(cname, "::TImpProxy<") || strstr(cname, "::TClaImpProxy<"))
00175          out_modulename = "TREEPLAYER";
00176       else {
00177          // determine the module name from the library name:
00178          out_modulename = cl->GetSharedLibs();
00179          Ssiz_t pos = out_modulename.Index(' ');
00180          if (pos != kNPOS)
00181             out_modulename.Remove(pos, out_modulename.Length());
00182          if (out_modulename.BeginsWith("lib"))
00183             out_modulename.Remove(0,3);
00184          pos = out_modulename.Index('.');
00185          if (pos != kNPOS)
00186             out_modulename.Remove(pos, out_modulename.Length());
00187 
00188          if (!out_modulename.Length()) {
00189             out_modulename = "USER";
00190             return false;
00191          }
00192       }
00193    }
00194 
00195    return true;
00196 }
00197 
00198 //______________________________________________________________________________
00199 void THtml::TFileDefinition::ExpandSearchPath(TString& path) const
00200 {
00201    // Create all permutations of path and THtml's input path:
00202    // path being PP/ and THtml's input being .:include/:src/ gives
00203    // .:./PP/:include:include/PP/:src/:src/PP
00204    THtml* owner = GetOwner();
00205    if (!owner) return;
00206 
00207    TString pathext;
00208    TString inputdir = owner->GetInputPath();
00209    TString tok;
00210    Ssiz_t start = 0;
00211    while (inputdir.Tokenize(tok, start, THtml::GetDirDelimiter())) {
00212       if (pathext.Length())
00213          pathext += GetDirDelimiter();
00214       if (tok.EndsWith("\\"))
00215          tok.Remove(tok.Length() - 1);
00216       pathext += tok;
00217       if (path.BeginsWith(tok))
00218          pathext += GetDirDelimiter() + path;
00219       else
00220          pathext += GetDirDelimiter() + tok + "/" + path;
00221    }
00222    path = pathext;
00223 
00224 }
00225 
00226 //______________________________________________________________________________
00227 void THtml::TFileDefinition::SplitClassIntoDirFile(const TString& clname, TString& dir,
00228                                                    TString& filename) const
00229 {
00230    // Given a class name with a scope, split the class name into directory part
00231    // and file name: A::B::C becomes module B, filename C.
00232    TString token;
00233    Ssiz_t from = 0;
00234    filename = "";
00235    dir = "";
00236    while (clname.Tokenize(token, from, "::") ) {
00237       dir = filename;
00238       filename = token;
00239    }
00240 
00241    // convert from Scope, class to module, filename.h
00242    dir.ToLower();
00243 }
00244 
00245 
00246 //______________________________________________________________________________
00247 bool THtml::TFileDefinition::GetDeclFileName(const TClass* cl, TString& out_filename,
00248                                              TString& out_fsys, TFileSysEntry** fse) const
00249 {
00250    // Determine cl's declaration file name. Usually it's just
00251    // cl->GetDeclFileName(), but sometimes conversions need to be done
00252    // like include/ to abc/cde/inc/. If no declaration file name is
00253    // available, look for b/inc/C.h for class A::B::C. out_fsys will contain
00254    // the file system's (i.e. local machine's) full path name to the file.
00255    // The function returns false if the class's header file cannot be found.
00256    //
00257    // If your software cannot be mapped into this scheme then derive your
00258    // own class from TFileDefinition and pass it to THtml::SetFileDefinition().
00259 
00260    return GetFileName(cl, true, out_filename, out_fsys, fse);
00261 }
00262 
00263 //______________________________________________________________________________
00264 bool THtml::TFileDefinition::GetImplFileName(const TClass* cl, TString& out_filename,
00265                                              TString& out_fsys, TFileSysEntry** fse) const
00266 {
00267    // Determine cl's implementation file name. Usually it's just
00268    // cl->GetImplFileName(), but sometimes conversions need to be done.
00269    // If no implementation file name is available look for b/src/C.cxx for
00270    // class A::B::C. out_fsys will contain the file system's (i.e. local
00271    // machine's) full path name to the file.
00272    // The function returns false if the class's source file cannot be found.
00273    //
00274    // If your software cannot be mapped into this scheme then derive your
00275    // own class from TFileDefinition and pass it to THtml::SetFileDefinition().
00276 
00277    return GetFileName(cl, false, out_filename, out_fsys, fse);
00278 }
00279 
00280 
00281 //______________________________________________________________________________
00282 void THtml::TFileDefinition::NormalizePath(TString& filename) const
00283 {
00284    // Remove "/./" and collapse "/subdir/../" to "/"
00285    static const char* delim[] = {"/", "\\\\"};
00286    for (int i = 0; i < 2; ++i) {
00287       const char* d = delim[i];
00288       filename = filename.ReplaceAll(TString::Format("%c.%c", d[0], d[0]), TString(d[0]));
00289       TPRegexp reg(TString::Format("%s[^%s]+%s\\.\\.%s", d, d, d, d));
00290       while (reg.Substitute(filename, TString(d[0]), "", 0, 1)) {}
00291    }
00292    if (filename.BeginsWith("./") || filename.BeginsWith(".\\"))
00293       filename.Remove(0,2);
00294 }
00295 
00296 
00297 //______________________________________________________________________________
00298 TString THtml::TFileDefinition::MatchFileSysName(TString& filename, TFileSysEntry** fse) const
00299 {
00300    // Find filename in the list of system files; return the system file name
00301    // and change filename to the file name as included.
00302    // filename must be normalized (no "/./" etc) before calling.
00303 
00304    TList* bucket = GetOwner()->GetLocalFiles()->GetEntries().GetListForObject(gSystem->BaseName(filename));
00305    TString filesysname;
00306    if (bucket) {
00307       TIter iFS(bucket);
00308       TFileSysEntry* fsentry = 0;
00309       while ((fsentry = (TFileSysEntry*) iFS())) {
00310          if (!filename.EndsWith(fsentry->GetName()))
00311             continue;
00312          fsentry->GetFullName(filesysname, kTRUE); // get the short version
00313          if (!filename.EndsWith(filesysname)) {
00314             filesysname = "";
00315             continue;
00316          }
00317          filename = filesysname;
00318          fsentry->GetFullName(filesysname, kFALSE); // get the long version
00319          if (fse) *fse = fsentry;
00320          break;
00321       }
00322    }
00323    return filesysname;
00324 }
00325 
00326 
00327 //______________________________________________________________________________
00328 bool THtml::TFileDefinition::GetFileName(const TClass* cl, bool decl,
00329                                          TString& out_filename, TString& out_fsys,
00330                                          TFileSysEntry** fse) const
00331 {
00332    // Common implementation for GetDeclFileName(), GetImplFileName()
00333 
00334    out_fsys = "";
00335 
00336    if (!cl) {
00337       out_filename = "";
00338       return false;
00339    }
00340 
00341    TString possibleFileName;
00342    TString possiblePath;
00343    TString filesysname;
00344 
00345    TString clfile = decl ? cl->GetDeclFileName() : cl->GetImplFileName();
00346    NormalizePath(clfile);
00347 
00348    out_filename = clfile;
00349    if (clfile.Length()) {
00350       // check that clfile doesn't start with one of the include paths;
00351       // that's not what we want (include/TObject.h), we want the actual file
00352       // if it exists (core/base/inc/TObject.h)
00353 
00354       // special case for TMath namespace:
00355       if (clfile == "include/TMathBase.h") {
00356          clfile = "math/mathcore/inc/TMath.h";
00357          out_filename = clfile;
00358       }
00359 
00360       TString inclDir;
00361       TString inclPath(GetOwner()->GetPathInfo().fIncludePath);
00362       Ssiz_t pos = 0;
00363       Ssiz_t longestMatch = kNPOS;
00364       while (inclPath.Tokenize(inclDir, pos, GetOwner()->GetDirDelimiter())) {
00365          if (clfile.BeginsWith(inclDir) && (longestMatch == kNPOS || inclDir.Length() > longestMatch))
00366             longestMatch = inclDir.Length();
00367       }
00368       if (longestMatch != kNPOS) {
00369          clfile.Remove(0, longestMatch);
00370          if (clfile.BeginsWith("/") || clfile.BeginsWith("\\"))
00371             clfile.Remove(0, 1);
00372          TString asincl(clfile);
00373          GetOwner()->GetPathDefinition().GetFileNameFromInclude(asincl, clfile);
00374          out_filename = clfile;
00375       } else {
00376          // header file without a -Iinclude-dir prefix
00377          filesysname = MatchFileSysName(out_filename, fse);
00378          if (filesysname[0]) {
00379             clfile = out_filename;
00380          }
00381       }
00382    } else {
00383       // check for a file named like the class:
00384       filesysname = cl->GetName();
00385       int templateLevel = 0;
00386       Ssiz_t end = filesysname.Length();
00387       Ssiz_t start = end - 1;
00388       for (; start >= 0 && (templateLevel || filesysname[start] != ':'); --start) {
00389          if (filesysname[start] == '>')
00390             ++templateLevel;
00391          else if (filesysname[start] == '<') {
00392             --templateLevel;
00393             if (!templateLevel)
00394                end = start;
00395          }
00396       }
00397       filesysname = filesysname(start + 1, end - start - 1);
00398       if (decl)
00399          filesysname += ".h";
00400       else
00401          filesysname += ".cxx";
00402       out_filename = filesysname;
00403       filesysname = MatchFileSysName(out_filename, fse);
00404       if (filesysname[0]) {
00405          clfile = out_filename;
00406       }
00407    }
00408 
00409    if (!decl && !clfile.Length()) {
00410       // determine possible impl file name from the decl file name,
00411       // replacing ".whatever" by ".cxx", and looking for it in the known
00412       // file names
00413       TString declSysFileName;
00414       if (GetFileName(cl, true, filesysname, declSysFileName)) {
00415          filesysname = gSystem->BaseName(filesysname);
00416          Ssiz_t posExt = filesysname.Last('.');
00417          if (posExt != kNPOS)
00418             filesysname.Remove(posExt);
00419          filesysname += ".cxx";
00420          out_filename = filesysname;
00421          filesysname = MatchFileSysName(out_filename, fse);
00422          if (filesysname[0]) {
00423             clfile = out_filename;
00424          }
00425       }
00426    }
00427 
00428    if (clfile.Length() && !decl) {
00429       // Do not return the source file for these packages, even though we can find them.
00430       // THtml needs to have the class description in the source file if it finds the
00431       // source file, and these classes have their class descriptions in the header files.
00432       // THtml needs to be improved to collect all of a class' documentation before writing
00433       // it out, so it can take the class doc from the header even though a source exists.
00434       static const char* vetoClasses[] = {"math/mathcore/", "math/mathmore/", "math/genvector/",
00435                                           "math/minuit2/", "math/smatrix/"};
00436       for (unsigned int i = 0; i < sizeof(vetoClasses) / sizeof(char*); ++i) {
00437          if (clfile.Contains(vetoClasses[i])) {
00438             // of course there are exceptions from the exceptions:
00439             // TComplex and TRandom, TRandom1,...
00440             if (strcmp(cl->GetName(), "TComplex")
00441                 && strcmp(cl->GetName(), "TMath")
00442                 && strncmp(cl->GetName(), "TKDTree", 7)
00443                 && strcmp(cl->GetName(), "TVirtualFitter")
00444                 && strncmp(cl->GetName(), "TRandom", 7)) {
00445                out_filename = "";
00446                return false;
00447             } else break;
00448          }
00449       }
00450    }
00451 
00452 
00453    if (!clfile.Length()) {
00454       // determine possible decl file name from class + scope name:
00455       // A::B::C::myclass will result in possible file name myclass.h
00456       // in directory C/inc/
00457       out_filename = cl->GetName();
00458       if (!out_filename.Contains("::")) {
00459          out_filename = "";
00460          return false;
00461       }
00462       SplitClassIntoDirFile(out_filename, possiblePath, possibleFileName);
00463 
00464       // convert from Scope, class to module, filename.h
00465       if (possibleFileName.Length()) {
00466          if (decl)
00467             possibleFileName += ".h";
00468          else
00469             possibleFileName += ".cxx";
00470       }
00471       if (possiblePath.Length())
00472          possiblePath += "/";
00473       if (decl)
00474          possiblePath += "inc/";
00475       else
00476          possiblePath += "src/";
00477       out_filename = possiblePath + "/" + possibleFileName;
00478    } else {
00479       possiblePath = gSystem->DirName(clfile);
00480       possibleFileName = gSystem->BaseName(clfile);
00481    }
00482 
00483    if (possiblePath.Length())
00484       ExpandSearchPath(possiblePath);
00485    else possiblePath=".";
00486 
00487    out_fsys = gSystem->FindFile(possiblePath, possibleFileName, kReadPermission);
00488    if (out_fsys.Length()) {
00489       NormalizePath(out_fsys);
00490       return true;
00491    }
00492    out_filename = "";
00493    return false;
00494 }
00495 
00496 //______________________________________________________________________________
00497 bool THtml::TPathDefinition::GetMacroPath(const TString& module, TString& out_dir) const
00498 {
00499    // Determine the path to look for macros (see TDocMacroDirective) for
00500    // classes from a given module. If the path was sucessfully determined return true.
00501    // For ROOT, this directory is the "doc/macros" subdirectory of the module
00502    // directory; the path returned is GetDocDir(module) + "/macros".
00503    //
00504    // If your software cannot be mapped into this scheme then derive your
00505    // own class from TPathDefinition and pass it to THtml::SetPathDefinition().
00506 
00507    TString moduledoc;
00508    if (!GetDocDir(module, moduledoc))
00509       return false;
00510    if (moduledoc.EndsWith("\\"))
00511       moduledoc.Remove(moduledoc.Length() - 1);
00512 
00513    TString macropath(GetOwner()->GetMacroPath());
00514    TString macrodirpart;
00515    out_dir = "";
00516    Ssiz_t pos = 0;
00517    while (macropath.Tokenize(macrodirpart, pos, ":")) {
00518       out_dir += moduledoc + "/" + macrodirpart + ":";
00519    }
00520    return true;
00521 }
00522 
00523 
00524 //______________________________________________________________________________
00525 bool THtml::TPathDefinition::GetDocDir(const TString& module, TString& doc_dir) const
00526 {
00527    // Determine the module's documentation directory. If module is empty,
00528    // set doc_dir to the product's documentation directory.
00529    // If the path was sucessfuly determined return true.
00530    // For ROOT, this directory is the subdir "doc/" in the
00531    // module's path; the directory returned is module + "/doc".
00532    //
00533    // If your software cannot be mapped into this scheme then derive your
00534    // own class from TPathDefinition and pass it to THtml::SetPathDefinition().
00535 
00536    if (module.Length())
00537       doc_dir = module + "/";
00538    doc_dir += GetOwner()->GetPathInfo().fDocPath;
00539    return true;
00540 }
00541 
00542 
00543 //______________________________________________________________________________
00544 bool THtml::TPathDefinition::GetIncludeAs(TClass* cl, TString& out_dir) const
00545 {
00546    // Determine the path and filename used in an include statement for the
00547    // header file of the given class. E.g. the class ROOT::Math::Boost is
00548    // meant to be included as "Math/Genvector/Boost.h" - which is what
00549    // out_dir is set to. GetIncludeAs() returns whether the include
00550    // statement's path was successfully determined.
00551    //
00552    // Any leading directory part that is part of fIncludePath (see SetIncludePath)
00553    // will be removed. For ROOT, leading "include/" is removed; everything after
00554    // is the include path. Only classes from TMVA are different; they are included
00555    // as TMVA/ClassName.h.
00556    //
00557    // If your software cannot be mapped into this scheme then derive your
00558    // own class from TPathDefinition and pass it to THtml::SetPathDefinition().
00559 
00560    out_dir = "";
00561    if (!cl || !GetOwner()) return false;
00562 
00563    const char* clname = cl->GetName();
00564    TString hdr;
00565    if (!GetOwner()->GetDeclFileName(cl, kFALSE, hdr))
00566       return false;
00567 
00568    out_dir = hdr;
00569    bool includePathMatches = false;
00570    TString tok;
00571    Ssiz_t pos = 0;
00572    while (!includePathMatches && GetOwner()->GetPathInfo().fIncludePath.Tokenize(tok, pos, THtml::GetDirDelimiter()))
00573       if (out_dir.BeginsWith(tok)) {
00574          out_dir = hdr(tok.Length(), hdr.Length());
00575          if (out_dir[0] == '/' || out_dir[0] == '\\')
00576             out_dir.Remove(0, 1);
00577          includePathMatches = true;
00578       }
00579 
00580    if (!includePathMatches) {
00581       // We probably have a file super/module/inc/optional/filename.h.
00582       // That gets translated into optional/filename.h.
00583       // Assume that only one occurrence of "/inc/" exists in hdr.
00584       // If /inc/ is not part of the include file name then
00585       // just return the full path.
00586       // If we have matched any include path then this ROOT-only
00587       // algorithm is skipped!
00588       Ssiz_t posInc = hdr.Index("/inc/");
00589       if (posInc == kNPOS) return true;
00590       hdr.Remove(0, posInc + 5);
00591       out_dir = hdr;
00592 
00593       // TMVA and RooStats special treatment:
00594       // TMVA::Whatever claims to be in in math/tmva/inc/Whatever.h
00595       // but it needs to get included as TMVA/Whatever.h
00596       if (strstr(clname, "TMVA::"))
00597          out_dir.Prepend("TMVA/");
00598       if (strstr(clname, "RooStats::"))
00599          out_dir.Prepend("RooStats/");
00600    }
00601 
00602    return (out_dir.Length());
00603 }
00604 
00605 
00606 //______________________________________________________________________________
00607 bool THtml::TPathDefinition::GetFileNameFromInclude(const char* included, TString& out_fsname) const
00608 {
00609    // Set out_fsname to the full pathname corresponding to a file
00610    // included as "included". Return false if this file cannot be determined
00611    // or found. For ROOT, out_fsname corresponds to included prepended with
00612    // "include"; only THtml prefers to work on the original files, e.g.
00613    // core/base/inc/TObject.h instead of include/TObject.h, so the
00614    // default implementation searches the TFileSysDB for an entry with
00615    // basename(included) and with matching directory part, setting out_fsname
00616    // to the TFileSysEntry's path.
00617 
00618    if (!included) return false;
00619 
00620    out_fsname = included;
00621 
00622    if (!strncmp(included, "TMVA/", 5)) {
00623       out_fsname.Remove(0, 4);
00624       out_fsname.Prepend("tmva/inc");
00625       return true;
00626    }
00627    // special treatment for nested histfactory
00628    if (!strncmp(included, "RooStats/HistFactory/", 21)) {
00629       out_fsname.Remove(0, 20);
00630       out_fsname.Prepend("roofit/histfactory/inc");
00631       return true;
00632    }
00633    // special treatment for roostats
00634    if (!strncmp(included, "RooStats/", 9)) {
00635       out_fsname.Remove(0, 8);
00636       out_fsname.Prepend("roofit/roostats/inc");
00637       return true;
00638    }
00639 
00640    TString incBase(gSystem->BaseName(included));
00641    TList* bucket = GetOwner()->GetLocalFiles()->GetEntries().GetListForObject(incBase);
00642    if (!bucket) return false;
00643 
00644    TString alldir(gSystem->DirName(included));
00645    TObjArray* arrSubDirs = alldir.Tokenize("/");
00646    TIter iEntry(bucket);
00647    TFileSysEntry* entry = 0;
00648    while ((entry = (TFileSysEntry*) iEntry())) {
00649       if (incBase != entry->GetName()) continue;
00650       // find entry with matching enclosing directory
00651       THtml::TFileSysDir* parent = entry->GetParent();
00652       for (int i = arrSubDirs->GetEntries() - 1; parent && i >= 0; --i) {
00653          const TString& subdir(((TObjString*)(*arrSubDirs)[i])->String());
00654          if (!subdir.Length() || subdir == ".")
00655             continue;
00656          if (subdir == parent->GetName())
00657             parent = parent->GetParent();
00658          else parent = 0;
00659       }
00660       if (parent) {
00661          // entry found!
00662          entry->GetFullName(out_fsname, kFALSE);
00663          delete arrSubDirs;
00664          return true;
00665       }
00666    }
00667    delete arrSubDirs;
00668    return false;
00669 }
00670 
00671 //______________________________________________________________________________
00672 void THtml::TFileSysDir::Recurse(TFileSysDB* db, const char* path)
00673 {
00674    // Recursively fill entries by parsing the contents of path.
00675 
00676    TString dir(path);
00677    if (gDebug > 0 || GetLevel() < 2)
00678       Info("Recurse", "scanning %s...", path);
00679    TPMERegexp regexp(db->GetIgnore());
00680    dir += "/";
00681    void* hDir = gSystem->OpenDirectory(dir);
00682    const char* direntry = 0;
00683    while ((direntry = gSystem->GetDirEntry(hDir))) {
00684       if (!direntry[0] || direntry[0] == '.' || regexp.Match(direntry)) continue;
00685       TString entryPath(dir + direntry);
00686       if (gSystem->AccessPathName(entryPath, kReadPermission))
00687          continue;
00688       FileStat_t buf;
00689       gSystem->GetPathInfo(entryPath, buf);
00690       if (R_ISDIR(buf.fMode)) {
00691          // skip if we would nest too deeply,  and skip soft links:
00692          if (GetLevel() > db->GetMaxLevel()
00693 #ifndef R__WIN32
00694              || db->GetMapIno().GetValue(buf.fIno)
00695 #endif
00696              ) continue;
00697          TFileSysDir* subdir = new TFileSysDir(direntry, this);
00698          fDirs.Add(subdir);
00699 #ifndef R__WIN32
00700          db->GetMapIno().Add(buf.fIno, (Long_t)subdir);
00701 #endif
00702          subdir->Recurse(db, entryPath);
00703       } else {
00704          int delen = strlen(direntry);
00705          // only .cxx and .h are taken
00706          if (strcmp(direntry + delen - 4, ".cxx")
00707              && strcmp(direntry + delen - 2, ".h"))
00708             continue;
00709          TFileSysEntry* entry = new TFileSysEntry(direntry, this);
00710          db->GetEntries().Add(entry);
00711          fFiles.Add(entry);
00712       }
00713    } // while dir entry
00714    gSystem->FreeDirectory(hDir);
00715 }
00716 
00717 
00718 //______________________________________________________________________________
00719 void THtml::TFileSysDB::Fill()
00720 {
00721    // Recursively fill entries by parsing the path specified in GetName();
00722    // can be a THtml::GetDirDelimiter() delimited list of paths.
00723 
00724    TString dir;
00725    Ssiz_t posPath = 0;
00726    while (fName.Tokenize(dir, posPath, THtml::GetDirDelimiter())) {
00727       if (gSystem->AccessPathName(dir, kReadPermission)) {
00728          Warning("Fill", "Cannot read InputPath \"%s\"!", dir.Data());
00729          continue;
00730       }
00731       FileStat_t buf;
00732       gSystem->GetPathInfo(dir, buf);
00733       if (R_ISDIR(buf.fMode)) {
00734 #ifndef R__WIN32
00735          TFileSysRoot* prevroot = (TFileSysRoot*) (Long_t)GetMapIno().GetValue(buf.fIno);
00736          if (prevroot != 0) {
00737             Warning("Fill", "InputPath \"%s\" already present as \"%s\"!", dir.Data(), prevroot->GetName());
00738             continue;
00739          }
00740 #endif
00741          TFileSysRoot* root = new TFileSysRoot(dir, this);
00742          fDirs.Add(root);
00743 #ifndef R__WIN32
00744          GetMapIno().Add(buf.fIno, (Long_t)root);
00745 #endif
00746          root->Recurse(this, dir);
00747       } else {
00748          Warning("Fill", "Cannot read InputPath \"%s\"!", dir.Data());
00749       }
00750    }
00751 }
00752 
00753 
00754 ////////////////////////////////////////////////////////////////////////////////
00755 /* BEGIN_HTML
00756 <p>The THtml class is designed to easily document
00757 classes, code, and code related text files (like change logs). It generates HTML
00758 pages conforming to the XHTML 1.0 transitional specifications; an example of
00759 these pages is ROOT's own <a href="http://root.cern.ch/root/html/ClassIndex.html">
00760 reference guide</a>. This page was verified to be valid XHTML 1.0 transitional,
00761 which proves that all pages generated by THtml can be valid, as long as the user
00762 provided XHTML (documentation, header, etc) is valid. You can check the current
00763 THtml by clicking this icon:
00764 <a href="http://validator.w3.org/check?uri=referer"><img
00765         src="http://www.w3.org/Icons/valid-xhtml10"
00766         alt="Valid XHTML 1.0 Transitional" height="31" width="88" style="border: none;"/></a></p>
00767 Overview:
00768 <ol style="list-style-type: upper-roman;">
00769   <li><a href="#usage">Usage</a></li>
00770   <li><a href="#conf">Configuration</a>
00771   <ol><li><a href="#conf:input">Input files</a></li>
00772   <li><a href="#conf:output">Output directory</a></li>
00773   <li><a href="#conf:liblink">Linking other documentation</a></li>
00774   <li><a href="#conf:classdoc">Recognizing class documentation</a></li>
00775   <li><a href="#conf:tags">Author, copyright, etc.</a></li>
00776   <li><a href="#conf:header">Header and footer</a></li>
00777   <li><a href="#conf:search">Links to searches, home page, ViewVC</a></li>
00778   <li><a href="#conf:charset">HTML Charset</a></li>
00779   </ol></li>
00780   <li><a href="#syntax">Documentation syntax</a>
00781   <ol><li><a href="#syntax:classdesc">Class description</a></li>
00782   <li><a href="#syntax:classidx">Class index</a></li>
00783   <li><a href="#syntax:meth">Method documentation</a></li>
00784   <li><a href="#syntax:datamem">Data member documentation</a></li>
00785   </ol></li>
00786   <li><a href="#directive">Documentation directives</a>
00787   <ol><li><a href="#directive:html"><tt>BEGIN<!-- -->_HTML</tt> <tt>END<!-- -->_HTML</tt>: include 'raw' HTML</a></li>
00788   <li><a href="#directive:macro"><tt>BEGIN<!-- -->_MACRO</tt> <tt>END<!-- -->_MACRO</tt>: include a picture generated by a macro</a></li>
00789   <li><a href="#directive:latex"><tt>BEGIN<!-- -->_LATEX</tt> <tt>END<!-- -->_LATEX</tt>: include a latex picture</a></li>
00790   </ol></li>
00791   <li><a href="#index">Product and module index</a></li>
00792   <li><a href="#aux">Auxiliary files: style sheet, JavaScript, help page</a></li>
00793   <li><a href="#charts">Class Charts</a></li>
00794   <li><a href="#confvar">Configuration variables</a></li>
00795   <li><a href="#how">Behind the scenes</a></li>
00796 </ol>
00797 
00798 
00799 <h3><a name="usage">I. Usage</a></h3>
00800 These are typical things people do with THtml:
00801 <pre>
00802     root[] <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> html;                // create a <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> object
00803     root[] html.MakeAll();             // generate documentation for all changed classes
00804 </pre>
00805 or to run on just a few classes:
00806 <pre>
00807     root[] <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> html;                // create a <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> object
00808     root[] html.MakeIndex();           // create auxilliary files (style sheet etc) and indices
00809     root[] html.MakeClass("TMyClass"); // create documentation for TMyClass only
00810 </pre>
00811 To "beautify" (i.e. create links to documentation for class names etc) some text
00812 file or macro, use:
00813 <pre>
00814     root[] html.Convert( "hsimple.C", "Histogram example" )
00815 </pre>
00816 
00817 
00818 <h3><a name="conf">II. Configuration</a></h3>
00819 Most configuration options can be set as a call to THtml, or as a TEnv variable,
00820 which you can set in your .rootrc.
00821 
00822 <h4><a name="conf:input">II.1 Input files</a></h4>
00823 
00824 <p>In your .rootrc, define Root.Html.SourceDir to point to directories containing
00825 .cxx and .h files (see: <a href="http://root.cern.ch/root/html/TEnv.html">TEnv</a>)
00826 of the classes you want to document, or call THtml::SetInputDir()</p>
00827 
00828 <p>Example:</p><pre>
00829   Root.Html.SourceDir:  .:src:include
00830   Root.Html.Root:       http://root.cern.ch/root/html</pre>
00831 
00832 
00833 <h4><a name="conf:output">II.2 Output directory</a></h4>
00834 
00835 <p>The output directory can be specified using the Root.Html.OutputDir
00836 configuration variable (default value: "htmldoc"). If that directory
00837 doesn't exist <a href="http://root.cern.ch/root/html/THtml.html">THtml</a>
00838 will create it.</p>
00839 
00840 <p>Example:</p><pre>
00841   Root.Html.OutputDir:         htmldoc</pre>
00842 
00843 <h4><a name="conf:liblink">II.3 Linking other documentation</a></h4>
00844 
00845 <p>When trying to document a class, THtml searches for a source file in
00846 the directories set via SetInputDir(). If it cannot find it, it assumes
00847 that this class must have been documented before. Based on the library
00848 this class is defined in, it checks the configuration variable
00849 <tt>Root.Html.LibName</tt>, and creates a link using its value.
00850 Alternatively, you can set these URLs via THtml::SetLibURL().</p>
00851 
00852 <p>Example:<br/>
00853 If a class MyClass is defined in class mylibs/libMyLib.so, and .rootrc
00854 contains</p><pre>
00855   Root.Html.MyLib: ../mylib/</pre>
00856 <p>THtml will create a link to "../mylib/MyClass.html".</p>
00857 
00858 <p>The library name association can be set up using the rootmap facility.
00859 For the library in the example above, which contains a dictionary
00860 generated from the linkdef MyLinkdef.h, the command to generate the
00861 rootmap file is</p>
00862 <pre>  $ rlibmap -f -r rootmap -l mylib/libMyLib.so -d libCore.so -c MyLinkdef.h</pre>
00863 <p>Here, <tt>-r</tt> specifies that the entries for libMyLib should be updated,
00864 <tt>-l</tt> specifies the library we're dealing with, <tt>-d</tt> its
00865 dependencies, and <tt>-c</tt> its linkdef. The rootmap file must be within
00866 one of the <tt>LD_LIBRARY_PATH</tt> (or <tt>PATH</tt> for Windows) directories
00867 when ROOT is started, otherwise ROOT will not use it.</p>
00868 
00869 <h4><a name="conf:classdoc">II.4 Recognizing class documentation</a></h4>
00870 
00871 <p>The class documentation has to appear in the header file containing the
00872 class, right in front of its declaration. It is introduced by a string
00873 defined by Root.Html.Description or SetClassDocTag(). See the section on
00874 <a href="#syntax">documentation syntax</a> for further details.</p>
00875 
00876 <p>Example:</p><pre>
00877   Root.Html.Description:       //____________________</pre>
00878 
00879 <p>The class documentation will show which include statement is to be used
00880 and which library needs to be linked to access it.
00881 The include file name is determined via
00882 <a href="http://root.cern.ch/root/html/TClass.html#TClass:GetDeclFileName">
00883 TClass::GetDeclFileName()</a>;
00884 leading parts are removed if they match any of the ':' separated entries in
00885 THtml::GetIncludePath().</p>
00886 
00887 <h4><a name="conf:tags">II.5 Author, copyright, etc.</a></h4>
00888 
00889 <p>During the conversion,
00890 <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> will look for
00891 some strings ("tags") in the source file, which have to appear right in
00892 front of e.g. the author's name, copyright notice, etc. These tags can be
00893 defined with the following environment variables: Root.Html.Author,
00894 Root.Html.LastUpdate and Root.Html.Copyright, or with
00895 SetAuthorTag(), SetLastUpdateTag(), SetCopyrightTag().</p>
00896 
00897 <p>If the LastUpdate tag is not found, the current date and time are used.
00898 This is useful when using
00899 <a href="http://root.cern.ch/root/html/THtml.html#THtml:MakeAll">THtml::MakeAll()</a>'s
00900 default option force=kFALSE, in which case
00901 <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> generates
00902 documentation only for changed classes.</p>
00903 
00904 Authors can be a comma separated list of author entries. Each entry has
00905 one of the following two formats
00906 <ul><li><tt>Name (non-alpha)</tt>.
00907 <p><a href="http://root.cern.ch/root/html/THtml.html">THtml</a> will generate an
00908 HTML link for <tt>Name</tt>, taking the Root.Html.XWho configuration
00909 variable (defaults to "http://consult.cern.ch/xwho/people?") and adding
00910 all parts of the name with spaces replaces by '+'. Non-alphanumerical
00911 characters are printed out behind <tt>Name</tt>.</p>
00912 
00913 <p>Example:</p>
00914 <tt>// Author: Enrico Fermi</tt> appears in the source file.
00915 <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> will generate the link
00916 <tt>http://consult.cern.ch/xwho/people?Enrico+Fermi</tt>. This works well for
00917 people at CERN.</li>
00918 
00919 <li><tt>Name &lt;link&gt; Info</tt>.
00920 <p><a href="http://root.cern.ch/root/html/THtml.html">THtml</a> will generate
00921 an HTML link for <tt>Name</tt> as specified by <tt>link</tt> and print
00922 <tt>Info</tt> behind <tt>Name</tt>.</p>
00923 
00924 <p>Example:</p>
00925 <tt>// Author: Enrico Fermi &lt;http://www.enricos-home.it&gt;</tt> or<br/>
00926 <tt>// Author: Enrico Fermi &lt;mailto:enrico@fnal.gov&gt;</tt> in the
00927 source file. That's world compatible.</li>
00928 </ul>
00929 
00930 <p>Example (with defaults given):</p><pre>
00931       Root.Html.Author:     // Author:
00932       Root.Html.LastUpdate: // @(#)
00933       Root.Html.Copyright:  * Copyright
00934       Root.Html.XWho:       http://consult.cern.ch/xwho/people?</pre>
00935 
00936 
00937 <h4><a name="conf:header">II.6 Header and footer</a></h4>
00938 
00939 <p><a href="http://root.cern.ch/root/html/THtml.html">THtml</a> generates
00940 a default header and footer for all pages. You can
00941 specify your own versions with the configuration variables Root.Html.Header
00942 and Root.Html.Footer, or by calling SetHeader(), SetFooter().
00943 Both variables default to "", using the standard Root
00944 versions. If it has a "+" appended, <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> will
00945 write both versions (user and root) to a file, for the header in the order
00946 1st root, 2nd user, and for the footer 1st user, 2nd root (the root
00947 versions containing "&lt;html&gt;" and &lt;/html&gt; tags, resp).</p>
00948 
00949 <p>If you want to replace root's header you have to write a file containing
00950 all HTML elements necessary starting with the &lt;doctype&gt; tag and ending with
00951 (and including) the &lt;body&gt; tag. If you add your header it will be added
00952 directly after Root's &lt;body&gt; tag. Any occurrence of the string <tt>%TITLE%</tt>
00953 in the user's header file will be replaced by
00954 a sensible, automatically generated title. If the header is generated for a
00955 class, occurrences of <tt>%CLASS%</tt> will be replaced by the current class's name,
00956 <tt>%SRCFILE%</tt> and <tt>%INCFILE%</tt> by the name of the source and header file, resp.
00957 (as given by <a href="http://root.cern.ch/root/html/TClass.html#TClass:GetImplFileLine">TClass::GetImplFileName()</a>,
00958 <a href="http://root.cern.ch/root/html/TClass.html#TClass:GetImplFileLine">TClass::GetDeclFileName()</a>).
00959 If the header is not generated for a class, they will be replaced by "".</p>
00960 
00961 <p>Root's footer starts with the tag &lt;!--SIGNATURE--&gt;. It includes the
00962 author(s), last update, copyright, the links to the Root home page, to the
00963 user home page, to the index file (ClassIndex.html), to the top of the page
00964 and <tt>this page is automatically generated</tt> infomation. It ends with the
00965 tags <tt>&lt;/body&gt;&lt;/html&gt;</tt>. If you want to replace it,
00966 <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> will search for some
00967 tags in your footer: Occurrences of the strings <tt>%AUTHOR%</tt>, <tt>%UPDATE%</tt>, and
00968 <tt>%COPYRIGHT%</tt> are replaced by their
00969 corresponding values before writing the html file. The <tt>%AUTHOR%</tt> tag will be
00970 replaced by the exact string that follows Root.Html.Author, no link
00971 generation will occur.</p>
00972 
00973 
00974 <h4><a name="conf:search">II.7 Links to searches, home page, ViewVC</a></h4>
00975 
00976 <p>Additional parameters can be set by Root.Html.Homepage (address of the
00977 user's home page), Root.Html.SearchEngine (search engine for the class
00978 documentation), Root.Html.Search (search URL, where %u is replaced by the
00979 referer and %s by the escaped search expression), and a ViewVC base URL
00980 Root.Html.ViewCVS. For the latter, the file name is appended or, if
00981 the URL contains %f, %f is replaced by the file name.
00982 All values default to "".</p>
00983 
00984 <p>Examples:</p><pre>
00985       Root.Html.Homepage:     http://www.enricos-home.it
00986       Root.Html.SearchEngine: http://root.cern.ch/root/Search.phtml
00987       Root.Html.Search:       http://www.google.com/search?q=%s+site%3A%u</pre>
00988 
00989 
00990 <h4><a name="conf:charset">II.8 HTML Charset</a></h4>
00991 
00992 <p>XHTML 1.0 transitional recommends the specification of the charset in the
00993 content type meta tag, see e.g. <a href="http://www.w3.org/TR/2002/REC-xhtml1-20020801/">http://www.w3.org/TR/2002/REC-xhtml1-20020801/</a>
00994 <a href="http://root.cern.ch/root/html/THtml.html">THtml</a> generates it for the HTML output files. It defaults to ISO-8859-1, and
00995 can be changed using Root.Html.Charset.</p>
00996 
00997 <p>Example:</p><pre>
00998       Root.Html.Charset:      EUC-JP</pre>
00999 
01000 <h3><a name="syntax">III. Documentation syntax</a></h3>
01001 <h4><a name="syntax:classdesc">III.1 Class description</a></h4>
01002 
01003 <p>A class description block, which must be placed before the first
01004 member function, has a following form:</p>
01005 <pre>
01006 ////////////////////////////////////////////////////////////////
01007 //                                                            //
01008 // TMyClass                                                   //
01009 //                                                            //
01010 // This is the description block.                             //
01011 //                                                            //
01012 ////////////////////////////////////////////////////////////////
01013 </pre>
01014 <p>The environment variable Root.Html.Description
01015 (see: <a href="http://root.cern.ch/root/html/TEnv.html">TEnv</a>) contains
01016 the delimiter string (default value: <tt>//_________________</tt>). It means
01017 that you can also write your class description block like this:</p>
01018 <pre>
01019    //_____________________________________________________________
01020    // A description of the class starts with the line above, and
01021    // will take place here !
01022    //
01023 </pre>
01024 <p>Note that <b><i>everything</i></b> until the first non-commented line is considered
01025 as a valid class description block.</p>
01026 
01027 <h4><a name="syntax:classidx">III.2 Class index</a></h4>
01028 
01029 <p>All classes to be documented will have an entry in the ClassIndex.html,
01030 showing their name with a link to their documentation page and a miniature
01031 description. This discription for e.g. the class MyClass has to be given
01032 in MyClass's header as a comment right after ClassDef(MyClass, n).</p>
01033 
01034 <h4><a name="syntax:meth">III.3 Method documentation</a></h4>
01035 <p>A member function description block starts immediately after '{'
01036 and looks like this:</p>
01037 <pre>
01038    void TWorld::HelloWorldFunc(string *text)
01039    {
01040       // This is an example of description for the
01041       // TWorld member function
01042 
01043       helloWorld.Print( text );
01044    }
01045 </pre>
01046 Like in a class description block, <b><i>everything</i></b> until the first
01047 non-commented line is considered as a valid member function
01048 description block.
01049 
01050 If the rootrc variable <tt>Root.Html.DescriptionStyle</tt> is set to
01051 <tt>Doc++</tt> THtml will also look for method documentation in front of
01052 the function implementation. This feature is not recommended; source code
01053 making use of this does not comply to the ROOT documentation standards, which
01054 means future versions of THtml might not support it anymore.
01055 
01056 <h4><a name="syntax:datamem">III.4 Data member documentation</a></h4>
01057 
01058 <p>Data members are documented by putting a C++ comment behind their
01059 declaration in the header file, e.g.</p>
01060 <pre>
01061    int fIAmADataMember; // this is a data member
01062 </pre>
01063 
01064 
01065 <h3><a name="directive">IV. Documentation directives</a></h3>
01066 <em>NOTE that THtml does not yet support nested directives
01067 (i.e. latex inside html etc)!</em>
01068 
01069 <h4><a name="directive:html">IV.1 <tt>BEGIN<!-- -->_HTML</tt> <tt>END<!-- -->_HTML</tt>: include 'raw' HTML</a></h4>
01070 
01071 <p>You can insert pure html code into your documentation comments. During the
01072 generation of the documentation, this code will be inserted as is
01073 into the html file.</p>
01074 <p>Pure html code must be surrounded by the keywords
01075 <tt>BEGIN<!-- -->_HTML</tt> and <tt>END<!-- -->_HTML</tt>, where the
01076 case is ignored.
01077 An example of pure html code is this class description you are reading right now.
01078 THtml uses a
01079 <a href="http://root.cern.ch/root/html/TDocHtmlDirective.html">TDocHtmlDirective</a>
01080 object to process this directive.</p>
01081 
01082 <h4><a name="directive:macro">IV.2 <tt>BEGIN<!-- -->_MACRO</tt> <tt>END<!-- -->_MACRO</tt>: include a picture generated by a macro</a></h4>
01083 
01084 <p>THtml can create images from scripts. You can either call an external
01085 script by surrounding it by "begin_macro"/"end_macro", or include an unnamed
01086 macro within these keywords. The macro should return a pointer to an object;
01087 this object will then be saved as a GIF file.</p>
01088 <p>Objects deriving from
01089 <a href="http://root.cern.ch/root/html/TGObject.html">TGObject</a> (GUI elements)
01090 will need to run in graphics mode (non-batch). You must specify this as a parameter:
01091 "Begin_macro(GUI)...".
01092 To create a second tab that displays the source of the macro you can specify
01093 the argument "Begin_macro(source)...".
01094 Of course you can combine them,
01095 e.g. as "Begin_macro(source,gui)...".
01096 THtml uses a
01097 <a href="http://root.cern.ch/root/html/TDocMacroDirective.html">TDocMacroDirective</a>
01098 object to process this directive.</p>
01099 <p>This is an example:</p> END_HTML
01100 BEGIN_MACRO(source)
01101 {
01102   TCanvas* macro_example_canvas = new TCanvas("macro_example_canvas", "", 150, 150);
01103   macro_example_canvas->SetBorderSize(0);
01104   macro_example_canvas->SetFillStyle(1001);
01105   macro_example_canvas->SetFillColor(kWhite);
01106   macro_example_canvas->cd();
01107   TArc* macro_example_arc = new TArc(0.5,0.32,0.11,180,360);
01108   macro_example_arc->Draw();
01109   TEllipse* macro_example_ellipsis = new TEllipse(0.42,0.58,0.014,0.014,0,360,0);
01110   macro_example_ellipsis->SetFillStyle(0);
01111   macro_example_ellipsis->Draw();
01112   macro_example_ellipsis = new TEllipse(0.58,0.58,0.014,0.014,0,360,0);
01113   macro_example_ellipsis->SetFillStyle(0);
01114   macro_example_ellipsis->Draw();
01115   macro_example_ellipsis = new TEllipse(0.50,0.48,0.22,0.32,0,360,0);
01116   macro_example_ellipsis->SetFillStyle(0);
01117   macro_example_ellipsis->Draw();
01118   TLine* macro_example_line = new TLine(0.48,0.53,0.52,0.41);
01119   macro_example_line->Draw();
01120   return macro_example_canvas;
01121 }
01122 END_MACRO
01123 
01124 BEGIN_HTML
01125 <h4><a name="directive:latex">IV.3 <tt>BEGIN<!-- -->_LATEX</tt> <tt>END<!-- -->_LATEX</tt>: include a latex picture</a></h4>
01126 
01127 <p>You can specify <a href="http://root.cern.ch/root/html/TLatex.html">TLatex</a>
01128 style text and let THtml convert it into an image by surrounding it by "Begin_Latex", "End_Latex".
01129 You can have multiple lines, and e.g. align each line at the '=' sign by passing
01130 the argument <tt>separator='='</tt>. You can also specify how to align these parts;
01131 if you want the part left of the separator to be right aligned, and the right part
01132 to be left aligned, you could specify <tt>align='rl'</tt>.
01133 THtml uses a <a href="http://root.cern.ch/root/html/TDocLatexDirective.html">TDocLatexDirective</a>
01134 object to process the directive.
01135 This is an example output with arguments <tt>separator='=', align='rl'</tt>:</p>
01136 END_HTML BEGIN_LATEX(separator='=', align='rl')#kappa(x)^{2}=sin(x)^{x}
01137 x=#chi^{2} END_LATEX
01138 
01139 BEGIN_HTML
01140 
01141 <h3><a name="index">V. Product and module index</a></h3>
01142 
01143 <p><a href="#THtml:MakeIndex">THtml::MakeIndex()</a> will generate index files for classes
01144 and types, all modules, and the product which you can set by
01145 <a href="#THtml:SetProductName">THtml::SetProductName()</a>.
01146 THtml will make use of external documentation in the module and product index,
01147 either by linking it or by including it.
01148 For the product THtml will include files found in the directory defined by
01149 <a href="#THtml:SetProductDocDir">THtml::SetProductDocDir()</a>.
01150 The files for modules are searched based on the source file directory of the
01151 module's classes; the (possibly relative) path set by
01152 <a href="#THtml:SetModuleDocPath">THtml::SetModuleDocPath()</a> will guide THtml
01153 to the files.</p>
01154 
01155 <p>A filename starting with "index." will be included in the index page;
01156 all other files will be linked.
01157 Only files ending on <tt>.html</tt> or <tt>.txt</tt> will be taken into account;
01158 the text files will first be run through
01159 <a href="#THtml:Convert">THtml::Convert()</a>.
01160 You can see an example <a href="http://root.cern.ch/root/html/HIST_Index.html">here</a>;
01161 the part between "Index of HIST classes" and "Jump to" is created by parsing
01162 the module's doc directory.</p>
01163 
01164 <h3><a name="aux">VI. Auxiliary files: style sheet, JavaScript, help page</a></h3>
01165 
01166 <p>The documentation pages share a common set of javascript and CSS files. They
01167 are generated automatically when running <a href="#THtml:MakeAll">MakeAll()</a>;
01168 they can be generated on
01169 demand by calling <a href="#THtml:CreateAuxiliaryFiles">CreateAuxiliaryFiles()</a>.</p>
01170 
01171 
01172 <h3><a name="charts">VII. Class Charts</a></h3>
01173 THtml can generate a number of graphical representations for a class, which
01174 are displayed as a tabbed set of imaged ontop of the class description.
01175 It can show the inheritance, inherited and hidden members, directly and
01176 indirectly included files, and library dependencies.
01177 
01178 These graphs are generated using the <a href="http://www.graphviz.org/">Graphviz</a>
01179 package. You can install it from <a href="http://www.graphviz.org">http://www.graphviz.org</a>.
01180 You can either put it into your $PATH, or tell THtml where to find it by calling
01181 <a href="#THtml:SetDotDir">SetDotDir()</a>.
01182 
01183 
01184 <h3><a name="confvar">VIII. Configuration variables</a></h3>
01185 
01186 <p>Here is a list of all configuration variables that are known to THtml.
01187 You can set them in your .rootrc file, see
01188 <a href="http://root.cern.ch/root/html/TEnv.html">TEnv</a>.</p>
01189 
01190 <pre>
01191   Root.Html.OutputDir    (default: htmldoc)
01192   Root.Html.SourceDir    (default: .:src/:include/)
01193   Root.Html.Author       (default: // Author:) - start tag for authors
01194   Root.Html.LastUpdate   (default: // @(#)) - start tag for last update
01195   Root.Html.Copyright    (default:  * Copyright) - start tag for copyright notice
01196   Root.Html.Description  (default: //____________________ ) - start tag for class descr
01197   Root.Html.HomePage     (default: ) - URL to the user defined home page
01198   Root.Html.Header       (default: ) - location of user defined header
01199   Root.Html.Footer       (default: ) - location of user defined footer
01200   Root.Html.Root         (default: ) - URL of Root's class documentation
01201   Root.Html.SearchEngine (default: ) - link to the search engine
01202   Root.Html.Search       (defualt: ) - link to search by replacing "%s" with user input
01203   Root.Html.ViewCVS      (default: ) - URL of ViewCVS base
01204   Root.Html.XWho         (default: http://consult.cern.ch/xwho/people?) - URL of CERN's xWho
01205   Root.Html.Charset      (default: ISO-8859-1) - HTML character set
01206 </pre>
01207 
01208 <h3><a name="how">IX. Behind the scene</a></h3>
01209 
01210 <p>Internally, THtml is just an API class that sets up the list of known
01211 classes, and forwards API invocations to the "work horses".
01212 <a href="http://root.cern.ch/root/html/TDocOutput.html">TDocOutput</a>
01213 generates the output by letting a
01214 <a href="http://root.cern.ch/root/html/TDocParser.html">TDocParser</a>
01215 object parse the sources, which in turn invokes objects deriving from
01216 <a href="http://root.cern.ch/root/html/TDocDirective.html">TDocDirective</a>
01217 to process directives.</p>
01218 
01219 END_HTML */
01220 ////////////////////////////////////////////////////////////////////////////////
01221 
01222 ClassImp(THtml)
01223 //______________________________________________________________________________
01224 THtml::THtml():
01225    fCounterFormat("%12s %5s %s"),
01226    fProductName("(UNKNOWN PRODUCT)"),
01227    fThreadedClassIter(0), fThreadedClassCount(0), fMakeClassMutex(0),
01228    fGClient(0), fPathDef(0), fModuleDef(0), fFileDef(0),
01229    fLocalFiles(0), fBatch(kFALSE)
01230 {
01231    // Create a THtml object.
01232    // In case output directory does not exist an error
01233    // will be printed and gHtml stays 0 also zombie bit will be set.
01234 
01235    // check for source directory
01236    fPathInfo.fInputPath = gEnv->GetValue("Root.Html.SourceDir", "./:src/:include/");
01237 
01238    // check for output directory
01239    SetOutputDir(gEnv->GetValue("Root.Html.OutputDir", "htmldoc"));
01240 
01241    fLinkInfo.fXwho = gEnv->GetValue("Root.Html.XWho", "http://consult.cern.ch/xwho/people?");
01242    fLinkInfo.fROOTURL = gEnv->GetValue("Root.Html.Root", "http://root.cern.ch/root/html");
01243    fDocSyntax.fClassDocTag = gEnv->GetValue("Root.Html.Description", "//____________________");
01244    fDocSyntax.fAuthorTag = gEnv->GetValue("Root.Html.Author", "// Author:");
01245    fDocSyntax.fLastUpdateTag = gEnv->GetValue("Root.Html.LastUpdate", "// @(#)");
01246    fDocSyntax.fCopyrightTag = gEnv->GetValue("Root.Html.Copyright", "* Copyright");
01247    fOutputStyle.fHeader = gEnv->GetValue("Root.Html.Header", "");
01248    fOutputStyle.fFooter = gEnv->GetValue("Root.Html.Footer", "");
01249    fLinkInfo.fHomepage = gEnv->GetValue("Root.Html.Homepage", "");
01250    fLinkInfo.fSearchStemURL = gEnv->GetValue("Root.Html.Search", "");
01251    fLinkInfo.fSearchEngine = gEnv->GetValue("Root.Html.SearchEngine", "");
01252    fLinkInfo.fViewCVS = gEnv->GetValue("Root.Html.ViewCVS", "");
01253    fOutputStyle.fCharset = gEnv->GetValue("Root.Html.Charset", "ISO-8859-1");
01254    fDocSyntax.fDocStyle = gEnv->GetValue("Root.Html.DescriptionStyle", "");
01255 
01256    fDocEntityInfo.fClasses.SetOwner();
01257    fDocEntityInfo.fModules.SetOwner();
01258    // insert html object in the list of special ROOT objects
01259    if (!gHtml) {
01260       gHtml = this;
01261       gROOT->GetListOfSpecials()->Add(gHtml);
01262    }
01263 
01264 }
01265 
01266 
01267 //______________________________________________________________________________
01268 THtml::~THtml()
01269 {
01270 // Default destructor
01271 
01272    fDocEntityInfo.fClasses.Clear();
01273    fDocEntityInfo.fModules.Clear();
01274    if (gHtml == this) {
01275       gROOT->GetListOfSpecials()->Remove(gHtml);
01276       gHtml = 0;
01277    }
01278    delete fPathDef;
01279    delete fModuleDef;
01280    delete fFileDef;
01281    delete fLocalFiles;
01282 }
01283 
01284 //______________________________________________________________________________
01285 void THtml::AddMacroPath(const char* path)
01286 {
01287    // Add path to the directories to be searched for macro files
01288    // that are to be executed via the TDocMacroDirective
01289    // ("Begin_Macro"/"End_Macro"); relative to the source file
01290    // that the directive is run on.
01291 
01292    const char pathDelimiter =
01293 #ifdef R__WIN32
01294       ';';
01295 #else
01296       ':';
01297 #endif
01298    fPathInfo.fMacroPath += pathDelimiter;
01299    fPathInfo.fMacroPath += path;
01300 }
01301 
01302 
01303 //______________________________________________________________________________
01304 void THtml::CreateAuxiliaryFiles() const
01305 {
01306    // copy CSS, javascript file, etc to the output dir
01307    CreateJavascript();
01308    CreateStyleSheet();
01309    CopyFileFromEtcDir("HELP.html");
01310 }
01311 
01312 //______________________________________________________________________________
01313 const THtml::TModuleDefinition& THtml::GetModuleDefinition() const
01314 {
01315    // Return the TModuleDefinition (or derived) object as set by
01316    // SetModuleDefinition(); create and return a TModuleDefinition object
01317    // if none was set.
01318    if (!fModuleDef) {
01319       fModuleDef = new TModuleDefinition();
01320       fModuleDef->SetOwner(const_cast<THtml*>(this));
01321    }
01322    return *fModuleDef;
01323 }
01324 
01325 //______________________________________________________________________________
01326 const THtml::TFileDefinition& THtml::GetFileDefinition() const
01327 {
01328    // Return the TFileDefinition (or derived) object as set by
01329    // SetFileDefinition(); create and return a TFileDefinition object
01330    // if none was set.
01331    if (!fFileDef) {
01332       fFileDef = new TFileDefinition();
01333       fFileDef->SetOwner(const_cast<THtml*>(this));
01334    }
01335    return *fFileDef;
01336 }
01337 
01338 //______________________________________________________________________________
01339 const THtml::TPathDefinition& THtml::GetPathDefinition() const
01340 {
01341    // Return the TModuleDefinition (or derived) object as set by
01342    // SetModuleDefinition(); create and return a TModuleDefinition object
01343    // if none was set.
01344    if (!fPathDef) {
01345       fPathDef = new TPathDefinition();
01346       fPathDef->SetOwner(const_cast<THtml*>(this));
01347    }
01348    return *fPathDef;
01349 }
01350 
01351 
01352 //______________________________________________________________________________
01353 const char* THtml::GetEtcDir() const
01354 {
01355 // Get the directory containing THtml's auxiliary files ($ROOTSYS/etc/html)
01356 
01357    if (fPathInfo.fEtcDir.Length())
01358       return fPathInfo.fEtcDir;
01359 
01360    R__LOCKGUARD(GetMakeClassMutex());
01361 
01362    fPathInfo.fEtcDir = "html";
01363 
01364 #ifdef ROOTETCDIR
01365    gSystem->PrependPathName(ROOTETCDIR, fPathInfo.fEtcDir);
01366 #else
01367    gSystem->PrependPathName("etc", fPathInfo.fEtcDir);
01368 # ifdef ROOTPREFIX
01369    gSystem->PrependPathName(ROOTPREFIX, fPathInfo.fEtcDir);
01370 # else
01371    if (getenv("ROOTSYS"))
01372       gSystem->PrependPathName(getenv("ROOTSYS"), fPathInfo.fEtcDir);
01373 # endif
01374 #endif
01375 
01376    return fPathInfo.fEtcDir;
01377 }
01378 
01379 
01380 //______________________________________________________________________________
01381 TClassDocInfo *THtml::GetNextClass()
01382 {
01383    // Return the next class to be generated for MakeClassThreaded.
01384 
01385    if (!fThreadedClassIter) return 0;
01386 
01387    R__LOCKGUARD(GetMakeClassMutex());
01388 
01389    TClassDocInfo* classinfo = 0;
01390    while ((classinfo = (TClassDocInfo*)(*fThreadedClassIter)())
01391           && !classinfo->IsSelected()) { }
01392 
01393    if (!classinfo) {
01394       delete fThreadedClassIter;
01395       fThreadedClassIter = 0;
01396    }
01397 
01398    fCounter.Form("%5d", fDocEntityInfo.fClasses.GetSize() - fThreadedClassCount++);
01399 
01400    return classinfo;
01401 }
01402 
01403 
01404 //______________________________________________________________________________
01405 const char* THtml::GetURL(const char* lib /*=0*/) const
01406 {
01407    // Get the documentation URL for library lib.
01408    // If lib == 0 or no documentation URL has been set for lib, return the ROOT
01409    // documentation URL. The return value is always != 0.
01410 
01411    R__LOCKGUARD(GetMakeClassMutex());
01412 
01413    if (lib && strlen(lib)) {
01414       std::map<std::string, TString>::const_iterator iUrl = fLinkInfo.fLibURLs.find(lib);
01415       if (iUrl != fLinkInfo.fLibURLs.end()) return iUrl->second;
01416       return gEnv->GetValue(TString("Root.Html.") + lib, fLinkInfo.fROOTURL);
01417    }
01418    return fLinkInfo.fROOTURL;
01419 }
01420 
01421 //______________________________________________________________________________
01422 Bool_t THtml::HaveDot()
01423 {
01424    // Check whether dot is available in $PATH or in the directory set
01425    // by SetDotPath()
01426 
01427    if (fPathInfo.fFoundDot != PathInfo_t::kDotUnknown)
01428       return (fPathInfo.fFoundDot == PathInfo_t::kDotFound);
01429 
01430    R__LOCKGUARD(GetMakeClassMutex());
01431 
01432    Info("HaveDot", "Checking for Graphviz (dot)...");
01433    TString runDot("dot");
01434    if (fPathInfo.fDotDir.Length())
01435       gSystem->PrependPathName(fPathInfo.fDotDir, runDot);
01436    runDot += " -V";
01437    if (gDebug > 3)
01438       Info("HaveDot", "Running: %s", runDot.Data());
01439    if (gSystem->Exec(runDot)) {
01440       fPathInfo.fFoundDot = PathInfo_t::kDotNotFound;
01441       return kFALSE;
01442    }
01443    fPathInfo.fFoundDot = PathInfo_t::kDotFound;
01444    return kTRUE;
01445 
01446 }
01447 
01448 //______________________________________________________________________________
01449 void THtml::HelperDeleted(THtml::THelperBase* who)
01450 {
01451    // Inform the THtml object that one of its helper objects was deleted.
01452    // Called by THtml::HelperBase::~HelperBase().
01453 
01454    THelperBase* helpers[3] = {fPathDef, fModuleDef, fFileDef};
01455    for (int i = 0; who && i < 3; ++i)
01456       if (who == helpers[i])
01457          helpers[i] = who = 0;
01458 }
01459 
01460 
01461 //______________________________________________________________________________
01462 void THtml::Convert(const char *filename, const char *title,
01463                     const char *dirname /*= ""*/, const char *relpath /*= "../"*/,
01464                     Int_t includeOutput /* = kNoOutput */,
01465                     const char* context /* = "" */)
01466 {
01467 // It converts a single text file to HTML
01468 //
01469 //
01470 // Input: filename - name of the file to convert
01471 //        title    - title which will be placed at the top of the HTML file
01472 //        dirname  - optional parameter, if it's not specified, output will
01473 //                   be placed in htmldoc/examples directory.
01474 //        relpath  - optional parameter pointing to the THtml generated doc
01475 //                   on the server, relative to the current page.
01476 //        includeOutput - if != kNoOutput, run the script passed as filename and
01477 //                   store all created canvases in PNG files that are
01478 //                   shown next to the converted source. Bitwise-ORing with
01479 //                   re-runs the script even if output PNGs exist that are newer
01480 //                   than the script. If kCompiledOutput is passed, the script is
01481 //                   run through ACLiC (.x filename+)
01482 //        context  - line shown verbatim at the top of the page; e.g. for links.
01483 //                   If context is non-empty it is expected to also print the
01484 //                   title.
01485 //
01486 //  NOTE: Output file name is the same as filename, but with extension .html
01487 //
01488 
01489    gROOT->GetListOfGlobals(kTRUE);        // force update of this list
01490    CreateListOfClasses("*");
01491 
01492    const char *dir;
01493 
01494    // if it's not defined, make the "examples" as a default directory
01495    if (!*dirname) {
01496       gSystem->ExpandPathName(fPathInfo.fOutputDir);
01497       dir = gSystem->ConcatFileName(fPathInfo.fOutputDir, "examples");
01498    } else
01499       dir = dirname;
01500 
01501    // create directory if necessary
01502    if (gSystem->AccessPathName(dir))
01503       gSystem->MakeDirectory(dir);
01504 
01505    // find a file
01506    char *cRealFilename =
01507        gSystem->Which(fPathInfo.fInputPath, filename, kReadPermission);
01508 
01509    if (!cRealFilename) {
01510       Error("Convert", "Can't find file '%s' !", filename);
01511       return;
01512    }
01513 
01514    TString realFilename(cRealFilename);
01515    delete[] cRealFilename;
01516    cRealFilename = 0;
01517 
01518    // open source file
01519    ifstream sourceFile;
01520    sourceFile.open(realFilename, ios::in);
01521 
01522    if (!sourceFile.good()) {
01523       Error("Convert", "Can't open file '%s' !", realFilename.Data());
01524       return;
01525    }
01526 
01527    if (gSystem->AccessPathName(dir)) {
01528       Error("Convert",
01529             "Directory '%s' doesn't exist, or it's write protected !", dir);
01530       return;
01531    }
01532    char *tmp1 =
01533        gSystem->ConcatFileName(dir, gSystem->BaseName(filename));
01534 
01535    TDocOutput output(*this);
01536    if (!fGClient)
01537       gROOT->ProcessLine(TString::Format("*((TGClient**)0x%lx) = gClient;",
01538                                          (ULong_t)&fGClient));
01539    if (includeOutput && !fGClient)
01540       Warning("Convert", "Output requested but cannot initialize graphics: GUI  and GL windows not be available");
01541    output.Convert(sourceFile, realFilename, tmp1, title, relpath, includeOutput, context, fGClient);
01542 
01543    if (tmp1)
01544       delete[]tmp1;
01545    tmp1 = 0;
01546 }
01547 
01548 //______________________________________________________________________________
01549 void  THtml::GetModuleNameForClass(TString& module, TClass* cl) const
01550 {
01551    // Return the module name for a given class.
01552    // Use the cached information from fDocEntityInfo.fClasses.
01553 
01554    module = "(UNKNOWN)";
01555    if (!cl) return;
01556 
01557    TClassDocInfo* cdi = (TClassDocInfo*)fDocEntityInfo.fClasses.FindObject(cl->GetName());
01558    if (!cdi || !cdi->GetModule())
01559       return;
01560    module = cdi->GetModule()->GetName();
01561 }
01562 
01563 
01564 //______________________________________________________________________________
01565 void THtml::CreateListOfClasses(const char* filter)
01566 {
01567 // Create the list of all known classes
01568 
01569    if (fDocEntityInfo.fClasses.GetSize() && fDocEntityInfo.fClassFilter == filter)
01570       return;
01571 
01572    Info("CreateListOfClasses", "Initializing - this might take a while...");
01573    // get total number of classes
01574    Int_t totalNumberOfClasses = gClassTable->Classes();
01575 
01576    // allocate memory
01577    fDocEntityInfo.fClasses.Clear();
01578    fDocEntityInfo.fModules.Clear();
01579 
01580    fDocEntityInfo.fClassFilter = filter;
01581 
01582    // start from begining
01583    gClassTable->Init();
01584    if (filter && (!filter[0] || !strcmp(filter, "*")))
01585       filter = ".*";
01586    TString reg = filter;
01587    TPMERegexp re(reg);
01588 
01589    bool skipROOTClasses = false;
01590    std::set<std::string> rootLibs;
01591    TList classesDeclFileNotFound;
01592    TList classesImplFileNotFound;
01593 
01594    // pre-run TObject at i == -1
01595    for (Int_t i = -1; i < totalNumberOfClasses; i++) {
01596 
01597       // get class name
01598       const char *cname = 0;
01599       if (i < 0) cname = "TObject";
01600       else cname = gClassTable->Next();
01601 
01602       if (i >= 0 && !strcmp(cname, "TObject")) {
01603          // skip the second iteration on TObject
01604          continue;
01605       }
01606 
01607       // This is a hack for until after Cint and Reflex are one.
01608       if (strstr(cname, "__gnu_cxx::")) continue;
01609 
01610       // get class & filename - use TROOT::GetClass, as we also
01611       // want those classes without decl file name!
01612       TClass *classPtr = TClass::GetClass((const char *) cname, kTRUE);
01613       if (!classPtr) continue;
01614 
01615       std::string shortName(ShortType(cname));
01616       cname = shortName.c_str();
01617 
01618       TString s = cname;
01619       Bool_t matchesSelection = re.Match(s);
01620 
01621 
01622       TString hdr;
01623       TString hdrFS;
01624       TString src;
01625       TString srcFS;
01626       TString htmlfilename;
01627       TFileSysEntry* fse = 0;
01628 
01629       TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(cname);
01630       if (cdi) {
01631          hdr = cdi->GetDeclFileName();
01632          hdrFS = cdi->GetDeclFileSysName();
01633          src = cdi->GetImplFileName();
01634          srcFS = cdi->GetImplFileSysName();
01635          htmlfilename = cdi->GetHtmlFileName();
01636       }
01637 
01638       if (!hdrFS.Length()) {
01639          if (!GetFileDefinition().GetDeclFileName(classPtr, hdr, hdrFS, &fse)) {
01640             // we don't even know where the class is defined;
01641             // just skip. Silence if it doesn't match the selection anyway
01642             if (i == -1 ) {
01643                skipROOTClasses = true;
01644                Info("CreateListOfClasses", "Cannot find header file for TObject at %s given the input path %s.",
01645                   classPtr->GetDeclFileName(), GetInputPath().Data());
01646                Info("CreateListOfClasses", "Assuming documentation is not for ROOT classes, or you need to pass "
01647                   "the proper directory to THtml::SetInputPath() so I can find %s.", classPtr->GetDeclFileName());
01648                continue;
01649             }
01650             // ignore STL
01651             if (classPtr->GetDeclFileName() && !strncmp(classPtr->GetDeclFileName(), "prec_stl/", 9))
01652                continue;
01653             if (skipROOTClasses) {
01654                if (classPtr->GetSharedLibs() && classPtr->GetSharedLibs()[0]) {
01655                   std::string lib(classPtr->GetSharedLibs());
01656                   size_t posSpace = lib.find(' ');
01657                   if (posSpace != std::string::npos)
01658                      lib.erase(posSpace);
01659                   if (rootLibs.find(lib) == rootLibs.end()) {
01660 #ifdef ROOTLIBDIR
01661                      TString rootlibdir = ROOTLIBDIR;
01662 #else
01663                      TString rootlibdir = "lib";
01664                      gSystem->PrependPathName(gRootDir, rootlibdir);
01665 #endif
01666                      TString sLib(lib);
01667                      if (sLib.Index('.') == -1) {
01668                         sLib += ".";
01669                         sLib += gSystem->GetSoExt();
01670                      }
01671                      gSystem->PrependPathName(rootlibdir, sLib);
01672                      if (gSystem->AccessPathName(sLib))
01673                         // the library doesn't exist in $ROOTSYS/lib, so it's not
01674                         // a root lib and we need to tell the user.
01675                         classesDeclFileNotFound.AddLast(classPtr);
01676                      else rootLibs.insert(lib);
01677                   } // end "if rootLibs does not contain lib"
01678                } else {
01679                   // lib name unknown
01680                   static const char* rootClassesToIgnore[] =
01681                   { "ColorStruct_t", "CpuInfo_t", "Event_t", "FileStat_t", "GCValues_t", "MemInfo_t",
01682                      "PictureAttributes_t", "Point_t", "ProcInfo_t", "ROOT", "ROOT::Fit",
01683                      "Rectangle_t", "RedirectHandle_t", "Segment_t", "SetWindowAttributes_t",
01684                      "SysInfo_t", "TCint", "UserGroup_t", "WindowAttributes_t", "timespec", 0};
01685                   static const char* rootClassStemsToIgnore[] =
01686                   { "ROOT::Math", "TKDTree", "TMatrixT", "TParameter", "vector", 0 };
01687                   static size_t rootClassStemsToIgnoreLen[] = {0, 0, 0, 0, 0};
01688                   static std::set<std::string> setRootClassesToIgnore;
01689                   if (setRootClassesToIgnore.empty()) {
01690                      for (int ii = 0; rootClassesToIgnore[ii]; ++ii)
01691                         setRootClassesToIgnore.insert(rootClassesToIgnore[ii]);
01692                      for (int ii = 0; rootClassStemsToIgnore[ii]; ++ii)
01693                         rootClassStemsToIgnoreLen[ii] = strlen(rootClassStemsToIgnore[ii]);
01694                   }
01695                   // only complain about this class if it should not be ignored:
01696                   if (setRootClassesToIgnore.find(cname) == setRootClassesToIgnore.end()) {
01697                      bool matched = false;
01698                      for (int ii = 0; !matched && rootClassStemsToIgnore[ii]; ++ii)
01699                         matched = !strncmp(cname, rootClassStemsToIgnore[ii], rootClassStemsToIgnoreLen[ii]);
01700                      if (!matched)
01701                         classesDeclFileNotFound.AddLast(classPtr);
01702                   }
01703                } // lib name known
01704                continue;
01705             } else {
01706                if (matchesSelection && (!classPtr->GetDeclFileName() || !strstr(classPtr->GetDeclFileName(),"prec_stl/")))
01707                   classesDeclFileNotFound.AddLast(classPtr);
01708                continue;
01709             }
01710          }
01711       }
01712 
01713       Bool_t haveSource = (srcFS.Length());
01714       if (!haveSource)
01715          haveSource = GetFileDefinition().GetImplFileName(classPtr, src, srcFS, fse ? 0 : &fse);
01716 
01717       if (!haveSource) {
01718          classesImplFileNotFound.AddLast(classPtr);
01719       }
01720 
01721       if (!htmlfilename.Length())
01722          GetHtmlFileName(classPtr, htmlfilename);
01723 
01724       if (!cdi) {
01725          cdi = new TClassDocInfo(classPtr, htmlfilename, hdrFS, srcFS, hdr, src);
01726          fDocEntityInfo.fClasses.Add(cdi);
01727       } else {
01728          cdi->SetDeclFileName(hdr);
01729          cdi->SetImplFileName(src);
01730          cdi->SetDeclFileSysName(hdrFS);
01731          cdi->SetImplFileSysName(srcFS);
01732          cdi->SetHtmlFileName(htmlfilename);
01733       }
01734 
01735       cdi->SetSelected(matchesSelection);
01736 
01737       TString modulename;
01738       GetModuleDefinition().GetModule(classPtr, fse, modulename);
01739       if (!modulename.Length() || modulename == "USER")
01740          GetModuleNameForClass(modulename, classPtr);
01741 
01742       TModuleDocInfo* module = (TModuleDocInfo*) fDocEntityInfo.fModules.FindObject(modulename);
01743       if (!module) {
01744          bool moduleSelected = cdi->IsSelected();
01745 
01746          TString parentModuleName(gSystem->DirName(modulename));
01747          TModuleDocInfo* super = 0;
01748          if (parentModuleName.Length() && parentModuleName != ".") {
01749             super = (TModuleDocInfo*) fDocEntityInfo.fModules.FindObject(parentModuleName);
01750             if (!super) {
01751                // create parents:
01752                TString token;
01753                Ssiz_t pos = 0;
01754                while (parentModuleName.Tokenize(token, pos, "/")) {
01755                   if (!token.Length() || token == ".") continue;
01756                   super = new TModuleDocInfo(token, super);
01757                   super->SetSelected(moduleSelected);
01758                   fDocEntityInfo.fModules.Add(super);
01759                }
01760             }
01761          }
01762          module = new TModuleDocInfo(modulename, super);
01763          module->SetSelected(moduleSelected);
01764          fDocEntityInfo.fModules.Add(module);
01765       }
01766 
01767       if (module) {
01768          module->AddClass(cdi);
01769          cdi->SetModule(module);
01770          if (cdi->HaveSource() && cdi->IsSelected())
01771             module->SetSelected();
01772       }
01773 
01774       // clear the typedefs; we fill them later
01775       cdi->GetListOfTypedefs().Clear();
01776 
01777       if (gDebug > 0)
01778          Info("CreateListOfClasses", "Adding class %s, module %s (%sselected)",
01779               cdi->GetName(), module ? module->GetName() : "[UNKNOWN]",
01780               cdi->IsSelected() ? "" : "not ");
01781    }
01782 
01783 
01784 
01785    bool cannotFind = false;
01786    if (!classesDeclFileNotFound.IsEmpty()) {
01787       Warning("CreateListOfClasses",
01788          "Cannot find the header for the following classes [reason]:");
01789       TIter iClassesDeclFileNotFound(&classesDeclFileNotFound);
01790       TClass* iClass = 0;
01791       while ((iClass = (TClass*)iClassesDeclFileNotFound())) {
01792          if (iClass->GetDeclFileName() && iClass->GetDeclFileName()[0]) {
01793             Warning("CreateListOfClasses", "   %s [header %s not found]", iClass->GetName(), iClass->GetDeclFileName());
01794             cannotFind = true;
01795          } else
01796             Warning("CreateListOfClasses", "   %s [header file is unknown]", iClass->GetName());
01797       }
01798    }
01799 
01800    if (!classesImplFileNotFound.IsEmpty() && gDebug > 3) {
01801       Warning("CreateListOfClasses",
01802          "Cannot find the source file for the following classes [reason]:");
01803       TIter iClassesDeclFileNotFound(&classesImplFileNotFound);
01804       TClass* iClass = 0;
01805       while ((iClass = (TClass*)iClassesDeclFileNotFound())) {
01806          if (iClass->GetDeclFileName() && iClass->GetDeclFileName()[0]) {
01807             Info("CreateListOfClasses", "   %s [source %s not found]", iClass->GetName(), iClass->GetImplFileName());
01808             cannotFind = true;
01809          } else
01810             Info("CreateListOfClasses", "   %s [source file is unknown, add \"ClassImpl(%s)\" to source file if it exists]",
01811                iClass->GetName(), iClass->GetName());
01812       }
01813    }
01814    if (cannotFind) {
01815       Warning("CreateListOfClasses", "THtml cannot find all headers and sources. ");
01816       Warning("CreateListOfClasses",
01817          "You might need to adjust the input path (currently %s) by calling THtml::SetInputDir()",
01818          GetInputPath().Data());
01819    }
01820 
01821    // fill typedefs
01822    TIter iTypedef(gROOT->GetListOfTypes());
01823    TDataType* dt = 0;
01824    TDocOutput output(*this);
01825    while ((dt = (TDataType*) iTypedef())) {
01826       if (dt->GetType() != -1) continue;
01827       TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(dt->GetFullTypeName());
01828       if (cdi) {
01829          cdi->GetListOfTypedefs().Add(dt);
01830          if (gDebug > 1)
01831             Info("CreateListOfClasses", "Adding typedef %s to class %s",
01832                  dt->GetName(), cdi->GetName());
01833 
01834          bool inNamespace = true;
01835          TString surroundingNamespace(dt->GetName());
01836          Ssiz_t posTemplate = surroundingNamespace.Last('>');
01837          inNamespace = inNamespace && (posTemplate == kNPOS);
01838          if (inNamespace) {
01839             Ssiz_t posColumn = surroundingNamespace.Last(':');
01840             if (posColumn != kNPOS) {
01841                surroundingNamespace.Remove(posColumn - 1);
01842                TClass* clSurrounding = GetClass(surroundingNamespace);
01843                inNamespace = inNamespace && (!clSurrounding || IsNamespace(clSurrounding));
01844             }
01845          }
01846          if (inNamespace && cdi->GetModule()) {
01847             TString htmlfilename(dt->GetName());
01848             output.NameSpace2FileName(htmlfilename);
01849             htmlfilename += ".html";
01850             TClassDocInfo* cdiTD = new TClassDocInfo(dt, htmlfilename);
01851             cdiTD->SetModule(cdi->GetModule());
01852             cdiTD->SetSelected(cdi->IsSelected());
01853             cdi->GetModule()->AddClass(cdiTD);
01854          }
01855       }
01856    }
01857 
01858    fDocEntityInfo.fClasses.Sort();
01859    fDocEntityInfo.fModules.Sort();
01860    TIter iterModule(&fDocEntityInfo.fModules);
01861    TModuleDocInfo* mdi = 0;
01862    while ((mdi = (TModuleDocInfo*) iterModule()))
01863       mdi->GetClasses()->Sort();
01864 
01865    if (fProductName == "(UNKNOWN PRODUCT)"
01866       && fDocEntityInfo.fModules.FindObject("core/base")
01867       && fDocEntityInfo.fModules.FindObject("core/cont")
01868       && fDocEntityInfo.fModules.FindObject("core/rint")
01869       && gProgName && strstr(gProgName, "root"))
01870       // if we have these modules we're probably building the root doc
01871       fProductName = "ROOT";
01872 
01873    if (fProductName == "(UNKNOWN PRODUCT)") {
01874       Warning("CreateListOfClasses", "Product not set. You should call gHtml->SetProduct(\"MyProductName\");");
01875    } else if (fProductName != "ROOT") {
01876       if (GetViewCVS().Contains("http://root.cern.ch/"))
01877          SetViewCVS("");
01878    }
01879 
01880    if (fDocEntityInfo.fModules.GetEntries() == 1
01881       && fDocEntityInfo.fModules.At(0)->GetName()
01882       && !strcmp(fDocEntityInfo.fModules.At(0)->GetName(), "(UNKNOWN)"))
01883       // Only one module, and its name is not known.
01884       // Let's call it "MAIN":
01885       ((TModuleDocInfo*) fDocEntityInfo.fModules.At(0))->SetName("MAIN");
01886 
01887    Info("CreateListOfClasses", "Initializing - DONE.");
01888 }
01889 
01890 
01891 //______________________________________________________________________________
01892 void THtml::CreateListOfTypes()
01893 {
01894 // Create index of all data types and a page for each typedef-to-class
01895 
01896    TDocOutput output(*this);
01897    output.CreateTypeIndex();
01898    output.CreateClassTypeDefs();
01899 }
01900 
01901 //______________________________________________________________________________
01902 Bool_t THtml::CopyFileFromEtcDir(const char* filename) const {
01903    // Copy a file from $ROOTSYS/etc/html into GetOutputDir()
01904 
01905    R__LOCKGUARD(GetMakeClassMutex());
01906 
01907    TString outFile(filename);
01908 
01909    TString inFile(outFile);
01910    gSystem->PrependPathName(GetEtcDir(), inFile);
01911 
01912    gSystem->PrependPathName(GetOutputDir(), outFile);
01913 
01914    if (gSystem->CopyFile(inFile, outFile, kTRUE) != 0) {
01915       Warning("CopyFileFromEtcDir", "Could not copy %s to %s", inFile.Data(), outFile.Data());
01916       return kFALSE;
01917    }
01918 
01919    return kTRUE;
01920 }
01921 
01922 //______________________________________________________________________________
01923 void THtml::CreateHierarchy()
01924 {
01925    // Create the inheritance hierarchy diagram for all classes
01926    TDocOutput output(*this);
01927    output.CreateHierarchy();
01928 }
01929 
01930 //______________________________________________________________________________
01931 void THtml::CreateJavascript() const {
01932    // Write the default ROOT style sheet.
01933    CopyFileFromEtcDir("ROOT.js");
01934 }
01935 
01936 //______________________________________________________________________________
01937 void THtml::CreateStyleSheet() const {
01938    // Write the default ROOT style sheet.
01939    CopyFileFromEtcDir("ROOT.css");
01940    CopyFileFromEtcDir("shadowAlpha.png");
01941    CopyFileFromEtcDir("shadow.gif");
01942 }
01943 
01944 
01945 
01946 //______________________________________________________________________________
01947 void THtml::GetDerivedClasses(TClass* cl, std::map<TClass*, Int_t>& derived) const
01948 {
01949    // fill derived with all classes inheriting from cl and their inheritance
01950    // distance to cl
01951 
01952    TIter iClass(&fDocEntityInfo.fClasses);
01953    TClassDocInfo* cdi = 0;
01954    while ((cdi = (TClassDocInfo*) iClass())) {
01955       TClass* candidate = dynamic_cast<TClass*>(cdi->GetClass());
01956       if (!candidate) continue;
01957       if (candidate != cl && candidate->InheritsFrom(cl)) {
01958          Int_t level = 0;
01959          TClass* currentBaseOfCandidate = candidate;
01960          while (currentBaseOfCandidate != cl) {
01961             TList* bases = currentBaseOfCandidate->GetListOfBases();
01962             if (!bases) continue;
01963             TIter iBase(bases);
01964             TBaseClass* base = 0;
01965             while ((base = (TBaseClass*) iBase())) {
01966                TClass* clBase = base->GetClassPointer();
01967                if (clBase && clBase->InheritsFrom(cl)) {
01968                   ++level;
01969                   currentBaseOfCandidate = clBase;
01970                }
01971             }
01972          }
01973          derived[candidate] = level;
01974       }
01975    }
01976 }
01977 
01978 //______________________________________________________________________________
01979 void THtml::GetHtmlFileName(TClass * classPtr, TString& filename) const
01980 {
01981 // Return real HTML filename
01982 //
01983 //
01984 //  Input: classPtr - pointer to a class
01985 //         filename - string containing a full name
01986 //         of the corresponding HTML file after the function returns.
01987 //
01988 
01989    filename.Remove(0);
01990    if (!classPtr) return;
01991 
01992    TString cFilename;
01993    if (!GetImplFileName(classPtr, kFALSE, cFilename))
01994       GetDeclFileName(classPtr, kFALSE, cFilename);
01995 
01996    // classes without Impl/DeclFileName don't have docs,
01997    // and classes without docs don't have output file names
01998    if (!cFilename.Length())
01999       return;
02000 
02001    TString libName;
02002    const char *colon = strchr(cFilename, ':');
02003    if (colon)
02004       // old version, where source file name is prepended by "TAG:"
02005       libName = TString(cFilename, colon - cFilename);
02006    else
02007       // New version, check class's libname.
02008       // If libname is dir/libMyLib.so, check Root.Html.MyLib
02009       // If libname is myOtherLib.so.2.3, check Root.Html.myOtherLib
02010       // (i.e. remove directories, "lib" prefix, and any "extension")
02011       if (classPtr->GetSharedLibs()) {
02012          // first one is the class's lib
02013          TString libname(classPtr->GetSharedLibs());
02014          Ssiz_t posSpace = libname.First(' ');
02015          if (posSpace != kNPOS)
02016             libname.Remove(posSpace, libname.Length());
02017          TString libnameBase = gSystem->BaseName(libname);
02018          if (libnameBase.BeginsWith("lib"))
02019             libnameBase.Remove(0, 3);
02020          Ssiz_t posExt = libnameBase.First('.');
02021          if (posExt != '.')
02022             libnameBase.Remove(posExt, libnameBase.Length());
02023          if (libnameBase.Length())
02024             libName = libnameBase;
02025       }
02026 
02027    filename = cFilename;
02028    TString htmlFileName;
02029    if (!filename.Length() ||
02030       !gSystem->FindFile(fPathInfo.fInputPath, filename, kReadPermission)) {
02031       htmlFileName = GetURL(libName);
02032    } else
02033       htmlFileName = "./";
02034 
02035    if (htmlFileName.Length()) {
02036       filename = htmlFileName;
02037       TString className(classPtr->GetName());
02038       TDocOutput output(*const_cast<THtml*>(this));
02039       output.NameSpace2FileName(className);
02040       gSystem->PrependPathName(filename, className);
02041       filename = className;
02042       filename.ReplaceAll("\\", "/");
02043       filename += ".html";
02044    } else filename.Remove(0);
02045 }
02046 
02047 //______________________________________________________________________________
02048 const char* THtml::GetHtmlFileName(const char* classname) const
02049 {
02050    // Get the html file name for a class named classname.
02051    // Returns 0 if the class is not documented.
02052    TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(classname);
02053    if (cdi)
02054       return cdi->GetHtmlFileName();
02055    return 0;
02056 }
02057 
02058 //______________________________________________________________________________
02059 TClass *THtml::GetClass(const char *name1) const
02060 {
02061 //*-*-*-*-*Return pointer to class with name*-*-*-*-*-*-*-*-*-*-*-*-*
02062 //*-*      =================================
02063    if(!name1 || !name1[0]) return 0;
02064    // no doc for internal classes
02065    if (strstr(name1,"ROOT::")==name1) {
02066       Bool_t ret = kTRUE;
02067       if (!strncmp(name1 + 6,"Math", 4))   ret = kFALSE;
02068       if (!strncmp(name1 + 6,"Reflex", 6)) ret = kFALSE;
02069       if (!strncmp(name1 + 6,"Cintex", 6)) ret = kFALSE;
02070       if (ret) return 0;
02071    }
02072 
02073    TClassDocInfo* cdi = (TClassDocInfo*)fDocEntityInfo.fClasses.FindObject(name1);
02074    if (!cdi) return 0;
02075    TClass *cl = dynamic_cast<TClass*>(cdi->GetClass());
02076    // hack to get rid of prec_stl types
02077    // TClassEdit checks are far too slow...
02078    /*
02079    if (cl && GetDeclFileName(cl) &&
02080        strstr(GetDeclFileName(cl),"prec_stl/"))
02081       cl = 0;
02082    */
02083    TString declFileName;
02084    if (cl && GetDeclFileName(cl, kFALSE, declFileName))
02085       return cl;
02086    return 0;
02087 }
02088 
02089 //______________________________________________________________________________
02090 bool THtml::GetDeclFileName(TClass * cl, Bool_t filesys, TString& out_name) const
02091 {
02092    // Return declaration file name; return the full path if filesys is true.
02093    return GetDeclImplFileName(cl, filesys, true, out_name);
02094 }
02095 
02096 //______________________________________________________________________________
02097 bool THtml::GetImplFileName(TClass * cl, Bool_t filesys, TString& out_name) const
02098 {
02099    // Return implementation file name
02100    return GetDeclImplFileName(cl, filesys, false, out_name);
02101 }
02102 
02103 //______________________________________________________________________________
02104 bool THtml::GetDeclImplFileName(TClass * cl, bool filesys, bool decl, TString& out_name) const
02105 {
02106    // Combined implementation for GetDeclFileName(), GetImplFileName():
02107    // Return declaration / implementation file name (depending on decl);
02108    // return the full path if filesys is true.
02109 
02110    out_name = "";
02111 
02112    R__LOCKGUARD(GetMakeClassMutex());
02113    TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(cl->GetName());
02114    // whether we need to determine the fil name
02115    bool determine = (!cdi); // no cdi
02116    if (!determine) determine |=  decl &&  filesys && !cdi->GetDeclFileSysName()[0];
02117    if (!determine) determine |=  decl && !filesys && !cdi->GetDeclFileName()[0];
02118    if (!determine) determine |= !decl &&  filesys && !cdi->GetImplFileSysName()[0];
02119    if (!determine) determine |= !decl && !filesys && !cdi->GetImplFileName()[0];
02120    if (determine) {
02121       TString name;
02122       TString sysname;
02123       if (decl) {
02124          if (!GetFileDefinition().GetDeclFileName(cl, name, sysname))
02125             return false;
02126       } else {
02127          if (!GetFileDefinition().GetImplFileName(cl, name, sysname))
02128             return false;
02129       }
02130       if (cdi) {
02131          if (decl) {
02132             if (!cdi->GetDeclFileName() || !cdi->GetDeclFileName()[0])
02133                cdi->SetDeclFileName(name);
02134             if (!cdi->GetDeclFileSysName() || !cdi->GetDeclFileSysName()[0])
02135                cdi->SetDeclFileSysName(sysname);
02136          } else {
02137             if (!cdi->GetImplFileName() || !cdi->GetImplFileName()[0])
02138                cdi->SetImplFileName(name);
02139             if (!cdi->GetImplFileSysName() || !cdi->GetImplFileSysName()[0])
02140                cdi->SetImplFileSysName(sysname);
02141          }
02142       }
02143 
02144       if (filesys) out_name = sysname;
02145       else         out_name = name;
02146       return true;
02147    }
02148    if (filesys) {
02149       if (decl) out_name = cdi->GetDeclFileSysName();
02150       else      out_name = cdi->GetImplFileSysName();
02151    } else {
02152       if (decl) out_name = cdi->GetDeclFileName();
02153       else      out_name = cdi->GetImplFileName();
02154    }
02155    return true;
02156 }
02157 
02158 //______________________________________________________________________________
02159 const TString& THtml::GetOutputDir(Bool_t createDir /*= kTRUE*/) const
02160 {
02161    // Return the output directory as set by SetOutputDir().
02162    // Create it if it doesn't exist and if createDir is kTRUE.
02163 
02164    if (createDir) {
02165       R__LOCKGUARD(GetMakeClassMutex());
02166 
02167       gSystem->ExpandPathName(const_cast<THtml*>(this)->fPathInfo.fOutputDir);
02168       Long64_t sSize;
02169       Long_t sId, sFlags, sModtime;
02170       if (fPathInfo.fOutputDir.EndsWith("/") || fPathInfo.fOutputDir.EndsWith("\\"))
02171          fPathInfo.fOutputDir.Remove(fPathInfo.fOutputDir.Length() - 1);
02172       Int_t st = gSystem->GetPathInfo(fPathInfo.fOutputDir, &sId, &sSize, &sFlags, &sModtime);
02173       if (st || !(sFlags & 2)) {
02174          if (st == 0)
02175             Error("GetOutputDir", "output directory %s is an existing file",
02176                   fPathInfo.fOutputDir.Data());
02177          else if (gSystem->MakeDirectory(fPathInfo.fOutputDir) == -1)
02178             Error("GetOutputDir", "output directory %s does not exist and can't create it", fPathInfo.fOutputDir.Data());
02179       }
02180    }
02181    return fPathInfo.fOutputDir;
02182 }
02183 
02184 //______________________________________________________________________________
02185 Bool_t THtml::IsNamespace(const TClass*cl)
02186 {
02187    // Check whether cl is a namespace
02188    return (cl->Property() & kIsNamespace);
02189 }
02190 
02191 //______________________________________________________________________________
02192 void THtml::LoadAllLibs()
02193 {
02194    // Load all libraries known to ROOT via the rootmap system.
02195 
02196    TEnv* mapfile = gInterpreter->GetMapfile();
02197    if (!mapfile || !mapfile->GetTable()) return;
02198 
02199    std::set<std::string> loadedlibs;
02200    std::set<std::string> failedlibs;
02201 
02202    TEnvRec* rec = 0;
02203    TIter iEnvRec(mapfile->GetTable());
02204    while ((rec = (TEnvRec*) iEnvRec())) {
02205       TString libs = rec->GetValue();
02206       TString lib;
02207       Ssiz_t pos = 0;
02208       while (libs.Tokenize(lib, pos)) {
02209          // check that none of the libs failed to load
02210          if (failedlibs.find(lib.Data()) != failedlibs.end()) {
02211             // don't load it or any of its dependencies
02212             libs = "";
02213             break;
02214          }
02215       }
02216       pos = 0;
02217       while (libs.Tokenize(lib, pos)) {
02218          // ignore libCore - it's already loaded
02219          if (lib.BeginsWith("libCore"))
02220             continue;
02221 
02222          if (loadedlibs.find(lib.Data()) == loadedlibs.end()) {
02223             // just load the first library - TSystem will do the rest.
02224             gSystem->Load(lib);
02225             loadedlibs.insert(lib.Data());
02226          }
02227       }
02228    }
02229 }
02230 
02231 
02232 //______________________________________________________________________________
02233 void THtml::MakeAll(Bool_t force, const char *filter, int numthreads /*= -1*/)
02234 {
02235 // Produce documentation for all the classes specified in the filter (by default "*")
02236 // To process all classes having a name starting with XX, do:
02237 //        html.MakeAll(kFALSE,"XX*");
02238 // If force=kFALSE (default), only the classes that have been modified since
02239 // the previous call to this function will be generated.
02240 // If force=kTRUE, all classes passing the filter will be processed.
02241 // If numthreads is != -1, use numthreads threads, else decide automatically
02242 // based on the number of CPUs.
02243 
02244    MakeIndex(filter);
02245 
02246    if (numthreads == 1) {
02247       // CreateListOfClasses(filter); already done by MakeIndex
02248       TClassDocInfo* classinfo = 0;
02249       TIter iClassInfo(&fDocEntityInfo.fClasses);
02250       UInt_t count = 0;
02251 
02252       while ((classinfo = (TClassDocInfo*)iClassInfo())) {
02253          if (!classinfo->IsSelected())
02254             continue;
02255          fCounter.Form("%5d", fDocEntityInfo.fClasses.GetSize() - count++);
02256          MakeClass(classinfo, force);
02257       }
02258    } else {
02259       if (numthreads == -1) {
02260          SysInfo_t sysinfo;
02261          gSystem->GetSysInfo(&sysinfo);
02262          numthreads = sysinfo.fCpus;
02263          if (numthreads < 1)
02264             numthreads = 2;
02265       }
02266       fThreadedClassCount = 0;
02267       fThreadedClassIter = new TIter(&fDocEntityInfo.fClasses);
02268       THtmlThreadInfo hti(this, force);
02269       if (!fMakeClassMutex && gGlobalMutex) {
02270          gGlobalMutex->Lock();
02271          fMakeClassMutex = gGlobalMutex->Factory(kTRUE);
02272          gGlobalMutex->UnLock();
02273       }
02274 
02275       TList threads;
02276       gSystem->Load("libThread");
02277       while (--numthreads >= 0) {
02278          TThread* thread = new TThread(MakeClassThreaded, &hti);
02279          thread->Run();
02280          threads.Add(thread);
02281       }
02282 
02283       TIter iThread(&threads);
02284       TThread* thread = 0;
02285       Bool_t wait = kTRUE;
02286       while (wait) {
02287          while (wait && (thread = (TThread*) iThread()))
02288             wait &= (thread->GetState() == TThread::kRunningState);
02289          gSystem->ProcessEvents();
02290          gSystem->Sleep(500);
02291       }
02292 
02293       iThread.Reset();
02294       while ((thread = (TThread*) iThread()))
02295          thread->Join();
02296    }
02297    fCounter.Remove(0);
02298 }
02299 
02300 
02301 //______________________________________________________________________________
02302 void THtml::MakeClass(const char *className, Bool_t force)
02303 {
02304 // Make HTML files for a single class
02305 //
02306 //
02307 // Input: className - name of the class to process
02308 //
02309    CreateListOfClasses("*");
02310 
02311    TClassDocInfo* cdi = (TClassDocInfo*)fDocEntityInfo.fClasses.FindObject(className);
02312    if (!cdi) {
02313       if (!TClassEdit::IsStdClass(className)) // stl classes won't be available, so no warning
02314          Error("MakeClass", "Unknown class '%s'!", className);
02315       return;
02316    }
02317 
02318    MakeClass(cdi, force);
02319 }
02320 
02321 //______________________________________________________________________________
02322 void THtml::MakeClass(void *cdi_void, Bool_t force)
02323 {
02324 // Make HTML files for a single class
02325 //
02326 //
02327 // Input: cdi - doc info for class to process
02328 //
02329    if (!fDocEntityInfo.fClasses.GetSize())
02330       CreateListOfClasses("*");
02331 
02332    TClassDocInfo* cdi = (TClassDocInfo*) cdi_void;
02333    TClass* currentClass = dynamic_cast<TClass*>(cdi->GetClass());
02334 
02335    if (!currentClass) {
02336       if (!cdi->GetClass() &&
02337           !TClassEdit::IsStdClass(cdi->GetName())) // stl classes won't be available, so no warning
02338          Error("MakeClass", "Class '%s' is known, but I cannot find its TClass object!", cdi->GetName());
02339       return;
02340    }
02341    TString htmlFile(cdi->GetHtmlFileName());
02342    if (htmlFile.Length()
02343        && (htmlFile.BeginsWith("http://")
02344            || htmlFile.BeginsWith("https://")
02345            || gSystem->IsAbsoluteFileName(htmlFile))
02346        ) {
02347       htmlFile.Remove(0);
02348    }
02349    if (htmlFile.Length()) {
02350       TClassDocOutput cdo(*this, currentClass, &cdi->GetListOfTypedefs());
02351       cdo.Class2Html(force);
02352       cdo.MakeTree(force);
02353    } else {
02354       TString what(cdi->GetName());
02355       what += " (sources not found)";
02356       Printf(fCounterFormat.Data(), "-skipped-", fCounter.Data(), what.Data());
02357    }
02358 }
02359 
02360 
02361 //______________________________________________________________________________
02362 void* THtml::MakeClassThreaded(void* info) {
02363    // Entry point of worker threads for multi-threaded MakeAll().
02364    // info points to an (internal) THtmlThreadInfo object containing the current
02365    // THtml object, and whether "force" was passed to MakeAll().
02366    // The thread will poll GetNextClass() until no further class is available.
02367 
02368    const THtmlThreadInfo* hti = (const THtmlThreadInfo*)info;
02369    if (!hti) return 0;
02370    TClassDocInfo* classinfo = 0;
02371    while ((classinfo = hti->GetHtml()->GetNextClass()))
02372       hti->GetHtml()->MakeClass(classinfo, hti->GetForce());
02373 
02374    return 0;
02375 }
02376 
02377 //______________________________________________________________________________
02378 void THtml::MakeIndex(const char *filter)
02379 {
02380    // Create the index files for the product, modules, all types, etc.
02381    // By default all classes are indexed (if filter="*");
02382    // to generate an index for all classes starting with "XX", do
02383    //    html.MakeIndex("XX*");
02384 
02385    CreateListOfClasses(filter);
02386 
02387    TDocOutput output(*this);
02388    // create indices
02389    output.CreateTypeIndex();
02390    output.CreateClassTypeDefs();
02391    output.CreateModuleIndex();
02392    output.CreateClassIndex();
02393    output.CreateProductIndex();
02394 
02395    // create a class hierarchy
02396    output.CreateHierarchy();
02397 }
02398 
02399 
02400 //______________________________________________________________________________
02401 void THtml::MakeTree(const char *className, Bool_t force)
02402 {
02403 // Make an inheritance tree
02404 //
02405 //
02406 // Input: className - name of the class to process
02407 //
02408 
02409    // create canvas & set fill color
02410    TClass *classPtr = GetClass(className);
02411 
02412    if (!classPtr) {
02413       Error("MakeTree", "Unknown class '%s' !", className);
02414       return;
02415    }
02416 
02417    TClassDocOutput cdo(*this, classPtr, 0);
02418    cdo.MakeTree(force);
02419 }
02420 
02421 //______________________________________________________________________________
02422 void THtml::SetFoundDot(Bool_t found) {
02423    // Set whether "dot" (a GraphViz utility) is avaliable
02424    if (found) fPathInfo.fFoundDot = PathInfo_t::kDotFound;
02425    else fPathInfo.fFoundDot = PathInfo_t::kDotNotFound;
02426 }
02427 
02428 //______________________________________________________________________________
02429 void THtml::SetLocalFiles() const
02430 {
02431    // Fill the files available in the file system below fPathInfo.fInputPath
02432    if (fLocalFiles) delete fLocalFiles;
02433    fLocalFiles = new TFileSysDB(fPathInfo.fInputPath, fPathInfo.fIgnorePath + "|(\\b" + GetOutputDir(kFALSE) + "\\b)" , 6);
02434 }
02435 
02436 //______________________________________________________________________________
02437 void THtml::SetModuleDefinition(const TModuleDefinition& md)
02438 {
02439    // Set the module defining object to be used; can also be a user derived
02440    // object (a la traits).
02441    delete fModuleDef;
02442    fModuleDef = (TModuleDefinition*) md.Clone();
02443    fModuleDef->SetOwner(const_cast<THtml*>(this));
02444 }
02445 
02446 
02447 //______________________________________________________________________________
02448 void THtml::SetFileDefinition(const TFileDefinition& md)
02449 {
02450    // Set the file defining object to be used; can also be a user derived
02451    // object (a la traits).
02452    delete fFileDef;
02453    fFileDef = (TFileDefinition*) md.Clone();
02454    fFileDef->SetOwner(const_cast<THtml*>(this));
02455 }
02456 
02457 
02458 //______________________________________________________________________________
02459 void THtml::SetPathDefinition(const TPathDefinition& md)
02460 {
02461    // Set the path defining object to be used; can also be a user derived
02462    // object (a la traits).
02463    delete fPathDef;
02464    fPathDef = (TPathDefinition*) md.Clone();
02465    fPathDef->SetOwner(const_cast<THtml*>(this));
02466 }
02467 
02468 
02469 //______________________________________________________________________________
02470 void THtml::SetInputDir(const char *dir)
02471 {
02472    // Set the directory containing the source files.
02473    // The source file for a class MyClass will be searched
02474    // by prepending dir to the value of
02475    // MyClass::Class()->GetImplFileName() - which can contain
02476    // directory information!
02477    // Also resets the class structure, in case new files can
02478    // be found after this call.
02479 
02480    fPathInfo.fInputPath = dir;
02481    gSystem->ExpandPathName(fPathInfo.fInputPath);
02482 
02483    // reset class table
02484    fDocEntityInfo.fClasses.Clear();
02485    fDocEntityInfo.fModules.Clear();
02486 }
02487 
02488 //______________________________________________________________________________
02489 void THtml::SetOutputDir(const char *dir)
02490 {
02491    // Set the directory where the HTML pages shuold be written to.
02492    // If the directory does not exist it will be created when needed.
02493    fPathInfo.fOutputDir = dir;
02494 #ifdef R__WIN32
02495    fPathInfo.fOutputDir.ReplaceAll("/","\\");
02496 #endif
02497 }
02498 
02499 //______________________________________________________________________________
02500 void THtml::SetDeclFileName(TClass* cl, const char* filename)
02501 {
02502    // Explicitly set a decl file name for TClass cl.
02503    TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(cl->GetName());
02504    if (!cdi) {
02505       cdi = new TClassDocInfo(cl, "" /*html*/, "" /*fsdecl*/, "" /*fsimpl*/, filename);
02506       fDocEntityInfo.fClasses.Add(cdi);
02507    } else
02508       cdi->SetDeclFileName(filename);
02509 }
02510 
02511 //______________________________________________________________________________
02512 void THtml::SetImplFileName(TClass* cl, const char* filename)
02513 {
02514    // Explicitly set a impl file name for TClass cl.
02515    TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(cl->GetName());
02516    if (!cdi) {
02517       cdi = new TClassDocInfo(cl, "" /*html*/, "" /*fsdecl*/, "" /*fsimpl*/, 0 /*decl*/, filename);
02518       fDocEntityInfo.fClasses.Add(cdi);
02519    } else
02520       cdi->SetImplFileName(filename);
02521 }
02522 
02523 //______________________________________________________________________________
02524 const char* THtml::ShortType(const char* name) const
02525 {
02526    // Get short type name, i.e. with default templates removed.
02527    const char* tmplt = strchr(name, '<');
02528    if (!tmplt) return name;
02529    tmplt = strrchr(tmplt, ':');
02530    if (tmplt > name && tmplt[-1] == ':') {
02531       // work-around for CINT bug: template instantiation can produce bogus
02532       // typedefs e.g. in namespace ROOT::Math::ROOT::Math instead of ROOT::Math.
02533       TString namesp(name, tmplt - name - 1);
02534       // is the enclosing namespace known?
02535       if (!GetClass(namesp)) return name;
02536    }
02537    TObject* scn = fDocEntityInfo.fShortClassNames.FindObject(name);
02538    if (!scn) {
02539       scn = new TNamed(name, TClassEdit::ShortType(name, 1<<7));
02540       fDocEntityInfo.fShortClassNames.Add(scn);
02541    }
02542    return scn->GetTitle();
02543 }

Generated on Tue Jul 5 14:24:56 2011 for ROOT_528-00b_version by  doxygen 1.5.1