00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00060
00061 if (fHtml) {
00062 fHtml->HelperDeleted(this);
00063 }
00064 }
00065
00066
00067
00068 void THtml::THelperBase::SetOwner(THtml* html) {
00069
00070
00071
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
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 out_modulename = "USER";
00105 if (!cl) return false;
00106
00107
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
00119
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
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
00149 if (out_modulename.EndsWith("/src")
00150 || out_modulename.EndsWith("/inc"))
00151 out_modulename.Remove(out_modulename.Length() - 4, 4);
00152 else {
00153
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
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
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
00202
00203
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
00231
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
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
00251
00252
00253
00254
00255
00256
00257
00258
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
00268
00269
00270
00271
00272
00273
00274
00275
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
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
00301
00302
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);
00313 if (!filename.EndsWith(filesysname)) {
00314 filesysname = "";
00315 continue;
00316 }
00317 filename = filesysname;
00318 fsentry->GetFullName(filesysname, kFALSE);
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
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
00351
00352
00353
00354
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
00377 filesysname = MatchFileSysName(out_filename, fse);
00378 if (filesysname[0]) {
00379 clfile = out_filename;
00380 }
00381 }
00382 } else {
00383
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
00411
00412
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
00430
00431
00432
00433
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
00439
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
00455
00456
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
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
00500
00501
00502
00503
00504
00505
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
00528
00529
00530
00531
00532
00533
00534
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
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
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
00582
00583
00584
00585
00586
00587
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
00594
00595
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
00610
00611
00612
00613
00614
00615
00616
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
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
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
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
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
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
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
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 }
00714 gSystem->FreeDirectory(hDir);
00715 }
00716
00717
00718
00719 void THtml::TFileSysDB::Fill()
00720 {
00721
00722
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
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
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
01232
01233
01234
01235
01236 fPathInfo.fInputPath = gEnv->GetValue("Root.Html.SourceDir", "./:src/:include/");
01237
01238
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
01259 if (!gHtml) {
01260 gHtml = this;
01261 gROOT->GetListOfSpecials()->Add(gHtml);
01262 }
01263
01264 }
01265
01266
01267
01268 THtml::~THtml()
01269 {
01270
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
01288
01289
01290
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
01307 CreateJavascript();
01308 CreateStyleSheet();
01309 CopyFileFromEtcDir("HELP.html");
01310 }
01311
01312
01313 const THtml::TModuleDefinition& THtml::GetModuleDefinition() const
01314 {
01315
01316
01317
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
01329
01330
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
01342
01343
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
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
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 ) const
01406 {
01407
01408
01409
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
01425
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
01452
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 ,
01465 const char* context )
01466 {
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489 gROOT->GetListOfGlobals(kTRUE);
01490 CreateListOfClasses("*");
01491
01492 const char *dir;
01493
01494
01495 if (!*dirname) {
01496 gSystem->ExpandPathName(fPathInfo.fOutputDir);
01497 dir = gSystem->ConcatFileName(fPathInfo.fOutputDir, "examples");
01498 } else
01499 dir = dirname;
01500
01501
01502 if (gSystem->AccessPathName(dir))
01503 gSystem->MakeDirectory(dir);
01504
01505
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
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
01552
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
01568
01569 if (fDocEntityInfo.fClasses.GetSize() && fDocEntityInfo.fClassFilter == filter)
01570 return;
01571
01572 Info("CreateListOfClasses", "Initializing - this might take a while...");
01573
01574 Int_t totalNumberOfClasses = gClassTable->Classes();
01575
01576
01577 fDocEntityInfo.fClasses.Clear();
01578 fDocEntityInfo.fModules.Clear();
01579
01580 fDocEntityInfo.fClassFilter = filter;
01581
01582
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
01595 for (Int_t i = -1; i < totalNumberOfClasses; i++) {
01596
01597
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
01604 continue;
01605 }
01606
01607
01608 if (strstr(cname, "__gnu_cxx::")) continue;
01609
01610
01611
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
01641
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
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
01674
01675 classesDeclFileNotFound.AddLast(classPtr);
01676 else rootLibs.insert(lib);
01677 }
01678 } else {
01679
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
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 }
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
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
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
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
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
01884
01885 ((TModuleDocInfo*) fDocEntityInfo.fModules.At(0))->SetName("MAIN");
01886
01887 Info("CreateListOfClasses", "Initializing - DONE.");
01888 }
01889
01890
01891
01892 void THtml::CreateListOfTypes()
01893 {
01894
01895
01896 TDocOutput output(*this);
01897 output.CreateTypeIndex();
01898 output.CreateClassTypeDefs();
01899 }
01900
01901
01902 Bool_t THtml::CopyFileFromEtcDir(const char* filename) const {
01903
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
01926 TDocOutput output(*this);
01927 output.CreateHierarchy();
01928 }
01929
01930
01931 void THtml::CreateJavascript() const {
01932
01933 CopyFileFromEtcDir("ROOT.js");
01934 }
01935
01936
01937 void THtml::CreateStyleSheet() const {
01938
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
01950
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
01982
01983
01984
01985
01986
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
01997
01998 if (!cFilename.Length())
01999 return;
02000
02001 TString libName;
02002 const char *colon = strchr(cFilename, ':');
02003 if (colon)
02004
02005 libName = TString(cFilename, colon - cFilename);
02006 else
02007
02008
02009
02010
02011 if (classPtr->GetSharedLibs()) {
02012
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
02051
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
02062
02063 if(!name1 || !name1[0]) return 0;
02064
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
02077
02078
02079
02080
02081
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
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
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
02107
02108
02109
02110 out_name = "";
02111
02112 R__LOCKGUARD(GetMakeClassMutex());
02113 TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(cl->GetName());
02114
02115 bool determine = (!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 ) const
02160 {
02161
02162
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
02188 return (cl->Property() & kIsNamespace);
02189 }
02190
02191
02192 void THtml::LoadAllLibs()
02193 {
02194
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
02210 if (failedlibs.find(lib.Data()) != failedlibs.end()) {
02211
02212 libs = "";
02213 break;
02214 }
02215 }
02216 pos = 0;
02217 while (libs.Tokenize(lib, pos)) {
02218
02219 if (lib.BeginsWith("libCore"))
02220 continue;
02221
02222 if (loadedlibs.find(lib.Data()) == loadedlibs.end()) {
02223
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 )
02234 {
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244 MakeIndex(filter);
02245
02246 if (numthreads == 1) {
02247
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
02305
02306
02307
02308
02309 CreateListOfClasses("*");
02310
02311 TClassDocInfo* cdi = (TClassDocInfo*)fDocEntityInfo.fClasses.FindObject(className);
02312 if (!cdi) {
02313 if (!TClassEdit::IsStdClass(className))
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
02325
02326
02327
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()))
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
02364
02365
02366
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
02381
02382
02383
02384
02385 CreateListOfClasses(filter);
02386
02387 TDocOutput output(*this);
02388
02389 output.CreateTypeIndex();
02390 output.CreateClassTypeDefs();
02391 output.CreateModuleIndex();
02392 output.CreateClassIndex();
02393 output.CreateProductIndex();
02394
02395
02396 output.CreateHierarchy();
02397 }
02398
02399
02400
02401 void THtml::MakeTree(const char *className, Bool_t force)
02402 {
02403
02404
02405
02406
02407
02408
02409
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
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
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
02440
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
02451
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
02462
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
02473
02474
02475
02476
02477
02478
02479
02480 fPathInfo.fInputPath = dir;
02481 gSystem->ExpandPathName(fPathInfo.fInputPath);
02482
02483
02484 fDocEntityInfo.fClasses.Clear();
02485 fDocEntityInfo.fModules.Clear();
02486 }
02487
02488
02489 void THtml::SetOutputDir(const char *dir)
02490 {
02491
02492
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
02503 TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(cl->GetName());
02504 if (!cdi) {
02505 cdi = new TClassDocInfo(cl, "" , "" , "" , 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
02515 TClassDocInfo* cdi = (TClassDocInfo*) fDocEntityInfo.fClasses.FindObject(cl->GetName());
02516 if (!cdi) {
02517 cdi = new TClassDocInfo(cl, "" , "" , "" , 0 , 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
02527 const char* tmplt = strchr(name, '<');
02528 if (!tmplt) return name;
02529 tmplt = strrchr(tmplt, ':');
02530 if (tmplt > name && tmplt[-1] == ':') {
02531
02532
02533 TString namesp(name, tmplt - name - 1);
02534
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 }