00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TDocParser.h"
00013
00014 #include "Riostream.h"
00015 #include "TBaseClass.h"
00016 #include "TClass.h"
00017 #include "TClassDocOutput.h"
00018 #include "TDataMember.h"
00019 #include "TDataType.h"
00020 #include "TDatime.h"
00021 #include "TDocDirective.h"
00022 #include "TEnv.h"
00023 #include "TGlobal.h"
00024 #include "THtml.h"
00025 #include "TInterpreter.h"
00026 #include "TMethod.h"
00027 #include "TMethodArg.h"
00028 #include "TPRegexp.h"
00029 #include "TROOT.h"
00030 #include "TSystem.h"
00031 #include "TVirtualMutex.h"
00032 #include <string>
00033
00034 namespace {
00035
00036 class TMethodWrapperImpl: public TDocMethodWrapper {
00037 public:
00038 TMethodWrapperImpl(TMethod* m, int overloadIdx):
00039 fMeth(m), fOverloadIdx(overloadIdx) {}
00040
00041 static void SetClass(const TClass* cl) { fgClass = cl; }
00042
00043 const char* GetName() const { return fMeth->GetName(); }
00044 ULong_t Hash() const { return fMeth->Hash();}
00045 Int_t GetNargs() const { return fMeth->GetNargs(); }
00046 virtual TMethod* GetMethod() const { return fMeth; }
00047 Bool_t IsSortable() const { return kTRUE; }
00048
00049 Int_t GetOverloadIdx() const { return fOverloadIdx; }
00050
00051 Int_t Compare(const TObject *obj) const {
00052 const TMethodWrapperImpl* m = dynamic_cast<const TMethodWrapperImpl*>(obj);
00053 if (!m) return 1;
00054
00055 Int_t ret = strcasecmp(GetName(), m->GetName());
00056 if (ret == 0) {
00057 if (GetNargs() < m->GetNargs()) return -1;
00058 else if (GetNargs() > m->GetNargs()) return 1;
00059 if (GetMethod()->GetClass()->InheritsFrom(m->GetMethod()->GetClass()))
00060 return -1;
00061 else
00062 return 1;
00063 }
00064
00065 const char* l(GetName());
00066 const char* r(m->GetName());
00067 if (l[0] == '~' && r[0] == '~') {
00068 ++l;
00069 ++r;
00070 }
00071 if (fgClass->InheritsFrom(l)) {
00072 if (fgClass->InheritsFrom(r)) {
00073 if (gROOT->GetClass(l)->InheritsFrom(r))
00074 return -1;
00075 else return 1;
00076 } else return -1;
00077 } else if (fgClass->InheritsFrom(r))
00078 return 1;
00079
00080 if (l[0] == '~') return -1;
00081 if (r[0] == '~') return 1;
00082 return (ret < 0) ? -1 : 1;
00083 }
00084
00085 private:
00086 static const TClass* fgClass;
00087 TMethod* fMeth;
00088 Int_t fOverloadIdx;
00089 };
00090
00091 const TClass* TMethodWrapperImpl::fgClass = 0;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 ClassImp(TDocParser);
00136
00137 std::set<std::string> TDocParser::fgKeywords;
00138
00139
00140 TDocParser::TDocParser(TClassDocOutput& docOutput, TClass* cl):
00141 fHtml(docOutput.GetHtml()), fDocOutput(&docOutput), fLineNo(0),
00142 fCurrentClass(cl), fRecentClass(0), fCurrentModule(0),
00143 fDirectiveCount(0), fLineNumber(0), fDocContext(kIgnore),
00144 fCheckForMethod(kFALSE), fClassDocState(kClassDoc_Uninitialized),
00145 fCommentAtBOL(kFALSE), fAllowDirectives(kTRUE)
00146 {
00147
00148
00149 InitKeywords();
00150
00151 fSourceInfoTags[kInfoLastUpdate] = fHtml->GetLastUpdateTag();
00152 fSourceInfoTags[kInfoAuthor] = fHtml->GetAuthorTag();
00153 fSourceInfoTags[kInfoCopyright] = fHtml->GetCopyrightTag();
00154
00155 fClassDescrTag = fHtml->GetClassDocTag();
00156
00157 TMethodWrapperImpl::SetClass(cl);
00158
00159 for (int ia = 0; ia < 3; ++ia) {
00160 fMethods[ia].Rehash(101);
00161 }
00162
00163 AddClassMethodsRecursively(0);
00164 AddClassDataMembersRecursively(0);
00165
00166
00167 fParseContext.push_back(kCode);
00168
00169
00170 TMethod *method;
00171 TIter nextMethod(fCurrentClass->GetListOfMethods());
00172 fMethodCounts.clear();
00173 while ((method = (TMethod *) nextMethod())) {
00174 ++fMethodCounts[method->GetName()];
00175 }
00176
00177 }
00178
00179
00180 TDocParser::TDocParser(TDocOutput& docOutput):
00181 fHtml(docOutput.GetHtml()), fDocOutput(&docOutput), fLineNo(0),
00182 fCurrentClass(0), fRecentClass(0), fDirectiveCount(0),
00183 fLineNumber(0), fDocContext(kIgnore),
00184 fCheckForMethod(kFALSE), fClassDocState(kClassDoc_Uninitialized),
00185 fCommentAtBOL(kFALSE), fAllowDirectives(kFALSE)
00186 {
00187
00188 InitKeywords();
00189
00190 fSourceInfoTags[kInfoLastUpdate] = fHtml->GetLastUpdateTag();
00191 fSourceInfoTags[kInfoAuthor] = fHtml->GetAuthorTag();
00192 fSourceInfoTags[kInfoCopyright] = fHtml->GetCopyrightTag();
00193
00194 fClassDescrTag = fHtml->GetClassDocTag();
00195
00196 TMethodWrapperImpl::SetClass(0);
00197 }
00198
00199
00200 TDocParser::~TDocParser()
00201 {
00202
00203 if (gDebug > 3) {
00204 for (std::map<std::string, Int_t>::const_iterator iMethod = fMethodCounts.begin();
00205 iMethod != fMethodCounts.end(); ++iMethod)
00206 if (iMethod->second)
00207 Info("~TDocParser", "Implementation of method %s::%s could not be found.",
00208 fCurrentClass ? fCurrentClass->GetName() : "",
00209 iMethod->first.c_str());
00210 TIter iDirective(&fDirectiveHandlers);
00211 TDocDirective* directive = 0;
00212 while ((directive = (TDocDirective*) iDirective())) {
00213 TString directiveName;
00214 directive->GetName(directiveName);
00215 Warning("~TDocParser", "Missing \"%s\" for macro %s", directive->GetEndTag(), directiveName.Data());
00216 }
00217 }
00218 }
00219
00220
00221 void TDocParser::AddClassMethodsRecursively(TBaseClass* bc)
00222 {
00223
00224
00225
00226
00227
00228 TClass *cl = fCurrentClass;
00229 if (bc)
00230 cl = bc->GetClassPointer(kFALSE);
00231 if (!cl) return;
00232
00233 TMethod *method;
00234 TIter nextMethod(cl->GetListOfMethods());
00235 std::map<std::string, int> methOverloads;
00236
00237 while ((method = (TMethod *) nextMethod())) {
00238
00239 if (!strcmp(method->GetName(), "Dictionary") ||
00240 !strcmp(method->GetName(), "Class_Version") ||
00241 !strcmp(method->GetName(), "Class_Name") ||
00242 !strcmp(method->GetName(), "DeclFileName") ||
00243 !strcmp(method->GetName(), "DeclFileLine") ||
00244 !strcmp(method->GetName(), "ImplFileName") ||
00245 !strcmp(method->GetName(), "ImplFileLine") ||
00246 (bc && (method->GetName()[0] == '~'
00247 || !strcmp(method->GetName(), method->GetReturnTypeName())))
00248 )
00249 continue;
00250
00251
00252 Int_t mtype = 0;
00253 if (kIsPrivate & method->Property())
00254 mtype = 0;
00255 else if (kIsProtected & method->Property())
00256 mtype = 1;
00257 else if (kIsPublic & method->Property())
00258 mtype = 2;
00259
00260 if (bc) {
00261 if (mtype == 0) continue;
00262 if (bc->Property() & kIsPrivate)
00263 mtype = 0;
00264 else if ((bc->Property() & kIsProtected) && mtype == 2)
00265 mtype = 1;
00266 }
00267
00268 Bool_t hidden = kFALSE;
00269 for (Int_t access = 0; !hidden && access < 3; ++access) {
00270 TMethodWrapperImpl* other = (TMethodWrapperImpl*) fMethods[access].FindObject(method->GetName());
00271 hidden |= (other) && (other->GetMethod()->GetClass() != method->GetClass());
00272 }
00273 if (!hidden) {
00274 fMethods[mtype].Add(new TMethodWrapperImpl(method, methOverloads[method->GetName()]));
00275 ++methOverloads[method->GetName()];
00276 }
00277 }
00278
00279 TIter iBase(cl->GetListOfBases());
00280 TBaseClass* base = 0;
00281 while ((base = (TBaseClass*)iBase()))
00282 AddClassMethodsRecursively(base);
00283
00284 if (!bc)
00285 for (Int_t access = 0; access < 3; ++access) {
00286 fMethods[access].SetOwner();
00287 fMethods[access].Sort();
00288 }
00289 }
00290
00291
00292 void TDocParser::AddClassDataMembersRecursively(TBaseClass* bc) {
00293
00294
00295
00296
00297
00298 TClass *cl = fCurrentClass;
00299 if (bc)
00300 cl = bc->GetClassPointer(kFALSE);
00301 if (!cl) return;
00302
00303 TDataMember *dm;
00304 TIter nextDM(cl->GetListOfDataMembers());
00305
00306 while ((dm = (TDataMember *) nextDM())) {
00307 if (!strcmp(dm->GetName(), "fgIsA"))
00308 continue;
00309 Int_t mtype = 0;
00310 if (kIsPrivate & dm->Property())
00311 mtype = 0;
00312 else if (kIsProtected & dm->Property())
00313 mtype = 1;
00314 else if (kIsPublic & dm->Property())
00315 mtype = 2;
00316
00317 if (bc) {
00318 if (mtype == 0) continue;
00319 if (bc->Property() & kIsPrivate)
00320 mtype = 0;
00321 else if ((bc->Property() & kIsProtected) && mtype == 2)
00322 mtype = 1;
00323 }
00324
00325 const Int_t flagEnumConst = G__BIT_ISENUM | G__BIT_ISCONSTANT | G__BIT_ISSTATIC;
00326 if ((dm->Property() & flagEnumConst) == flagEnumConst
00327 && dm->GetDataType() && dm->GetDataType()->GetType() == kInt_t) {
00328 mtype = 5;
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 }
00349
00350 fDataMembers[mtype].Add(dm);
00351 }
00352
00353 TIter iBase(cl->GetListOfBases());
00354 TBaseClass* base = 0;
00355 while ((base = (TBaseClass*)iBase()))
00356 AddClassDataMembersRecursively(base);
00357
00358 if (!bc)
00359 for (Int_t access = 0; access < 6; ++access) {
00360 fDataMembers[access].SetOwner(kFALSE);
00361 if (access < 3)
00362 fDataMembers[access].Sort();
00363 }
00364 }
00365
00366
00367
00368 void TDocParser::AnchorFromLine(const TString& line, TString& anchor) {
00369
00370
00371
00372 const char base64String[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
00373
00374
00375
00376
00377 UInt_t hash = ::Hash(line);
00378 anchor.Remove(0);
00379
00380 anchor += base64String[hash % 52];
00381 hash /= 52;
00382 while (hash) {
00383 anchor += base64String[hash % 64];
00384 hash /= 64;
00385 }
00386 }
00387
00388
00389 void TDocParser::Convert(std::ostream& out, std::istream& in, const char* relpath,
00390 Bool_t isCode, Bool_t interpretDirectives)
00391 {
00392
00393
00394 fLineNumber = 0;
00395 fParseContext.clear();
00396 if (isCode) fParseContext.push_back(kCode);
00397 else fParseContext.push_back(kComment);
00398
00399 while (!in.eof()) {
00400 fLineRaw.ReadLine(in, kFALSE);
00401 ++fLineNumber;
00402 if (in.eof())
00403 break;
00404
00405
00406 fLineComment = "";
00407 fLineSource = fLineRaw;
00408 fLineStripped = fLineRaw;
00409 Strip(fLineStripped);
00410
00411 DecorateKeywords(fLineSource);
00412 ProcessComment();
00413
00414
00415
00416
00417
00418 if (!interpretDirectives) {
00419
00420 if (!InContext(kDirective)) {
00421 GetDocOutput()->AdjustSourcePath(fLineSource, relpath);
00422 out << fLineSource << endl;
00423 }
00424 } else {
00425
00426 if (fLineComment.Length() ) {
00427 GetDocOutput()->AdjustSourcePath(fLineComment, relpath);
00428 out << fLineComment << endl;
00429 } else if (!InContext(kDirective)) {
00430 GetDocOutput()->AdjustSourcePath(fLineSource, relpath);
00431 out << fLineSource << endl;
00432 }
00433 }
00434 }
00435 }
00436
00437
00438 void TDocParser::DecorateKeywords(std::ostream& out, const char *text)
00439 {
00440
00441 TString str(text);
00442 DecorateKeywords(str);
00443 out << str;
00444 }
00445
00446
00447 void TDocParser::DecorateKeywords(TString& line)
00448 {
00449
00450
00451
00452
00453
00454 std::list<TClass*> currentType;
00455
00456 enum {
00457 kNada,
00458 kMember,
00459 kScope,
00460 kNumAccesses
00461 } scoping = kNada;
00462
00463 currentType.push_back(0);
00464
00465 Ssiz_t i = 0;
00466 while (isspace((UChar_t)line[i]))
00467 ++i;
00468
00469 Ssiz_t startOfLine = i;
00470
00471
00472
00473 Ssiz_t copiedToCommentUpTo = 0;
00474
00475 if (InContext(kDirective) && fDirectiveHandlers.Last()) {
00476
00477 TDocDirective* directive = (TDocDirective*)fDirectiveHandlers.Last();
00478 const char* endTag = directive->GetEndTag();
00479 Ssiz_t posEndTag = i;
00480 while (kNPOS != (posEndTag = line.Index(endTag, posEndTag, TString::kIgnoreCase)))
00481 if (posEndTag == 0 || line[posEndTag - 1] != '"')
00482 break;
00483 if (posEndTag != kNPOS)
00484 i = posEndTag;
00485 else {
00486 Ssiz_t start = 0;
00487 if (!InContext(kComment) || (InContext(kComment) & kCXXComment)) {
00488
00489 while (isspace((UChar_t)fLineRaw[start])) ++start;
00490 if (fLineRaw[start] == '/' && fLineRaw[start + 1] == '/')
00491 start += 2;
00492 else start = 0;
00493 }
00494 directive->AddLine(fLineRaw(start, fLineRaw.Length()));
00495 while(i < line.Length())
00496 fDocOutput->ReplaceSpecialChars(line, i);
00497 copiedToCommentUpTo = i;
00498 }
00499 }
00500
00501 for (; i < line.Length(); ++i) {
00502
00503 if (!currentType.back())
00504 scoping = kNada;
00505
00506
00507 if (Context() == kCode
00508 || Context() == kComment) {
00509 if (currentType.back())
00510 switch (line[i]) {
00511 case ':':
00512 if (line[i + 1] == ':') {
00513 scoping = kScope;
00514 i += 1;
00515 continue;
00516 }
00517 break;
00518 case '-':
00519 if (line[i + 1] == '>') {
00520 scoping = kMember;
00521 i += 1;
00522 continue;
00523 }
00524 break;
00525 case '.':
00526 if (line[i + 1] != '.') {
00527
00528 scoping = kMember;
00529 continue;
00530 }
00531 break;
00532 }
00533 switch (line[i]) {
00534 case '(':
00535 currentType.push_back(0);
00536 scoping = kNada;
00537 continue;
00538 break;
00539 case ')':
00540 if (currentType.size() > 1)
00541 currentType.pop_back();
00542 scoping = kMember;
00543 continue;
00544 break;
00545 }
00546 if (i >= line.Length())
00547 break;
00548 } else
00549 currentType.back() = 0;
00550
00551
00552 if (!IsWord(line[i])){
00553
00554 Bool_t haveHtmlEscapedChar = Context() == kString
00555 && i > 2 && line[i] == '\'' && line[i-1] == ';';
00556 if (haveHtmlEscapedChar) {
00557 Ssiz_t posBegin = i - 2;
00558 while (posBegin > 0 && IsWord(line[posBegin]))
00559 --posBegin;
00560 haveHtmlEscapedChar = posBegin > 0 &&
00561 line[posBegin] == '&' && line[posBegin - 1] == '\'';
00562 }
00563 EParseContext context = Context();
00564 Bool_t closeString = context == kString
00565 && ( line[i] == '"'
00566 || (line[i] == '\''
00567 && ( (i > 1 && line[i - 2] == '\'')
00568 || (i > 3 && line[i - 2] == '\\' && line[i - 3] == '\'')))
00569 || haveHtmlEscapedChar)
00570 && (i == 0 || line[i - 1] != '\\');
00571 if (context == kCode || context == kComment) {
00572 if (line[i] == '"' || (line[i] == '\'' && (
00573
00574 (line.Length() > i + 2 && line[i + 2] == '\'') ||
00575
00576 (line.Length() > i + 3 && line[i + 1] == '\'' && line[i + 3] == '\'')))) {
00577
00578 fDocOutput->DecorateEntityBegin(line, i, kString);
00579 fParseContext.push_back(kString);
00580 currentType.back() = 0;
00581 closeString = kFALSE;
00582 } else if (context == kCode
00583 && line[i] == '/' && (line[i+1] == '/' || line[i+1] == '*')) {
00584 fParseContext.push_back(kComment);
00585 if (line[i+1] == '/')
00586 fParseContext.back() |= kCXXComment;
00587 currentType.back() = 0;
00588 fDocOutput->DecorateEntityBegin(line, i, kComment);
00589 ++i;
00590 } else if (context == kComment
00591 && !(fParseContext.back() & kCXXComment)
00592 && line.Length() > i + 1
00593 && line[i] == '*' && line[i+1] == '/') {
00594 if (fParseContext.size()>1)
00595 fParseContext.pop_back();
00596
00597 currentType.back() = 0;
00598 i += 2;
00599 fDocOutput->DecorateEntityEnd(line, i, kComment);
00600 if (!fCommentAtBOL) {
00601 if (InContext(kDirective))
00602 ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(line(copiedToCommentUpTo, i));
00603 else
00604 fLineComment += line(copiedToCommentUpTo, i);
00605 copiedToCommentUpTo = i;
00606 }
00607 } else if (startOfLine == i
00608 && line[i] == '#'
00609 && context == kCode) {
00610 ExpandCPPLine(line, i);
00611 }
00612 }
00613
00614 if (i < line.Length())
00615 fDocOutput->ReplaceSpecialChars(line, i);
00616
00617 if (closeString) {
00618 fDocOutput->DecorateEntityEnd(line, i, kString);
00619 if (fParseContext.size()>1)
00620 fParseContext.pop_back();
00621
00622 currentType.back() = 0;
00623 }
00624 --i;
00625
00626 continue;
00627 }
00628
00629
00630 Ssiz_t endWord = i;
00631 while (endWord < line.Length() && IsName(line[endWord]))
00632 endWord++;
00633
00634 if (Context() == kString || Context() == kCPP) {
00635
00636 i = endWord - 1;
00637 continue;
00638 }
00639
00640 TString word(line(i, endWord - i));
00641
00642
00643 if ((i == 0 || (i > 0 && line[i - 1] != '"'))
00644 && HandleDirective(line, i, word, copiedToCommentUpTo)) {
00645
00646 currentType.back() = 0;
00647 continue;
00648 }
00649
00650
00651 if (Context() == kCode
00652 && fgKeywords.find(word.Data()) != fgKeywords.end()) {
00653 fDocOutput->DecorateEntityBegin(line, i, kKeyword);
00654 i += word.Length();
00655 fDocOutput->DecorateEntityEnd(line, i, kKeyword);
00656 --i;
00657 currentType.back() = 0;
00658 continue;
00659 }
00660
00661
00662
00663
00664
00665
00666
00667
00668 TDataType* subType = 0;
00669 TClass* subClass = 0;
00670 TDataMember *datamem = 0;
00671 TMethod *meth = 0;
00672 const char* globalTypeName = 0;
00673 if (!currentType.size()) {
00674 Warning("DecorateKeywords", "type context is empty!");
00675 currentType.push_back(0);
00676 }
00677 TClass* lookupScope = currentType.back();
00678
00679 if (scoping == kNada) {
00680 if (fCurrentClass)
00681 lookupScope = fCurrentClass;
00682 else
00683 lookupScope = fRecentClass;
00684 }
00685
00686 if (scoping == kNada) {
00687 subType = gROOT->GetType(word);
00688 if (!subType)
00689 subClass = fHtml->GetClass(word);
00690 if (!subType && !subClass) {
00691 TGlobal *global = gROOT->GetGlobal(word);
00692 if (global) {
00693
00694 globalTypeName = global->GetTypeName();
00695 subClass = fHtml->GetClass(globalTypeName);
00696 if (!subClass)
00697 subType = gROOT->GetType(globalTypeName);
00698 else
00699 if (subClass == THtml::Class() && word != "gHtml")
00700 subClass = 0;
00701 }
00702 }
00703 if (!subType && !subClass) {
00704
00705
00706
00707 }
00708 if (!subType && !subClass) {
00709
00710 while (isspace(line[endWord])) ++endWord;
00711 if (line[endWord] == '<' || line[endWord] == '>') {
00712
00713 Ssiz_t endWordT = endWord + 1;
00714 int templateLevel = 1;
00715 while (endWordT < line.Length()
00716 && (templateLevel
00717 || IsName(line[endWordT])
00718 || line[endWordT] == '<'
00719 || line[endWordT] == '>')) {
00720 if (line[endWordT] == '<')
00721 ++templateLevel;
00722 else if (line[endWordT] == '>')
00723 --templateLevel;
00724 endWordT++;
00725 }
00726 subClass = fHtml->GetClass(line(i, endWordT - i).Data());
00727 if (subClass)
00728 word = line(i, endWordT - i);
00729 }
00730 }
00731 }
00732
00733 if (lookupScope && !subType && !subClass) {
00734 if (scoping == kScope) {
00735 TString subClassName(lookupScope->GetName());
00736 subClassName += "::";
00737 subClassName += word;
00738 subClass = fHtml->GetClass(subClassName);
00739 if (!subClass)
00740 subType = gROOT->GetType(subClassName);
00741 }
00742 if (!subClass && !subType) {
00743
00744 datamem = lookupScope->GetDataMember(word);
00745 if (!datamem)
00746 meth = lookupScope->GetMethodAllAny(word);
00747 }
00748 if (!subClass && !subType && !datamem && !meth) {
00749
00750 while (isspace(line[endWord])) ++endWord;
00751 if (line[endWord] == '<' || line[endWord] == '>') {
00752
00753 Ssiz_t endWordT = endWord + 1;
00754 int templateLevel = 1;
00755 while (endWordT < line.Length()
00756 && (templateLevel
00757 || IsName(line[endWordT])
00758 || line[endWordT] == '<'
00759 || line[endWordT] == '>')) {
00760 if (line[endWordT] == '<')
00761 ++templateLevel;
00762 else if (line[endWordT] == '>')
00763 --templateLevel;
00764 endWordT++;
00765 }
00766 TString subClassName(lookupScope->GetName());
00767 subClassName += "::";
00768 subClassName += line(i, endWordT - i);
00769 subClass = fHtml->GetClass(subClassName);
00770 if (subClass)
00771 word = line(i, endWordT - i);
00772 }
00773 }
00774 }
00775
00776 TString mangledWord(word);
00777 fDocOutput->ReplaceSpecialChars(mangledWord);
00778 line.Replace(i, word.Length(), mangledWord);
00779
00780 TSubString substr(line(i, mangledWord.Length()));
00781 if (subType) {
00782 fDocOutput->ReferenceEntity(substr, subType,
00783 globalTypeName ? globalTypeName : subType->GetName());
00784 currentType.back() = 0;
00785 } else if (subClass) {
00786 fDocOutput->ReferenceEntity(substr, subClass,
00787 globalTypeName ? globalTypeName : subClass->GetName());
00788
00789 currentType.back() = subClass;
00790 fRecentClass = subClass;
00791 } else if (datamem || meth) {
00792 if (datamem) {
00793 fDocOutput->ReferenceEntity(substr, datamem);
00794
00795 if (datamem->GetTypeName())
00796 currentType.back() = fHtml->GetClass(datamem->GetTypeName());
00797 } else {
00798 fDocOutput->ReferenceEntity(substr, meth);
00799
00800 TString retTypeName = meth->GetReturnTypeName();
00801 if (retTypeName.BeginsWith("const "))
00802 retTypeName.Remove(0,6);
00803 Ssiz_t pos=0;
00804 while (IsWord(retTypeName[pos]) || retTypeName[pos]=='<' || retTypeName[pos]=='>' || retTypeName[pos]==':')
00805 ++pos;
00806 retTypeName.Remove(pos, retTypeName.Length());
00807 if (retTypeName.Length())
00808 currentType.back() = fHtml->GetClass(retTypeName);
00809 }
00810 } else
00811 currentType.back() = 0;
00812
00813
00814 i += substr.Length();
00815
00816 --i;
00817 }
00818 if (i > line.Length())
00819 i = line.Length();
00820
00821
00822 if (Context() == kString) {
00823 fDocOutput->DecorateEntityEnd(line, i, kString);
00824 if (fParseContext.size()>1)
00825 fParseContext.pop_back();
00826 currentType.back() = 0;
00827 }
00828
00829
00830
00831
00832
00833 if ((InContext(kComment) || fCommentAtBOL) && copiedToCommentUpTo < line.Length()) {
00834 if (InContext(kDirective))
00835 ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(line(copiedToCommentUpTo, line.Length()));
00836 else
00837 fLineComment += line(copiedToCommentUpTo, line.Length());
00838 }
00839
00840
00841
00842
00843 if (InContext(kComment) & kCXXComment) {
00844 fDocOutput->DecorateEntityEnd(line, i, kComment);
00845 if (fLineComment.Length()) {
00846 Ssiz_t pos = fLineComment.Length();
00847 fDocOutput->DecorateEntityEnd(fLineComment, pos, kComment);
00848 }
00849 RemoveCommentContext(kTRUE);
00850 currentType.back() = 0;
00851 }
00852 }
00853
00854
00855 void TDocParser::DecrementMethodCount(const char* name)
00856 {
00857
00858
00859
00860 typedef std::map<std::string , Int_t > MethodCount_t;
00861 MethodCount_t::iterator iMethodName = fMethodCounts.find(name);
00862 if (iMethodName != fMethodCounts.end()) {
00863 --(iMethodName->second);
00864 if (iMethodName->second <= 0)
00865 fMethodCounts.erase(iMethodName);
00866 }
00867 }
00868
00869
00870 void TDocParser::DeleteDirectiveOutput() const
00871 {
00872
00873
00874
00875 TIter iClass(gROOT->GetListOfClasses());
00876 TClass* cl = 0;
00877 while ((cl = (TClass*) iClass()))
00878 if (cl != TDocDirective::Class()
00879 && cl->InheritsFrom(TDocDirective::Class())) {
00880 TDocDirective* directive = (TDocDirective*) cl->New();
00881 if (!directive) continue;
00882 directive->SetParser(const_cast<TDocParser*>(this));
00883 directive->DeleteOutput();
00884 delete directive;
00885 }
00886 }
00887
00888
00889 void TDocParser::ExpandCPPLine(TString& line, Ssiz_t& pos)
00890 {
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 Bool_t linkExist = kFALSE;
00903 Ssiz_t posEndOfLine = line.Length();
00904 Ssiz_t posHash = pos;
00905
00906 Ssiz_t posInclude = line.Index("include", pos);
00907 if (posInclude != kNPOS) {
00908 TString filename;
00909 Ssiz_t posStartFilename = posInclude + 7;
00910 if (line.Tokenize(filename, posStartFilename, "[<\"]")) {
00911 Ssiz_t posEndFilename = posStartFilename;
00912 if (line.Tokenize(filename, posEndFilename, "[>\"]")) {
00913 R__LOCKGUARD(fHtml->GetMakeClassMutex());
00914
00915 TString filesysFileName;
00916 if (fHtml->GetPathDefinition().GetFileNameFromInclude(filename, filesysFileName)) {
00917 fDocOutput->CopyHtmlFile(filesysFileName);
00918
00919 TString endOfLine(line(posEndFilename - 1, line.Length()));
00920 line.Remove(posStartFilename, line.Length());
00921 for (Ssiz_t i = pos; i < line.Length();)
00922 fDocOutput->ReplaceSpecialChars(line, i);
00923
00924 line += "<a href=\"./";
00925 line += gSystem->BaseName(filename);
00926 line += "\">";
00927 line += filename + "</a>" + endOfLine[0];
00928 posEndOfLine = line.Length() - 1;
00929 fDocOutput->ReplaceSpecialChars(line, posEndOfLine);
00930
00931 line += endOfLine(1, endOfLine.Length());
00932
00933 linkExist = kTRUE;
00934 }
00935 }
00936 }
00937 }
00938
00939 if (!linkExist) {
00940 fDocOutput->ReplaceSpecialChars(line);
00941 posEndOfLine = line.Length();
00942 }
00943
00944 Ssiz_t posHashAfterDecoration = posHash;
00945 fDocOutput->DecorateEntityBegin(line, posHashAfterDecoration, kCPP);
00946 posEndOfLine += posHashAfterDecoration - posHash;
00947
00948 fDocOutput->DecorateEntityEnd(line, posEndOfLine, kCPP);
00949 pos = posEndOfLine;
00950 }
00951
00952
00953
00954 void TDocParser::GetCurrentModule(TString& out_module) const {
00955
00956 if (fCurrentModule) out_module = fCurrentModule;
00957 else if (fCurrentClass) fHtml->GetModuleNameForClass(out_module, fCurrentClass);
00958 else out_module = "(UNKNOWN MODULE WHILE PARSING)";
00959 }
00960
00961
00962 Bool_t TDocParser::HandleDirective(TString& line, Ssiz_t& pos, TString& word,
00963 Ssiz_t& copiedToCommentUpTo)
00964 {
00965
00966
00967
00968 Bool_t begin = kTRUE;
00969 TClass* clDirective = IsDirective(line, pos, word, begin);
00970 if (!clDirective)
00971 return kFALSE;
00972
00973
00974 Bool_t end = !begin;
00975
00976 TDocDirective* directive = 0;
00977
00978 if (begin) {
00979
00980 if (InContext(kDirective))
00981 ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(fLineSource(copiedToCommentUpTo, pos - copiedToCommentUpTo));
00982 else
00983 fLineComment += fLineSource(copiedToCommentUpTo, pos - copiedToCommentUpTo);
00984 copiedToCommentUpTo = pos;
00985
00986 pos += word.Length();
00987
00988 directive = (TDocDirective*) clDirective->New();
00989 if (!directive)
00990 return kFALSE;
00991
00992 directive->SetParser(this);
00993 if (fCurrentMethodTag.Length())
00994 directive->SetTag(fCurrentMethodTag);
00995 directive->SetCounter(fDirectiveCount++);
00996
00997
00998 TString params;
00999 if (begin && line[pos] == '(') {
01000 std::list<char> waitForClosing;
01001 Ssiz_t endParam = pos + 1;
01002 for (; endParam < line.Length()
01003 && (line[endParam] != ')' || !waitForClosing.empty()); ++endParam) {
01004 const char c = line[endParam];
01005 if (!waitForClosing.empty() && waitForClosing.back() == c) {
01006 waitForClosing.pop_back();
01007 continue;
01008 }
01009 switch (c) {
01010 case '"':
01011 if (waitForClosing.empty() || waitForClosing.back() != '\'')
01012 waitForClosing.push_back('"');
01013 break;
01014 case '\'':
01015 if (waitForClosing.empty() || waitForClosing.back() != '"')
01016 waitForClosing.push_back('\'');
01017 break;
01018 case '(':
01019 if (waitForClosing.empty() || (waitForClosing.back() != '"' && waitForClosing.back() != '\''))
01020 waitForClosing.push_back(')');
01021 break;
01022 case '\\':
01023 ++endParam;
01024 default:
01025 break;
01026 };
01027 }
01028 if (waitForClosing.empty()) {
01029 params = line(pos + 1, endParam - (pos + 1));
01030 pos += params.Length() + 2;
01031 }
01032 directive->SetParameters(params);
01033 }
01034
01035
01036 Ssiz_t posEndTag = pos;
01037 const char* endTag = directive->GetEndTag();
01038 Ssiz_t lenEndTag = strlen(endTag);
01039 while (kNPOS != (posEndTag = line.Index(endTag, posEndTag, TString::kIgnoreCase))) {
01040 if (line[posEndTag - 1] == '"') {
01041 posEndTag += lenEndTag;
01042 continue;
01043 }
01044 break;
01045 }
01046 if (posEndTag != kNPOS) {
01047 end = kTRUE;
01048 } else {
01049 fDirectiveHandlers.AddLast(directive);
01050
01051 fParseContext.push_back(kDirective);
01052 if (InContext(kComment) & kCXXComment)
01053 fParseContext.back() |= kCXXComment;
01054
01055 posEndTag = line.Length();
01056 }
01057
01058 directive->AddLine(line(pos, posEndTag - pos));
01059 TString remainder(line(posEndTag, line.Length()));
01060 line.Remove(posEndTag, line.Length());
01061
01062 while (pos < line.Length())
01063 fDocOutput->ReplaceSpecialChars(line, pos);
01064
01065 pos = line.Length();
01066
01067 copiedToCommentUpTo = line.Length();
01068 line += remainder;
01069 }
01070
01071
01072 if (end) {
01073
01074 if (!begin)
01075 pos += word.Length();
01076 else pos += word.Length() - 2;
01077
01078 if (!directive) directive = (TDocDirective*) fDirectiveHandlers.Last();
01079
01080 if (!directive) {
01081 Warning("HandleDirective", "Cannot find directive handler object %s !",
01082 fLineRaw.Data());
01083 return kFALSE;
01084 }
01085
01086 if (!begin) {
01087 Ssiz_t start = 0;
01088 if (!InContext(kComment) || (InContext(kComment) & kCXXComment)) {
01089
01090 while (isspace((UChar_t)fLineRaw[start])) ++start;
01091 if (fLineRaw[start] == '/' && fLineRaw[start + 1] == '/')
01092 start += 2;
01093 else start = 0;
01094 }
01095 directive->AddLine(line(start, pos - word.Length() - start));
01096
01097 TString remainder(line(pos, line.Length()));
01098 line.Remove(pos, line.Length());
01099 fDocOutput->ReplaceSpecialChars(line);
01100 pos = line.Length();
01101 line += remainder;
01102 }
01103 copiedToCommentUpTo = pos;
01104
01105 TString result;
01106 directive->GetResult(result);
01107
01108 if (!begin)
01109 fDirectiveHandlers.Remove(fDirectiveHandlers.LastLink());
01110 delete directive;
01111
01112 if (!begin) {
01113
01114 Bool_t isInCxxComment = InContext(kDirective) & kCXXComment;
01115 if (fParseContext.size()>1)
01116 fParseContext.pop_back();
01117 if (isInCxxComment && !InContext(kComment)) {
01118 fParseContext.push_back(kComment | kCXXComment);
01119 fDocOutput->DecorateEntityBegin(line, pos, kComment);
01120 }
01121 }
01122
01123 if (InContext(kDirective) && fDirectiveHandlers.Last())
01124 ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(result(0, result.Length()));
01125 else
01126 fLineComment += result;
01127
01128
01129
01130
01131
01132
01133
01134
01135 }
01136
01137 return kTRUE;
01138 }
01139
01140
01141 UInt_t TDocParser::InContext(Int_t context) const
01142 {
01143
01144
01145
01146
01147
01148 UInt_t lowerContext = context & kParseContextMask;
01149 UInt_t contextFlag = context & kParseContextFlagMask;
01150
01151 for (std::list<UInt_t>::const_reverse_iterator iPC = fParseContext.rbegin();
01152 iPC != fParseContext.rend(); ++iPC)
01153 if (!lowerContext || ((lowerContext && ((*iPC & kParseContextMask) == lowerContext))
01154 && (!contextFlag || (contextFlag && (*iPC & contextFlag)))))
01155 return *iPC;
01156
01157 return 0;
01158 }
01159
01160
01161 void TDocParser::InitKeywords() const
01162 {
01163
01164
01165 if (!fgKeywords.empty())
01166 return;
01167
01168 fgKeywords.insert("asm");
01169 fgKeywords.insert("auto");
01170 fgKeywords.insert("bool");
01171 fgKeywords.insert("break");
01172 fgKeywords.insert("case");
01173 fgKeywords.insert("catch");
01174 fgKeywords.insert("char");
01175 fgKeywords.insert("class");
01176 fgKeywords.insert("const");
01177 fgKeywords.insert("const_cast");
01178 fgKeywords.insert("continue");
01179 fgKeywords.insert("default");
01180 fgKeywords.insert("delete");
01181 fgKeywords.insert("do");
01182 fgKeywords.insert("double");
01183 fgKeywords.insert("dynamic_cast");
01184 fgKeywords.insert("else");
01185 fgKeywords.insert("enum");
01186 fgKeywords.insert("explicit");
01187 fgKeywords.insert("export");
01188 fgKeywords.insert("extern");
01189 fgKeywords.insert("false");
01190 fgKeywords.insert("float");
01191 fgKeywords.insert("for");
01192 fgKeywords.insert("friend");
01193 fgKeywords.insert("goto");
01194 fgKeywords.insert("if");
01195 fgKeywords.insert("inline");
01196 fgKeywords.insert("int");
01197 fgKeywords.insert("long");
01198 fgKeywords.insert("mutable");
01199 fgKeywords.insert("namespace");
01200 fgKeywords.insert("new");
01201 fgKeywords.insert("operator");
01202 fgKeywords.insert("private");
01203 fgKeywords.insert("protected");
01204 fgKeywords.insert("public");
01205 fgKeywords.insert("register");
01206 fgKeywords.insert("reinterpret_cast");
01207 fgKeywords.insert("return");
01208 fgKeywords.insert("short");
01209 fgKeywords.insert("signed");
01210 fgKeywords.insert("sizeof");
01211 fgKeywords.insert("static");
01212 fgKeywords.insert("static_cast");
01213 fgKeywords.insert("struct");
01214 fgKeywords.insert("switch");
01215 fgKeywords.insert("template");
01216 fgKeywords.insert("this");
01217 fgKeywords.insert("throw");
01218 fgKeywords.insert("true");
01219 fgKeywords.insert("try");
01220 fgKeywords.insert("typedef");
01221 fgKeywords.insert("typeid");
01222 fgKeywords.insert("typename");
01223 fgKeywords.insert("union");
01224 fgKeywords.insert("unsigned");
01225 fgKeywords.insert("using");
01226 fgKeywords.insert("virtual");
01227 fgKeywords.insert("void");
01228 fgKeywords.insert("volatile");
01229 fgKeywords.insert("wchar_t");
01230 fgKeywords.insert("while");
01231 }
01232
01233
01234 TClass* TDocParser::IsDirective(const TString& line, Ssiz_t pos,
01235 const TString& word, Bool_t& begin) const
01236 {
01237
01238
01239
01240
01241
01242
01243
01244
01245 if (pos > 0 && line[pos - 1] == '"')
01246 return 0;
01247
01248 begin = word.BeginsWith("begin_", TString::kIgnoreCase);
01249 Bool_t end = word.BeginsWith("end_", TString::kIgnoreCase);
01250
01251 if (!begin && !end)
01252 return 0;
01253
01254
01255
01256
01257
01258
01259 TString tag = word( begin ? 6 : 4, word.Length());
01260
01261 if (!tag.Length())
01262 return 0;
01263
01264 tag.ToLower();
01265 tag[0] -= 'a' - 'A';
01266 tag.Prepend("TDoc");
01267 tag += "Directive";
01268
01269 TClass* clDirective = TClass::GetClass(tag, kFALSE);
01270
01271 if (gDebug > 0 && !clDirective)
01272 Warning("IsDirective", "Unknown THtml directive %s in line %d!", word.Data(), fLineNo);
01273
01274 return clDirective;
01275 }
01276
01277
01278 Bool_t TDocParser::IsName(UChar_t c)
01279 {
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 Bool_t ret = kFALSE;
01292
01293 if (isalnum(c) || c == '_' || c == '~')
01294 ret = kTRUE;
01295
01296 return ret;
01297 }
01298
01299
01300
01301 Bool_t TDocParser::IsWord(UChar_t c)
01302 {
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 Bool_t ret = kFALSE;
01315
01316 if (isalpha(c) || c == '_' || c == '~')
01317 ret = kTRUE;
01318
01319 return ret;
01320 }
01321
01322
01323
01324 TMethod* TDocParser::LocateMethodInCurrentLine(Ssiz_t &posMethodName, TString& ret,
01325 TString& name, TString& params,
01326 Bool_t& isconst, std::ostream &srcOut,
01327 TString &anchor, std::ifstream& sourceFile,
01328 Bool_t allowPureVirtual)
01329 {
01330
01331
01332
01333
01334
01335
01336
01337 typedef std::map<std::string , Int_t > MethodCount_t;
01338 isconst = false;
01339
01340 if (posMethodName == kNPOS) {
01341 name.Remove(0);
01342 TMethod * meth = 0;
01343 Ssiz_t posBlock = fLineRaw.Index('{');
01344 Ssiz_t posQuote = fLineRaw.Index('"');
01345 if (posQuote != kNPOS && (posBlock == kNPOS || posQuote < posBlock))
01346 posBlock = posQuote;
01347 if (posBlock == kNPOS)
01348 posBlock = fLineRaw.Length();
01349 for (MethodCount_t::iterator iMethodName = fMethodCounts.begin();
01350 !name.Length() && iMethodName != fMethodCounts.end(); ++iMethodName) {
01351 TString lookFor(iMethodName->first);
01352 posMethodName = fLineRaw.Index(lookFor);
01353 if (posMethodName != kNPOS && posMethodName < posBlock
01354 && (posMethodName == 0 || !IsWord(fLineRaw[posMethodName - 1]))) {
01355
01356
01357 Ssiz_t posMethodEnd = posMethodName + lookFor.Length();
01358 while (isspace((UChar_t)fLineRaw[posMethodEnd])) ++posMethodEnd;
01359 if (fLineRaw[posMethodEnd] == '(') {
01360 meth = LocateMethodInCurrentLine(posMethodName, ret, name, params, isconst,
01361 srcOut, anchor, sourceFile, allowPureVirtual);
01362 if (name.Length())
01363 return meth;
01364 }
01365 }
01366 }
01367 return 0;
01368 }
01369
01370 name = fLineRaw(posMethodName, fLineRaw.Length() - posMethodName);
01371
01372
01373 ret = fLineRaw(0, posMethodName);
01374 if (ret.Length()) {
01375 while (ret.Length() && (IsName(ret[ret.Length() - 1]) || ret[ret.Length()-1] == ':'))
01376 ret.Remove(ret.Length() - 1, 1);
01377 Strip(ret);
01378 Bool_t didSomething = kTRUE;
01379 while (didSomething) {
01380 didSomething = kFALSE;
01381 if (ret.BeginsWith("inline ")) {
01382 didSomething = kTRUE;
01383 ret.Remove(0, 7);
01384 }
01385 if (ret.BeginsWith("static ")) {
01386 didSomething = kTRUE;
01387 ret.Remove(0, 7);
01388 }
01389 if (ret.BeginsWith("virtual ")) {
01390 didSomething = kTRUE;
01391 ret.Remove(0, 8);
01392 }
01393 }
01394 Strip(ret);
01395 }
01396
01397
01398 Ssiz_t posParam = name.First('(');
01399 if (posParam == kNPOS ||
01400
01401 ret.Contains("{") || ret.Contains("}") || ret.Contains("(") || ret.Contains(")")
01402 || ret.Contains("=")) {
01403 ret.Remove(0);
01404 name.Remove(0);
01405 params.Remove(0);
01406 return 0;
01407 }
01408
01409 if (name.BeginsWith("operator")) {
01410
01411 Ssiz_t checkOpBracketParam = posParam + 1;
01412 while (isspace((UChar_t)name[checkOpBracketParam]))
01413 ++checkOpBracketParam;
01414 if (name[checkOpBracketParam] == ')') {
01415 ++checkOpBracketParam;
01416 while (isspace((UChar_t)name[checkOpBracketParam]))
01417 ++checkOpBracketParam;
01418 if (name[checkOpBracketParam] == '(')
01419 posParam = checkOpBracketParam;
01420 }
01421 }
01422
01423 if (posParam == kNPOS) {
01424 ret.Remove(0);
01425 name.Remove(0);
01426 params.Remove(0);
01427 return 0;
01428 }
01429
01430 params = name(posParam, name.Length() - posParam);
01431 name.Remove(posParam);
01432 while (name.Length() && isspace((UChar_t)name[name.Length() - 1]))
01433 name.Remove(name.Length() - 1);
01434 if (!name.Length()) {
01435 ret.Remove(0);
01436 name.Remove(0);
01437 params.Remove(0);
01438 return 0;
01439 }
01440
01441 MethodCount_t::const_iterator iMethodName = fMethodCounts.find(name.Data());
01442 if (iMethodName == fMethodCounts.end() || iMethodName->second <= 0) {
01443 ret.Remove(0);
01444 name.Remove(0);
01445 params.Remove(0);
01446 return 0;
01447 }
01448
01449
01450 Ssiz_t posParamEnd = 1;
01451 Int_t bracketLevel = 1;
01452 while (bracketLevel) {
01453 const char* paramEnd = strpbrk(params.Data() + posParamEnd, ")(\"'");
01454 if (!paramEnd) {
01455
01456
01457 if (!anchor.Length()) {
01458
01459 AnchorFromLine(fLineStripped, anchor);
01460 if (srcOut)
01461 srcOut << "<a name=\"" << anchor << "\"></a>";
01462 }
01463 ++fLineNumber;
01464 if (srcOut)
01465 WriteSourceLine(srcOut);
01466
01467 fLineRaw.ReadLine(sourceFile, kFALSE);
01468 if (sourceFile.eof()) {
01469 Error("LocateMethodInCurrentLine",
01470 "Cannot find end of signature for function %s!",
01471 name.Data());
01472 break;
01473 }
01474
01475 fCommentAtBOL = kFALSE;
01476
01477
01478 fLineStripped = fLineRaw;
01479 Strip(fLineStripped);
01480
01481 fLineSource = fLineRaw;
01482 DecorateKeywords(fLineSource);
01483
01484 posParamEnd = params.Length();
01485 params += fLineRaw;
01486 } else
01487 posParamEnd = paramEnd - params.Data();
01488 switch (params[posParamEnd]) {
01489 case '(': ++bracketLevel; ++posParamEnd; break;
01490 case ')': --bracketLevel; ++posParamEnd; break;
01491 case '"':
01492 ++posParamEnd;
01493 while (params.Length() > posParamEnd && params[posParamEnd] != '"') {
01494
01495 if (params[posParamEnd] == '\\') ++posParamEnd;
01496 ++posParamEnd;
01497 }
01498 if (params.Length() <= posParamEnd) {
01499
01500 ret.Remove(0);
01501 name.Remove(0);
01502 params.Remove(0);
01503 return 0;
01504 }
01505 ++posParamEnd;
01506 break;
01507 case '\'':
01508 ++posParamEnd;
01509 if (params[posParamEnd] == '\\') ++posParamEnd;
01510 posParamEnd += 2;
01511 break;
01512 default:
01513 ++posParamEnd;
01514 }
01515 }
01516
01517 {
01518 TString pastParams(params(posParamEnd, params.Length()));
01519 pastParams = pastParams.Strip(TString::kLeading);
01520 isconst = pastParams.BeginsWith("const") && !(isalnum(pastParams[5]) || pastParams[5] == '_');
01521 }
01522
01523 Ssiz_t posBlock = params.Index('{', posParamEnd);
01524 Ssiz_t posSemicolon = params.Index(';', posParamEnd);
01525 Ssiz_t posPureVirt = params.Index('=', posParamEnd);
01526 if (posSemicolon != kNPOS)
01527 if ((posBlock == kNPOS || (posSemicolon < posBlock)) &&
01528 (posPureVirt == kNPOS || !allowPureVirtual)
01529 && !allowPureVirtual)
01530 params.Remove(0);
01531
01532 if (params.Length())
01533 params.Remove(posParamEnd);
01534
01535 if (!params.Length()) {
01536 ret.Remove(0);
01537 name.Remove(0);
01538 return 0;
01539 }
01540
01541 posMethodName = posParam + posParamEnd;
01542 if (fCurrentClass) {
01543 TMethod* meth = fCurrentClass->GetMethodAny(name);
01544 if (meth) {
01545 fDirectiveCount = 0;
01546 fCurrentMethodTag = name + "_";
01547 fCurrentMethodTag += fMethodCounts[name.Data()];
01548 return meth;
01549 }
01550 }
01551
01552 return 0;
01553 }
01554
01555
01556
01557 void TDocParser::Parse(std::ostream& out)
01558 {
01559
01560
01561
01562
01563 fClassDocState = kClassDoc_LookingNothingFound;
01564
01565 DeleteDirectiveOutput();
01566
01567 LocateMethodsInSource(out);
01568 LocateMethodsInHeaderInline(out);
01569 LocateMethodsInHeaderClassDecl(out);
01570
01571 if (!fSourceInfo[kInfoLastUpdate].Length()) {
01572 TDatime date;
01573 fSourceInfo[kInfoLastUpdate] = date.AsString();
01574 }
01575 }
01576
01577
01578 void TDocParser::LocateMethods(std::ostream& out, const char* filename,
01579 Bool_t lookForSourceInfo ,
01580 Bool_t useDocxxStyle ,
01581 Bool_t allowPureVirtual ,
01582 const char* methodPattern ,
01583 const char* sourceExt )
01584 {
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602 TString sourceFileName(filename);
01603 fCurrentFile = filename;
01604 if (!sourceFileName.Length()) {
01605 fHtml->GetImplFileName(fCurrentClass, kFALSE, sourceFileName);
01606 Error("LocateMethods", "Can't find source file '%s' for class %s!",
01607 sourceFileName.Data(), fCurrentClass->GetName());
01608 return;
01609 }
01610 ifstream sourceFile(sourceFileName.Data());
01611 if (!sourceFile || !sourceFile.good()) {
01612 Error("LocateMethods", "Can't open file '%s' for reading!", sourceFileName.Data());
01613 return;
01614 }
01615
01616 TPMERegexp patternRE(methodPattern ? methodPattern : "");
01617
01618 TString codeOneLiner;
01619 TString methodRet;
01620 TString methodName;
01621 TString methodParam;
01622 Bool_t methodIsConst = kFALSE;
01623 TString anchor;
01624 TString docxxComment;
01625
01626 Bool_t wroteMethodNowWaitingForOpenBlock = kFALSE;
01627
01628 std::ofstream srcHtmlOut;
01629 TString srcHtmlOutName;
01630 if (sourceExt && sourceExt[0]) {
01631 static_cast<TClassDocOutput*>(fDocOutput)->CreateSourceOutputStream(srcHtmlOut, sourceExt, srcHtmlOutName);
01632 fLineNumber = 0;
01633 } else {
01634 sourceExt = 0;
01635 srcHtmlOutName = fCurrentClass->GetName();
01636 fDocOutput->NameSpace2FileName(srcHtmlOutName);
01637 gSystem->PrependPathName("src", srcHtmlOutName);
01638 srcHtmlOutName += ".h.html";
01639 }
01640
01641 fParseContext.clear();
01642 fParseContext.push_back(kCode);
01643 fDocContext = kIgnore;
01644 fLineNo = 0;
01645
01646 while (!sourceFile.eof()) {
01647 Bool_t needAnchor = kFALSE;
01648
01649 ++fLineNo;
01650
01651 fLineRaw.ReadLine(sourceFile, kFALSE);
01652 if (sourceFile.eof()) break;
01653
01654 fCommentAtBOL = InContext(kComment);
01655
01656
01657 fLineStripped = fLineRaw;
01658 Strip(fLineStripped);
01659
01660 fLineSource = fLineRaw;
01661 fLineComment = "";
01662 DecorateKeywords(fLineSource);
01663
01664 if (!ProcessComment()) {
01665
01666
01667 if (fDocContext == kDocClass && fClassDocState < kClassDoc_Written) {
01668 TString strippedComment(fComment);
01669 Strip(strippedComment);
01670 if (strippedComment.Length() > 0) {
01671 fLastClassDoc = fComment;
01672 if (fClassDocState == kClassDoc_LookingNothingFound) {
01673 fFirstClassDoc = fComment;
01674 fClassDocState = kClassDoc_LookingHaveSomething;
01675 }
01676 }
01677 fDocContext = kIgnore;
01678 }
01679
01680 Ssiz_t impIdx = fLineStripped.Index("ClassImp(");
01681 if (impIdx == 0 && fClassDocState == kClassDoc_LookingHaveSomething) {
01682 TString name(fCurrentClass->GetName());
01683
01684 Ssiz_t posLastScope = kNPOS;
01685 while ((posLastScope = name.Index("::")) != kNPOS)
01686 name.Remove(0, posLastScope + 2);
01687
01688 Ssiz_t posName = fLineStripped.Index(name, impIdx);
01689 if (posName != kNPOS) {
01690 Ssiz_t posClosingParen = posName + name.Length();
01691 while (isspace(fLineStripped[posClosingParen])) ++posClosingParen;
01692 if (fLineStripped[posClosingParen] == ')') {
01693 WriteClassDoc(out, kFALSE);
01694 fDocContext = kIgnore;
01695 }
01696 }
01697 }
01698
01699 if (fLineStripped.Length())
01700
01701
01702 fLastClassDoc = "";
01703
01704
01705 if (methodName.Length() && !wroteMethodNowWaitingForOpenBlock) {
01706 TString savedComment;
01707 if (useDocxxStyle && docxxComment.Length()) {
01708 savedComment = fComment;
01709 fComment = docxxComment;
01710 }
01711 WriteMethod(out, methodRet, methodName, methodParam, methodIsConst,
01712 gSystem->BaseName(srcHtmlOutName), anchor, codeOneLiner);
01713 docxxComment.Remove(0);
01714 if (savedComment[0]) {
01715 fComment = savedComment;
01716 }
01717 }
01718
01719 if (!wroteMethodNowWaitingForOpenBlock) {
01720
01721 Ssiz_t posPattern = kNPOS;
01722 if (methodPattern) {
01723 posPattern = fLineRaw.Index((TPRegexp&)patternRE);
01724 }
01725 if (posPattern != kNPOS && methodPattern) {
01726
01727 static const char vetoChars[] = "{\"";
01728 for (int ich = 0; posPattern != kNPOS && vetoChars[ich]; ++ich) {
01729 Ssiz_t posVeto = fLineRaw.Index(vetoChars[ich]);
01730 if (posVeto != kNPOS && posVeto < posPattern)
01731 posPattern = kNPOS;
01732 }
01733 }
01734 if (posPattern != kNPOS || !methodPattern) {
01735 if (methodPattern) {
01736 patternRE.Match(fLineRaw);
01737 posPattern += patternRE[0].Length();
01738 }
01739 LocateMethodInCurrentLine(posPattern, methodRet, methodName,
01740 methodParam, methodIsConst, srcHtmlOut,
01741 anchor, sourceFile, allowPureVirtual);
01742 if (methodName.Length()) {
01743 fDocContext = kDocFunc;
01744 needAnchor = !anchor.Length();
01745 if (useDocxxStyle)
01746 docxxComment = fComment;
01747 fComment.Remove(0);
01748 codeOneLiner.Remove(0);
01749
01750 wroteMethodNowWaitingForOpenBlock = fLineRaw.Index("{", posPattern) == kNPOS;
01751 wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index(";", posPattern) == kNPOS;
01752 } else if (fLineRaw.First("{};") != kNPOS)
01753
01754 fComment.Remove(0);
01755 }
01756 else
01757 fComment.Remove(0);
01758 } else {
01759 wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index("{") == kNPOS;
01760 wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index(";") == kNPOS;
01761 }
01762
01763 if (methodName.Length() && !wroteMethodNowWaitingForOpenBlock) {
01764
01765 if (!codeOneLiner.Length() &&
01766 fLineSource.CountChar('{') == 1 &&
01767 fLineSource.CountChar('}') == 1) {
01768
01769 codeOneLiner = fLineSource;
01770 codeOneLiner.Remove(0, codeOneLiner.Index('{'));
01771 codeOneLiner.Remove(codeOneLiner.Index('}') + 1);
01772 }
01773 }
01774
01775 else if (!methodName.Length() && !useDocxxStyle)
01776 fComment.Remove(0);
01777
01778 if (needAnchor || fExtraLinesWithAnchor.find(fLineNo) != fExtraLinesWithAnchor.end()) {
01779 AnchorFromLine(fLineStripped, anchor);
01780 if (sourceExt)
01781 srcHtmlOut << "<a name=\"" << anchor << "\"></a>";
01782 }
01783
01784 }
01785
01786
01787 Ssiz_t posTag = kNPOS;
01788 if (lookForSourceInfo)
01789 for (Int_t si = 0; si < (Int_t) kNumSourceInfos; ++si)
01790 if (!fSourceInfo[si].Length() && (posTag = fLineRaw.Index(fSourceInfoTags[si])) != kNPOS) {
01791 fSourceInfo[si] = fLineRaw(posTag + strlen(fSourceInfoTags[si]), fLineRaw.Length() - posTag);
01792 if (si == kInfoAuthor)
01793 fDocOutput->FixupAuthorSourceInfo(fSourceInfo[kInfoAuthor]);
01794 }
01795
01796
01797
01798 ++fLineNumber;
01799 if (srcHtmlOut)
01800 WriteSourceLine(srcHtmlOut);
01801 else if (needAnchor)
01802 fExtraLinesWithAnchor.insert(fLineNo);
01803 }
01804
01805
01806 if (methodName.Length()) {
01807 if (useDocxxStyle && docxxComment.Length())
01808 fComment = docxxComment;
01809 WriteMethod(out, methodRet, methodName, methodParam, methodIsConst,
01810 gSystem->BaseName(srcHtmlOutName), anchor, codeOneLiner);
01811 docxxComment.Remove(0);
01812 } else
01813 WriteClassDoc(out);
01814
01815 srcHtmlOut << "</pre>" << std::endl;
01816
01817 fDocOutput->WriteLineNumbers(srcHtmlOut, fLineNumber, gSystem->BaseName(fCurrentFile));
01818
01819 srcHtmlOut << "</div>" << std::endl;
01820
01821 fDocOutput->WriteHtmlFooter(srcHtmlOut, "../");
01822
01823 fParseContext.clear();
01824 fParseContext.push_back(kCode);
01825 fDocContext = kIgnore;
01826 fCurrentFile = "";
01827 }
01828
01829
01830 void TDocParser::LocateMethodsInSource(std::ostream& out)
01831 {
01832
01833
01834
01835
01836
01837 Bool_t useDocxxStyle = (fHtml->GetDocStyle() == "Doc++");
01838
01839 TString pattern(fCurrentClass->GetName());
01840
01841 Ssiz_t posLastScope = kNPOS;
01842 while ((posLastScope = pattern.Index("::")) != kNPOS)
01843 pattern.Remove(0, posLastScope + 2);
01844 pattern += "::";
01845
01846 TString implFileName;
01847 if (fHtml->GetImplFileName(fCurrentClass, kTRUE, implFileName)) {
01848 LocateMethods(out, implFileName, kFALSE , useDocxxStyle,
01849 kFALSE , pattern, ".cxx.html");
01850 Ssiz_t posGt = pattern.Index('>');
01851 if (posGt != kNPOS) {
01852
01853 Ssiz_t posLt = pattern.Index('<');
01854 if (posLt != kNPOS && posLt < posGt) {
01855 pattern.Replace(posLt + 1, posGt - posLt - 1, ".*");
01856 LocateMethods(out, implFileName, kFALSE , useDocxxStyle,
01857 kFALSE , pattern, ".cxx.html");
01858 }
01859 }
01860 }
01861 }
01862
01863
01864 void TDocParser::LocateMethodsInHeaderInline(std::ostream& out)
01865 {
01866
01867
01868
01869
01870 Bool_t useDocxxStyle = kTRUE;
01871
01872 TString pattern(fCurrentClass->GetName());
01873
01874 Ssiz_t posLastScope = kNPOS;
01875 while ((posLastScope = pattern.Index("::")) != kNPOS)
01876 pattern.Remove(0, posLastScope + 1);
01877 pattern += "::";
01878
01879 TString declFileName;
01880 if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declFileName)) {
01881 LocateMethods(out, declFileName, kTRUE , useDocxxStyle,
01882 kFALSE , pattern, 0);
01883 Ssiz_t posGt = pattern.Index('>');
01884 if (posGt != kNPOS) {
01885
01886 Ssiz_t posLt = pattern.Index('<');
01887 if (posLt != kNPOS && posLt < posGt) {
01888 pattern.Replace(posLt + 1, posGt - posLt - 1, ".*");
01889 LocateMethods(out, declFileName, kTRUE , useDocxxStyle,
01890 kFALSE , pattern, 0);
01891 }
01892 }
01893 }
01894 }
01895
01896
01897 void TDocParser::LocateMethodsInHeaderClassDecl(std::ostream& out)
01898 {
01899
01900
01901
01902
01903 TString declFileName;
01904 if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declFileName))
01905 LocateMethods(out, declFileName, kTRUE, kTRUE ,
01906 kTRUE , 0, ".h.html");
01907 }
01908
01909
01910 Bool_t TDocParser::ProcessComment()
01911 {
01912
01913
01914
01915
01916
01917
01918 if (!fCommentAtBOL
01919 && !(fLineStripped[0] == '/'
01920 && (fLineStripped[1] == '/' || fLineStripped[1] == '*'))
01921 && !InContext(kComment) && !InContext(kDirective)) {
01922 fLineComment = "";
01923 return kFALSE;
01924 }
01925
01926
01927
01928
01929
01930 if (InContext(kDirective) && !fLineComment.Length())
01931 return kTRUE;
01932
01933 TString commentLine(fLineComment.Strip());
01934
01935
01936 Bool_t mustDealWithCommentAtBOL = fCommentAtBOL;
01937 Ssiz_t posComment = kNPOS;
01938 if (!fCommentAtBOL)
01939 posComment = commentLine.Index("<span class=\"comment\">", 0, TString::kIgnoreCase);
01940 Ssiz_t posSpanEnd = commentLine.Index("</span>", posComment == kNPOS?0:posComment, TString::kIgnoreCase);
01941 while ((mustDealWithCommentAtBOL && posSpanEnd != kNPOS) || posComment != kNPOS) {
01942 Int_t spanLevel = 1;
01943 Ssiz_t posSpan = commentLine.Index("<span", posComment + 1, TString::kIgnoreCase);
01944 while (spanLevel > 1 || (posSpan != kNPOS && posSpan < posSpanEnd)) {
01945
01946 if (posSpan != kNPOS && posSpan < posSpanEnd) {
01947 ++spanLevel;
01948 posSpan = commentLine.Index("<span", posSpan + 1, TString::kIgnoreCase);
01949
01950 continue;
01951 }
01952 --spanLevel;
01953
01954 posSpanEnd = commentLine.Index("</span>", posSpanEnd + 1, TString::kIgnoreCase);
01955 }
01956 if (posSpanEnd != kNPOS) {
01957
01958 commentLine.Remove(posSpanEnd, 7);
01959 if (posComment != kNPOS)
01960 commentLine.Remove(posComment, 22);
01961 else {
01962 mustDealWithCommentAtBOL = kFALSE;
01963
01964 posComment = 0;
01965 }
01966 posComment = commentLine.Index("<span class=\"comment\">", posComment, TString::kIgnoreCase);
01967 } else break;
01968 }
01969 if (posComment != kNPOS)
01970 commentLine.Remove(posComment, 22);
01971
01972
01973 if (!InContext(kComment) || (InContext(kComment) & kCXXComment)
01974 || (fLineStripped[0] == '/' && fLineStripped[1] == '*'))
01975 Strip(commentLine);
01976
01977
01978 if ((fClassDocState == kClassDoc_LookingNothingFound
01979 || fClassDocState == kClassDoc_LookingHaveSomething)
01980 && !fComment.Length()
01981 && fDocContext == kIgnore && commentLine.Contains(fClassDescrTag)) {
01982 fDocContext = kDocClass;
01983 }
01984
01985 char start_or_end = 0;
01986
01987 if (commentLine.Length()>1 && commentLine[0] == '/'
01988 && (commentLine[1] == '/' || commentLine[1] == '*')) {
01989 start_or_end = commentLine[1];
01990 commentLine.Remove(0, 2);
01991 }
01992
01993 if (start_or_end != '/' && commentLine.Length()>1
01994 && commentLine[commentLine.Length() - 2] == '*'
01995 && commentLine[commentLine.Length() - 1] == '/') {
01996 start_or_end = commentLine[commentLine.Length() - 2];
01997 commentLine.Remove(commentLine.Length()-2);
01998 }
01999
02000
02001 if (start_or_end && commentLine.Length() > 3) {
02002 TString lineAllOneChar(commentLine.Strip());
02003
02004 Ssiz_t len = lineAllOneChar.Length();
02005 if (len > 2) {
02006 Char_t c = lineAllOneChar[len - 1];
02007 if (c == lineAllOneChar[len - 2] && c == lineAllOneChar[len - 3]) {
02008 TString lineAllOneCharStripped = lineAllOneChar.Strip(TString::kTrailing, c);
02009 Strip(lineAllOneCharStripped);
02010 if (!lineAllOneCharStripped.Length()) {
02011 commentLine.Remove(0);
02012
02013
02014 if ((fClassDocState == kClassDoc_LookingNothingFound
02015 || fClassDocState == kClassDoc_LookingHaveSomething)
02016 && !fComment.Length()
02017 && fDocContext == kIgnore && start_or_end=='/') {
02018 fDocContext = kDocClass;
02019 }
02020 }
02021 }
02022 }
02023 }
02024
02025
02026 if (commentLine.Length() > 0 && start_or_end == commentLine[commentLine.Length() - 1])
02027
02028 commentLine = commentLine.Strip(TString::kTrailing, start_or_end);
02029
02030 if (commentLine.Length() > 2 && Context() != kDirective)
02031 while (commentLine.Length() > 2
02032 && !IsWord(commentLine[0])
02033 && commentLine[0] == commentLine[commentLine.Length() - 1])
02034 commentLine = commentLine.Strip(TString::kBoth, commentLine[0]);
02035
02036
02037 while (start_or_end && commentLine[0] == start_or_end)
02038 commentLine.Remove(0, 1);
02039
02040 fComment += commentLine + "\n";
02041
02042 return kTRUE;
02043 }
02044
02045
02046 void TDocParser::RemoveCommentContext(Bool_t cxxcomment)
02047 {
02048
02049
02050 UInt_t lookFor = kComment;
02051 if (cxxcomment) lookFor |= kCXXComment;
02052 std::list<UInt_t>::iterator iComment = fParseContext.end();
02053 for (std::list<UInt_t>::iterator iContext = fParseContext.begin();
02054 iContext != fParseContext.end(); ++ iContext)
02055 if (*iContext == lookFor) iComment =iContext;
02056 if (iComment != fParseContext.end())
02057 fParseContext.erase(iComment);
02058 }
02059
02060
02061 Bool_t TDocParser::Strip(TString& str)
02062 {
02063
02064 Bool_t changed = str[0] == ' ' || str[0] == '\t' || str[0] == '\n';
02065 changed |= str.Length()
02066 && (str[str.Length() - 1] == ' ' || str[str.Length() - 1] == '\t'
02067 || str[str.Length() - 1] == '\n');
02068 if (!changed) return kFALSE;
02069 Ssiz_t i = 0;
02070 while (str[i] == ' ' || str[i] == '\t' || str[i] == '\n')
02071 ++i;
02072 str.Remove(0,i);
02073 i = str.Length() - 1;
02074 while (i >= 0 && (str[i] == ' ' || str[i] == '\t' || str[i] == '\n'))
02075 --i;
02076 str.Remove(i + 1, str.Length());
02077 return kTRUE;
02078 }
02079
02080
02081 void TDocParser::WriteClassDoc(std::ostream& out, Bool_t first )
02082 {
02083
02084
02085 if (fClassDocState == kClassDoc_LookingHaveSomething || fClassDocState == kClassDoc_LookingNothingFound) {
02086 TString& classDoc = first || !fLastClassDoc.Length() ? fFirstClassDoc : fLastClassDoc;
02087 static_cast<TClassDocOutput*>(fDocOutput)->WriteClassDescription(out, classDoc);
02088 fClassDocState = kClassDoc_Written;
02089 }
02090
02091 }
02092
02093 namespace {
02094 static void RemoveUnneededSpaces(TString& s) {
02095
02096
02097 for (Ssiz_t i = 1; i < s.Length() - 1; ++i) {
02098 if (s[i] == ' ') {
02099 char p = s[i - 1];
02100 char n = s[i + 1];
02101 if (((isalnum(p) || p == '_') && (isalnum(n) || n == '_'))
02102 || (p == '>' && n == '>')) {
02103
02104 } else {
02105 while (isspace(s[i])) {
02106 s.Remove(i, 1);
02107 }
02108 }
02109 }
02110 }
02111 }
02112
02113 static void ParseParameters(TString& strippedParams, TList& paramArr) {
02114
02115
02116 int nest = 0;
02117 bool init = false;
02118 bool quoted = false;
02119 Ssiz_t len = strippedParams.Length();
02120 TString arg;
02121 for (Ssiz_t i = 0; i < len; ++i) {
02122 switch (strippedParams[i]) {
02123 case '<':
02124 case '(':
02125 case '[': ++nest; break;
02126 case '>':
02127 case ')':
02128 case ']': --nest; break;
02129 case '=': init = true; break;
02130 case '\'': ++i; if (strippedParams[i] == '\\') ++i; ++i; continue;
02131 case '\\': ++i; continue; break;
02132 case '"': quoted = !quoted; break;
02133 case ',': {
02134 if (!quoted && !nest) {
02135 TString strippedArg(arg.Strip(TString::kBoth));
02136 paramArr.AddLast(new TObjString(strippedArg));
02137 init = false;
02138 arg.Remove(0);
02139 continue;
02140 }
02141 }
02142 }
02143 if (!init) {
02144 arg += strippedParams[i];
02145 }
02146 }
02147 TString strippedLastArg(arg.Strip(TString::kBoth));
02148 if (strippedLastArg.Length()) {
02149 paramArr.AddLast(new TObjString(strippedLastArg));
02150 }
02151 }
02152
02153 void MatchOverloadSignatures(TCollection* candidates, TList* paramArr)
02154 {
02155
02156
02157 TList suppressed;
02158 TIter iCandidate(candidates);
02159 int nparams = paramArr->GetSize();
02160 for (int iparam = 0; iparam < nparams && candidates->GetSize() > 1; ++iparam) {
02161 TString& srcArg = ((TObjString*)paramArr->At(iparam))->String();
02162 TString noParName(srcArg);
02163 while (noParName.Length()
02164 && (isalnum(noParName[noParName.Length() - 1]) || noParName[noParName.Length() - 1] == '_'))
02165 noParName.Remove(noParName.Length() - 1);
02166 noParName = noParName.Strip(TString::kTrailing);
02167
02168 if (noParName.Length()) {
02169 RemoveUnneededSpaces(noParName);
02170 }
02171 RemoveUnneededSpaces(srcArg);
02172
02173
02174
02175
02176 for (int comparison = 0; comparison < 5; ++comparison) {
02177 if (comparison == 1 && noParName == srcArg)
02178
02179 continue;
02180 suppressed.Clear();
02181 iCandidate.Reset();
02182 TDocMethodWrapper* method = 0;
02183 while ((method = (TDocMethodWrapper*) iCandidate())) {
02184 TMethodArg* methArg = (TMethodArg*) method->GetMethod()->GetListOfMethodArgs()->At(iparam);
02185 TString sMethArg = methArg->GetFullTypeName();
02186 RemoveUnneededSpaces(sMethArg);
02187 bool matches = false;
02188 switch (comparison) {
02189 case 0: matches = (srcArg == sMethArg); break;
02190 case 1: matches = (noParName == sMethArg); break;
02191 case 2: matches = srcArg.Contains(sMethArg) || sMethArg.Contains(srcArg); break;
02192 }
02193 if (!matches) {
02194 suppressed.Add(method);
02195 }
02196 }
02197 if (suppressed.GetSize()
02198 && suppressed.GetSize() < candidates->GetSize()) {
02199 candidates->RemoveAll(&suppressed);
02200 break;
02201 }
02202 if (!suppressed.GetSize()) {
02203
02204 break;
02205 }
02206 }
02207 }
02208 if (candidates->GetSize() > 1) {
02209
02210 suppressed.Clear();
02211 iCandidate.Reset();
02212 TDocMethodWrapper* method = 0;
02213 while ((method = (TDocMethodWrapper*) iCandidate())) {
02214 if (method->TestBit(TDocMethodWrapper::kDocumented)) {
02215 suppressed.AddLast(method);
02216 }
02217 }
02218 if (suppressed.GetSize()
02219 && suppressed.GetSize() < candidates->GetSize()) {
02220 candidates->RemoveAll(&suppressed);
02221 }
02222 }
02223 }
02224 }
02225
02226
02227 void TDocParser::WriteMethod(std::ostream& out, TString& ret,
02228 TString& name, TString& params, Bool_t isconst,
02229 const char* filename, TString& anchor,
02230 TString& codeOneLiner)
02231 {
02232
02233
02234
02235 if (fClassDocState < kClassDoc_Written)
02236 WriteClassDoc(out);
02237
02238 TString strippedParams(params);
02239 if (strippedParams[0] == '(') {
02240 strippedParams.Remove(0, 1);
02241 strippedParams.Remove(strippedParams.Length() - 1);
02242 strippedParams = strippedParams.Strip(TString::kBoth);
02243 }
02244
02245 TList paramArr;
02246 paramArr.SetOwner();
02247 ParseParameters(strippedParams, paramArr);
02248 int nparams = paramArr.GetSize();
02249
02250
02251 TList candidates;
02252 for (int access = 0; access < 3; ++access) {
02253 TList* methList = fMethods[access].GetListForObject(name);
02254 if (!methList) continue;
02255
02256 TIter nextMethod(methList);
02257 TDocMethodWrapper* method = 0;
02258 while ((method = (TDocMethodWrapper *) nextMethod())) {
02259 if (name == method->GetName()
02260 && isconst == ((method->GetMethod()->Property() & kIsMethConst) > 0)
02261 && method->GetMethod()->GetListOfMethodArgs()->GetSize() == nparams) {
02262 candidates.Add(method);
02263 }
02264 }
02265 }
02266
02267 if (nparams && candidates.GetSize() > 1) {
02268 MatchOverloadSignatures(&candidates, ¶mArr);
02269 }
02270
02271 TDocMethodWrapper* guessedMethod = 0;
02272 if (candidates.GetSize() == 1) {
02273 guessedMethod = (TDocMethodWrapper*) candidates.First();
02274 guessedMethod->SetBit(TDocMethodWrapper::kDocumented);
02275 }
02276
02277 static_cast<TClassDocOutput*>(fDocOutput)->WriteMethod(out, ret, name, params, filename, anchor,
02278 fComment, codeOneLiner, guessedMethod);
02279
02280 DecrementMethodCount(name);
02281 ret.Remove(0);
02282 name.Remove(0);
02283 params.Remove(0);
02284 anchor.Remove(0);
02285 fComment.Remove(0);
02286
02287 fDocContext = kIgnore;
02288 }
02289
02290
02291 void TDocParser::WriteSourceLine(std::ostream& out)
02292 {
02293
02294
02295
02296 fDocOutput->AdjustSourcePath(fLineSource);
02297 out << fLineSource << std::endl;
02298
02299 }