36 class TMethodWrapperImpl:
public TDocMethodWrapper {
38 TMethodWrapperImpl(TMethod* m,
int overloadIdx):
39 fMeth(m), fOverloadIdx(overloadIdx) {}
41 static void SetClass(
const TClass* cl) { fgClass = cl; }
43 const char* GetName()
const {
return fMeth->GetName(); }
44 ULong_t Hash()
const {
return fMeth->Hash();}
45 Int_t GetNargs()
const {
return fMeth->GetNargs(); }
46 virtual TMethod* GetMethod()
const {
return fMeth; }
47 Bool_t IsSortable()
const {
return kTRUE; }
49 Int_t GetOverloadIdx()
const {
return fOverloadIdx; }
51 Int_t Compare(
const TObject *obj)
const {
52 const TMethodWrapperImpl* m =
dynamic_cast<const TMethodWrapperImpl*
>(obj);
55 Int_t ret = strcasecmp(GetName(), m->GetName());
57 if (GetNargs() < m->GetNargs())
return -1;
58 else if (GetNargs() > m->GetNargs())
return 1;
59 if (GetMethod()->GetClass()->InheritsFrom(m->GetMethod()->GetClass()))
65 const char* l(GetName());
66 const char* r(m->GetName());
67 if (l[0] ==
'~' && r[0] ==
'~') {
73 if (fMeth->Property() & (kIsConstructor|kIsDestructor)) {
74 lcl = TClass::GetClass(l);
76 if (m->fMeth->Property() & (kIsConstructor|kIsDestructor)) {
77 rcl = TClass::GetClass(r);
79 if (lcl && fgClass->InheritsFrom(lcl)) {
80 if (rcl && fgClass->InheritsFrom(rcl)) {
81 if (lcl->InheritsFrom(rcl))
85 }
else if (rcl && fgClass->InheritsFrom(rcl))
88 if (l[0] ==
'~')
return -1;
89 if (r[0] ==
'~')
return 1;
90 return (ret < 0) ? -1 : 1;
94 static const TClass* fgClass;
99 const TClass* TMethodWrapperImpl::fgClass = 0;
143 ClassImp(TDocParser);
145 std::set<std::string> TDocParser::fgKeywords;
150 TDocParser::TDocParser(TClassDocOutput& docOutput, TClass* cl):
151 fHtml(docOutput.GetHtml()), fDocOutput(&docOutput), fLineNo(0),
152 fCurrentClass(cl), fRecentClass(0), fCurrentModule(0),
153 fDirectiveCount(0), fLineNumber(0), fDocContext(kIgnore),
154 fCheckForMethod(kFALSE), fClassDocState(kClassDoc_Uninitialized),
155 fCommentAtBOL(kFALSE), fAllowDirectives(kTRUE)
159 fSourceInfoTags[kInfoLastUpdate] = fHtml->GetLastUpdateTag();
160 fSourceInfoTags[kInfoAuthor] = fHtml->GetAuthorTag();
161 fSourceInfoTags[kInfoCopyright] = fHtml->GetCopyrightTag();
163 fClassDescrTag = fHtml->GetClassDocTag();
165 TMethodWrapperImpl::SetClass(cl);
167 for (
int ia = 0; ia < 3; ++ia) {
168 fMethods[ia].Rehash(101);
171 AddClassMethodsRecursively(0);
172 AddClassDataMembersRecursively(0);
175 fParseContext.push_back(kCode);
179 TIter nextMethod(fCurrentClass->GetListOfMethods());
180 fMethodCounts.clear();
181 while ((method = (TMethod *) nextMethod())) {
182 ++fMethodCounts[method->GetName()];
190 TDocParser::TDocParser(TDocOutput& docOutput):
191 fHtml(docOutput.GetHtml()), fDocOutput(&docOutput), fLineNo(0),
192 fCurrentClass(0), fRecentClass(0), fDirectiveCount(0),
193 fLineNumber(0), fDocContext(kIgnore),
194 fCheckForMethod(kFALSE), fClassDocState(kClassDoc_Uninitialized),
195 fCommentAtBOL(kFALSE), fAllowDirectives(kFALSE)
199 fSourceInfoTags[kInfoLastUpdate] = fHtml->GetLastUpdateTag();
200 fSourceInfoTags[kInfoAuthor] = fHtml->GetAuthorTag();
201 fSourceInfoTags[kInfoCopyright] = fHtml->GetCopyrightTag();
203 fClassDescrTag = fHtml->GetClassDocTag();
205 TMethodWrapperImpl::SetClass(0);
211 TDocParser::~TDocParser()
214 for (std::map<std::string, Int_t>::const_iterator iMethod = fMethodCounts.begin();
215 iMethod != fMethodCounts.end(); ++iMethod)
217 Info(
"~TDocParser",
"Implementation of method %s::%s could not be found.",
218 fCurrentClass ? fCurrentClass->GetName() :
"",
219 iMethod->first.c_str());
220 TIter iDirective(&fDirectiveHandlers);
221 TDocDirective* directive = 0;
222 while ((directive = (TDocDirective*) iDirective())) {
223 TString directiveName;
224 directive->GetName(directiveName);
225 Warning(
"~TDocParser",
"Missing \"%s\" for macro %s", directive->GetEndTag(), directiveName.Data());
235 void TDocParser::AddClassMethodsRecursively(TBaseClass* bc)
238 TClass *cl = fCurrentClass;
240 cl = bc->GetClassPointer(kFALSE);
244 TIter nextMethod(cl->GetListOfMethods());
245 std::map<std::string, int> methOverloads;
247 while ((method = (TMethod *) nextMethod())) {
249 if (!strcmp(method->GetName(),
"Dictionary") ||
250 !strcmp(method->GetName(),
"Class_Version") ||
251 !strcmp(method->GetName(),
"Class_Name") ||
252 !strcmp(method->GetName(),
"DeclFileName") ||
253 !strcmp(method->GetName(),
"DeclFileLine") ||
254 !strcmp(method->GetName(),
"ImplFileName") ||
255 !strcmp(method->GetName(),
"ImplFileLine") ||
256 (bc && (method->GetName()[0] ==
'~'
257 || !strcmp(method->GetName(), method->GetReturnTypeName())))
263 if (kIsPrivate & method->Property())
265 else if (kIsProtected & method->Property())
267 else if (kIsPublic & method->Property())
271 if (mtype == 0)
continue;
272 if (bc->Property() & kIsPrivate)
274 else if ((bc->Property() & kIsProtected) && mtype == 2)
278 Bool_t hidden = kFALSE;
279 for (Int_t access = 0; !hidden && access < 3; ++access) {
280 TMethodWrapperImpl* other = (TMethodWrapperImpl*) fMethods[access].FindObject(method->GetName());
281 hidden |= (other) && (other->GetMethod()->GetClass() != method->GetClass());
284 fMethods[mtype].Add(
new TMethodWrapperImpl(method, methOverloads[method->GetName()]));
285 ++methOverloads[method->GetName()];
289 TIter iBase(cl->GetListOfBases());
290 TBaseClass* base = 0;
291 while ((base = (TBaseClass*)iBase()))
292 AddClassMethodsRecursively(base);
295 for (Int_t access = 0; access < 3; ++access) {
296 fMethods[access].SetOwner();
297 fMethods[access].Sort();
306 void TDocParser::AddClassDataMembersRecursively(TBaseClass* bc) {
308 TClass *cl = fCurrentClass;
310 cl = bc->GetClassPointer(kFALSE);
314 TIter nextDM(cl->GetListOfDataMembers());
316 while ((dm = (TDataMember *) nextDM())) {
317 if (!strcmp(dm->GetName(),
"fgIsA"))
320 if (kIsPrivate & dm->Property())
322 else if (kIsProtected & dm->Property())
324 else if (kIsPublic & dm->Property())
328 if (mtype == 0)
continue;
329 if (bc->Property() & kIsPrivate)
331 else if ((bc->Property() & kIsProtected) && mtype == 2)
335 const Int_t flagEnumConst = kIsEnum | kIsConstant | kIsStatic;
336 if ((dm->Property() & flagEnumConst) == flagEnumConst
337 && dm->GetDataType() && dm->GetDataType()->GetType() == kInt_t) {
360 fDataMembers[mtype].Add(dm);
363 TIter iBase(cl->GetListOfBases());
364 TBaseClass* base = 0;
365 while ((base = (TBaseClass*)iBase()))
366 AddClassDataMembersRecursively(base);
369 for (Int_t access = 0; access < 6; ++access) {
370 fDataMembers[access].SetOwner(kFALSE);
372 fDataMembers[access].Sort();
381 void TDocParser::AnchorFromLine(
const TString& line, TString& anchor) {
382 const char base64String[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
387 UInt_t hash = ::Hash(line);
390 anchor += base64String[hash % 52];
393 anchor += base64String[hash % 64];
402 void TDocParser::Convert(std::ostream& out, std::istream& in,
const char* relpath,
403 Bool_t isCode, Bool_t interpretDirectives)
406 fParseContext.clear();
407 if (isCode) fParseContext.push_back(kCode);
408 else fParseContext.push_back(kComment);
411 fLineRaw.ReadLine(in, kFALSE);
418 fLineSource = fLineRaw;
419 fLineStripped = fLineRaw;
420 Strip(fLineStripped);
422 DecorateKeywords(fLineSource);
428 if (!interpretDirectives) {
430 if (!InContext(kDirective)) {
431 GetDocOutput()->AdjustSourcePath(fLineSource, relpath);
432 out << fLineSource << std::endl;
436 if (fLineComment.Length() ) {
437 GetDocOutput()->AdjustSourcePath(fLineComment, relpath);
438 out << fLineComment << std::endl;
439 }
else if (!InContext(kDirective)) {
440 GetDocOutput()->AdjustSourcePath(fLineSource, relpath);
441 out << fLineSource << std::endl;
450 void TDocParser::DecorateKeywords(std::ostream& out,
const char *text)
453 DecorateKeywords(str);
463 void TDocParser::DecorateKeywords(TString& line)
465 std::list<TClass*> currentType;
474 currentType.push_back(0);
477 while (isspace((UChar_t)line[i]))
480 Ssiz_t startOfLine = i;
484 Ssiz_t copiedToCommentUpTo = 0;
486 if (InContext(kDirective) && fDirectiveHandlers.Last()) {
488 TDocDirective* directive = (TDocDirective*)fDirectiveHandlers.Last();
489 const char* endTag = directive->GetEndTag();
490 Ssiz_t posEndTag = i;
491 while (kNPOS != (posEndTag = line.Index(endTag, posEndTag, TString::kIgnoreCase)))
492 if (posEndTag == 0 || line[posEndTag - 1] !=
'"')
494 if (posEndTag != kNPOS)
498 if (!InContext(kComment) || (InContext(kComment) & kCXXComment)) {
500 while (isspace((UChar_t)fLineRaw[start])) ++start;
501 if (fLineRaw[start] ==
'/' && fLineRaw[start + 1] ==
'/')
505 directive->AddLine(fLineRaw(start, fLineRaw.Length()));
506 while(i < line.Length())
507 fDocOutput->ReplaceSpecialChars(line, i);
508 copiedToCommentUpTo = i;
512 for (; i < line.Length(); ++i) {
514 if (!currentType.back())
518 if (Context() == kCode
519 || Context() == kComment) {
520 if (currentType.back())
523 if (line[i + 1] ==
':') {
530 if (line[i + 1] ==
'>') {
537 if (line[i + 1] !=
'.') {
546 currentType.push_back(0);
551 if (currentType.size() > 1)
552 currentType.pop_back();
557 if (i >= line.Length())
560 currentType.back() = 0;
563 if (!IsWord(line[i])){
565 Bool_t haveHtmlEscapedChar = Context() == kString
566 && i > 2 && line[i] ==
'\'' && line[i-1] ==
';';
567 if (haveHtmlEscapedChar) {
568 Ssiz_t posBegin = i - 2;
569 while (posBegin > 0 && IsWord(line[posBegin]))
571 haveHtmlEscapedChar = posBegin > 0 &&
572 line[posBegin] ==
'&' && line[posBegin - 1] ==
'\'';
574 EParseContext context = Context();
575 Bool_t closeString = context == kString
578 && ( (i > 1 && line[i - 2] ==
'\'')
579 || (i > 3 && line[i - 2] ==
'\\' && line[i - 3] ==
'\'')))
580 || haveHtmlEscapedChar)
581 && (i == 0 || line[i - 1] !=
'\\');
582 if (context == kCode || context == kComment) {
583 if (line[i] ==
'"' || (line[i] ==
'\'' && (
585 (line.Length() > i + 2 && line[i + 2] ==
'\'') ||
587 (line.Length() > i + 3 && line[i + 1] ==
'\'' && line[i + 3] ==
'\'')))) {
589 fDocOutput->DecorateEntityBegin(line, i, kString);
590 fParseContext.push_back(kString);
591 currentType.back() = 0;
592 closeString = kFALSE;
593 }
else if (context == kCode
594 && line[i] ==
'/' && (line[i+1] ==
'/' || line[i+1] ==
'*')) {
595 fParseContext.push_back(kComment);
596 if (line[i+1] ==
'/')
597 fParseContext.back() |= kCXXComment;
598 currentType.back() = 0;
599 fDocOutput->DecorateEntityBegin(line, i, kComment);
601 }
else if (context == kComment
602 && !(fParseContext.back() & kCXXComment)
603 && line.Length() > i + 1
604 && line[i] ==
'*' && line[i+1] ==
'/') {
605 if (fParseContext.size()>1)
606 fParseContext.pop_back();
608 currentType.back() = 0;
610 fDocOutput->DecorateEntityEnd(line, i, kComment);
611 if (!fCommentAtBOL) {
612 if (InContext(kDirective))
613 ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(line(copiedToCommentUpTo, i));
615 fLineComment += line(copiedToCommentUpTo, i);
616 copiedToCommentUpTo = i;
618 }
else if (startOfLine == i
620 && context == kCode) {
621 ExpandCPPLine(line, i);
625 if (i < line.Length())
626 fDocOutput->ReplaceSpecialChars(line, i);
629 fDocOutput->DecorateEntityEnd(line, i, kString);
630 if (fParseContext.size()>1)
631 fParseContext.pop_back();
633 currentType.back() = 0;
642 while (endWord < line.Length() && IsName(line[endWord]))
645 if (Context() == kString || Context() == kCPP) {
651 TString word(line(i, endWord - i));
654 if ((i == 0 || (i > 0 && line[i - 1] !=
'"'))
655 && HandleDirective(line, i, word, copiedToCommentUpTo)) {
657 currentType.back() = 0;
662 if (Context() == kCode
663 && fgKeywords.find(word.Data()) != fgKeywords.end()) {
664 fDocOutput->DecorateEntityBegin(line, i, kKeyword);
666 fDocOutput->DecorateEntityEnd(line, i, kKeyword);
668 currentType.back() = 0;
679 TDataType* subType = 0;
680 TClass* subClass = 0;
681 TDataMember *datamem = 0;
683 const char* globalTypeName = 0;
684 if (currentType.empty()) {
685 Warning(
"DecorateKeywords",
"type context is empty!");
686 currentType.push_back(0);
688 TClass* lookupScope = currentType.back();
690 if (scoping == kNada) {
692 lookupScope = fCurrentClass;
694 lookupScope = fRecentClass;
697 if (scoping == kNada) {
698 subType = gROOT->GetType(word);
700 subClass = fHtml->GetClass(word);
701 if (!subType && !subClass) {
702 TGlobal *global = gROOT->GetGlobal(word);
705 globalTypeName = global->GetTypeName();
706 subClass = fHtml->GetClass(globalTypeName);
708 subType = gROOT->GetType(globalTypeName);
710 if (subClass == THtml::Class() && word !=
"gHtml")
714 if (!subType && !subClass) {
719 if (!subType && !subClass) {
721 while (isspace(line[endWord])) ++endWord;
722 if (line[endWord] ==
'<' || line[endWord] ==
'>') {
724 Ssiz_t endWordT = endWord + 1;
725 int templateLevel = 1;
726 while (endWordT < line.Length()
728 || IsName(line[endWordT])
729 || line[endWordT] ==
'<'
730 || line[endWordT] ==
'>')) {
731 if (line[endWordT] ==
'<')
733 else if (line[endWordT] ==
'>')
737 subClass = fHtml->GetClass(line(i, endWordT - i).Data());
739 word = line(i, endWordT - i);
744 if (lookupScope && !subType && !subClass) {
745 if (scoping == kScope) {
746 TString subClassName(lookupScope->GetName());
747 subClassName +=
"::";
748 subClassName += word;
749 subClass = fHtml->GetClass(subClassName);
751 subType = gROOT->GetType(subClassName);
753 if (!subClass && !subType) {
755 datamem = lookupScope->GetDataMember(word);
757 meth = lookupScope->GetMethodAllAny(word);
759 if (!subClass && !subType && !datamem && !meth) {
761 while (isspace(line[endWord])) ++endWord;
762 if (line[endWord] ==
'<' || line[endWord] ==
'>') {
764 Ssiz_t endWordT = endWord + 1;
765 int templateLevel = 1;
766 while (endWordT < line.Length()
768 || IsName(line[endWordT])
769 || line[endWordT] ==
'<'
770 || line[endWordT] ==
'>')) {
771 if (line[endWordT] ==
'<')
773 else if (line[endWordT] ==
'>')
777 TString subClassName(lookupScope->GetName());
778 subClassName +=
"::";
779 subClassName += line(i, endWordT - i);
780 subClass = fHtml->GetClass(subClassName);
782 word = line(i, endWordT - i);
787 TString mangledWord(word);
788 fDocOutput->ReplaceSpecialChars(mangledWord);
789 line.Replace(i, word.Length(), mangledWord);
791 TSubString substr(line(i, mangledWord.Length()));
793 fDocOutput->ReferenceEntity(substr, subType,
794 globalTypeName ? globalTypeName : subType->GetName());
795 currentType.back() = 0;
796 }
else if (subClass) {
797 fDocOutput->ReferenceEntity(substr, subClass,
798 globalTypeName ? globalTypeName : subClass->GetName());
800 currentType.back() = subClass;
801 fRecentClass = subClass;
802 }
else if (datamem || meth) {
804 fDocOutput->ReferenceEntity(substr, datamem);
806 if (datamem->GetTypeName())
807 currentType.back() = fHtml->GetClass(datamem->GetTypeName());
809 fDocOutput->ReferenceEntity(substr, meth);
811 TString retTypeName = meth->GetReturnTypeName();
812 if (retTypeName.BeginsWith(
"const "))
813 retTypeName.Remove(0,6);
815 while (IsWord(retTypeName[pos]) || retTypeName[pos]==
'<' || retTypeName[pos]==
'>' || retTypeName[pos]==
':')
817 retTypeName.Remove(pos, retTypeName.Length());
818 if (retTypeName.Length())
819 currentType.back() = fHtml->GetClass(retTypeName);
822 currentType.back() = 0;
825 i += substr.Length();
829 if (i > line.Length())
833 if (Context() == kString) {
834 fDocOutput->DecorateEntityEnd(line, i, kString);
835 if (fParseContext.size()>1)
836 fParseContext.pop_back();
837 currentType.back() = 0;
844 if ((InContext(kComment) || fCommentAtBOL) && copiedToCommentUpTo < line.Length()) {
845 if (InContext(kDirective))
846 ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(line(copiedToCommentUpTo, line.Length()));
848 fLineComment += line(copiedToCommentUpTo, line.Length());
854 if (InContext(kComment) & kCXXComment) {
855 fDocOutput->DecorateEntityEnd(line, i, kComment);
856 if (fLineComment.Length()) {
857 Ssiz_t pos = fLineComment.Length();
858 fDocOutput->DecorateEntityEnd(fLineComment, pos, kComment);
860 RemoveCommentContext(kTRUE);
861 currentType.back() = 0;
869 void TDocParser::DecrementMethodCount(
const char* name)
871 typedef std::map<std::string , Int_t > MethodCount_t;
872 MethodCount_t::iterator iMethodName = fMethodCounts.find(name);
873 if (iMethodName != fMethodCounts.end()) {
874 --(iMethodName->second);
875 if (iMethodName->second <= 0)
876 fMethodCounts.erase(iMethodName);
884 void TDocParser::DeleteDirectiveOutput()
const
886 TIter iClass(gROOT->GetListOfClasses());
888 while ((cl = (TClass*) iClass()))
889 if (cl != TDocDirective::Class()
890 && cl->InheritsFrom(TDocDirective::Class())) {
891 TDocDirective* directive = (TDocDirective*) cl->New();
892 if (!directive)
continue;
893 directive->SetParser(const_cast<TDocParser*>(
this));
894 directive->DeleteOutput();
911 void TDocParser::ExpandCPPLine(TString& line, Ssiz_t& pos)
913 Bool_t linkExist = kFALSE;
914 Ssiz_t posEndOfLine = line.Length();
915 Ssiz_t posHash = pos;
917 Ssiz_t posInclude = line.Index(
"include", pos);
918 if (posInclude != kNPOS) {
920 Ssiz_t posStartFilename = posInclude + 7;
921 if (line.Tokenize(filename, posStartFilename,
"[<\"]")) {
922 Ssiz_t posEndFilename = posStartFilename;
923 if (line.Tokenize(filename, posEndFilename,
"[>\"]")) {
924 R__LOCKGUARD(fHtml->GetMakeClassMutex());
926 TString filesysFileName;
927 if (fHtml->GetPathDefinition().GetFileNameFromInclude(filename, filesysFileName)) {
928 fDocOutput->CopyHtmlFile(filesysFileName);
930 TString endOfLine(line(posEndFilename - 1, line.Length()));
931 line.Remove(posStartFilename, line.Length());
932 for (Ssiz_t i = pos; i < line.Length();)
933 fDocOutput->ReplaceSpecialChars(line, i);
935 line +=
"<a href=\"./";
936 line += gSystem->BaseName(filename);
938 line += filename +
"</a>" + endOfLine[0];
939 posEndOfLine = line.Length() - 1;
940 fDocOutput->ReplaceSpecialChars(line, posEndOfLine);
942 line += endOfLine(1, endOfLine.Length());
951 fDocOutput->ReplaceSpecialChars(line);
952 posEndOfLine = line.Length();
955 Ssiz_t posHashAfterDecoration = posHash;
956 fDocOutput->DecorateEntityBegin(line, posHashAfterDecoration, kCPP);
957 posEndOfLine += posHashAfterDecoration - posHash;
959 fDocOutput->DecorateEntityEnd(line, posEndOfLine, kCPP);
967 void TDocParser::GetCurrentModule(TString& out_module)
const {
968 if (fCurrentModule) out_module = fCurrentModule;
969 else if (fCurrentClass) fHtml->GetModuleNameForClass(out_module, fCurrentClass);
970 else out_module =
"(UNKNOWN MODULE WHILE PARSING)";
977 Bool_t TDocParser::HandleDirective(TString& line, Ssiz_t& pos, TString& word,
978 Ssiz_t& copiedToCommentUpTo)
980 Bool_t begin = kTRUE;
981 TClass* clDirective = IsDirective(line, pos, word, begin);
988 TDocDirective* directive = 0;
992 if (InContext(kDirective))
993 ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(fLineSource(copiedToCommentUpTo, pos - copiedToCommentUpTo));
995 fLineComment += fLineSource(copiedToCommentUpTo, pos - copiedToCommentUpTo);
996 copiedToCommentUpTo = pos;
998 pos += word.Length();
1000 directive = (TDocDirective*) clDirective->New();
1004 directive->SetParser(
this);
1005 if (fCurrentMethodTag.Length())
1006 directive->SetTag(fCurrentMethodTag);
1007 directive->SetCounter(fDirectiveCount++);
1011 if (begin && line[pos] ==
'(') {
1012 std::list<char> waitForClosing;
1013 Ssiz_t endParam = pos + 1;
1014 for (; endParam < line.Length()
1015 && (line[endParam] !=
')' || !waitForClosing.empty()); ++endParam) {
1016 const char c = line[endParam];
1017 if (!waitForClosing.empty() && waitForClosing.back() == c) {
1018 waitForClosing.pop_back();
1023 if (waitForClosing.empty() || waitForClosing.back() !=
'\'')
1024 waitForClosing.push_back(
'"');
1027 if (waitForClosing.empty() || waitForClosing.back() !=
'"')
1028 waitForClosing.push_back(
'\'');
1031 if (waitForClosing.empty() || (waitForClosing.back() !=
'"' && waitForClosing.back() !=
'\''))
1032 waitForClosing.push_back(
')');
1040 if (waitForClosing.empty()) {
1041 params = line(pos + 1, endParam - (pos + 1));
1042 pos += params.Length() + 2;
1044 directive->SetParameters(params);
1048 Ssiz_t posEndTag = pos;
1049 const char* endTag = directive->GetEndTag();
1050 Ssiz_t lenEndTag = strlen(endTag);
1051 while (kNPOS != (posEndTag = line.Index(endTag, posEndTag, TString::kIgnoreCase))) {
1052 if (line[posEndTag - 1] ==
'"') {
1053 posEndTag += lenEndTag;
1058 if (posEndTag != kNPOS) {
1061 fDirectiveHandlers.AddLast(directive);
1063 fParseContext.push_back(kDirective);
1064 if (InContext(kComment) & kCXXComment)
1065 fParseContext.back() |= kCXXComment;
1067 posEndTag = line.Length();
1070 directive->AddLine(line(pos, posEndTag - pos));
1071 TString remainder(line(posEndTag, line.Length()));
1072 line.Remove(posEndTag, line.Length());
1074 while (pos < line.Length())
1075 fDocOutput->ReplaceSpecialChars(line, pos);
1077 pos = line.Length();
1079 copiedToCommentUpTo = line.Length();
1087 pos += word.Length();
1088 else pos += word.Length() - 2;
1090 if (!directive) directive = (TDocDirective*) fDirectiveHandlers.Last();
1093 Warning(
"HandleDirective",
"Cannot find directive handler object %s !",
1100 if (!InContext(kComment) || (InContext(kComment) & kCXXComment)) {
1102 while (isspace((UChar_t)fLineRaw[start])) ++start;
1103 if (fLineRaw[start] ==
'/' && fLineRaw[start + 1] ==
'/')
1107 directive->AddLine(line(start, pos - word.Length() - start));
1109 TString remainder(line(pos, line.Length()));
1110 line.Remove(pos, line.Length());
1111 fDocOutput->ReplaceSpecialChars(line);
1112 pos = line.Length();
1115 copiedToCommentUpTo = pos;
1118 directive->GetResult(result);
1121 fDirectiveHandlers.Remove(fDirectiveHandlers.LastLink());
1126 Bool_t isInCxxComment = InContext(kDirective) & kCXXComment;
1127 if (fParseContext.size()>1)
1128 fParseContext.pop_back();
1129 if (isInCxxComment && !InContext(kComment)) {
1130 fParseContext.push_back(kComment | kCXXComment);
1131 fDocOutput->DecorateEntityBegin(line, pos, kComment);
1135 if (InContext(kDirective) && fDirectiveHandlers.Last())
1136 ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(result(0, result.Length()));
1138 fLineComment += result;
1158 UInt_t TDocParser::InContext(Int_t context)
const
1160 UInt_t lowerContext = context & kParseContextMask;
1161 UInt_t contextFlag = context & kParseContextFlagMask;
1163 for (std::list<UInt_t>::const_reverse_iterator iPC = fParseContext.rbegin();
1164 iPC != fParseContext.rend(); ++iPC)
1165 if (!lowerContext || ((lowerContext && ((*iPC & kParseContextMask) == lowerContext))
1166 && (!contextFlag || (contextFlag && (*iPC & contextFlag)))))
1175 void TDocParser::InitKeywords()
const
1177 if (!fgKeywords.empty())
1180 fgKeywords.insert(
"asm");
1181 fgKeywords.insert(
"auto");
1182 fgKeywords.insert(
"bool");
1183 fgKeywords.insert(
"break");
1184 fgKeywords.insert(
"case");
1185 fgKeywords.insert(
"catch");
1186 fgKeywords.insert(
"char");
1187 fgKeywords.insert(
"class");
1188 fgKeywords.insert(
"const");
1189 fgKeywords.insert(
"const_cast");
1190 fgKeywords.insert(
"continue");
1191 fgKeywords.insert(
"default");
1192 fgKeywords.insert(
"delete");
1193 fgKeywords.insert(
"do");
1194 fgKeywords.insert(
"double");
1195 fgKeywords.insert(
"dynamic_cast");
1196 fgKeywords.insert(
"else");
1197 fgKeywords.insert(
"enum");
1198 fgKeywords.insert(
"explicit");
1199 fgKeywords.insert(
"export");
1200 fgKeywords.insert(
"extern");
1201 fgKeywords.insert(
"false");
1202 fgKeywords.insert(
"float");
1203 fgKeywords.insert(
"for");
1204 fgKeywords.insert(
"friend");
1205 fgKeywords.insert(
"goto");
1206 fgKeywords.insert(
"if");
1207 fgKeywords.insert(
"inline");
1208 fgKeywords.insert(
"int");
1209 fgKeywords.insert(
"long");
1210 fgKeywords.insert(
"mutable");
1211 fgKeywords.insert(
"namespace");
1212 fgKeywords.insert(
"new");
1213 fgKeywords.insert(
"operator");
1214 fgKeywords.insert(
"private");
1215 fgKeywords.insert(
"protected");
1216 fgKeywords.insert(
"public");
1217 fgKeywords.insert(
"register");
1218 fgKeywords.insert(
"reinterpret_cast");
1219 fgKeywords.insert(
"return");
1220 fgKeywords.insert(
"short");
1221 fgKeywords.insert(
"signed");
1222 fgKeywords.insert(
"sizeof");
1223 fgKeywords.insert(
"static");
1224 fgKeywords.insert(
"static_cast");
1225 fgKeywords.insert(
"struct");
1226 fgKeywords.insert(
"switch");
1227 fgKeywords.insert(
"template");
1228 fgKeywords.insert(
"this");
1229 fgKeywords.insert(
"throw");
1230 fgKeywords.insert(
"true");
1231 fgKeywords.insert(
"try");
1232 fgKeywords.insert(
"typedef");
1233 fgKeywords.insert(
"typeid");
1234 fgKeywords.insert(
"typename");
1235 fgKeywords.insert(
"union");
1236 fgKeywords.insert(
"unsigned");
1237 fgKeywords.insert(
"using");
1238 fgKeywords.insert(
"virtual");
1239 fgKeywords.insert(
"void");
1240 fgKeywords.insert(
"volatile");
1241 fgKeywords.insert(
"wchar_t");
1242 fgKeywords.insert(
"while");
1253 TClass* TDocParser::IsDirective(
const TString& line, Ssiz_t pos,
1254 const TString& word, Bool_t& begin)
const
1257 if (pos > 0 && line[pos - 1] ==
'"')
1260 begin = word.BeginsWith(
"begin_", TString::kIgnoreCase);
1261 Bool_t end = word.BeginsWith(
"end_", TString::kIgnoreCase);
1271 TString tag = word( begin ? 6 : 4, word.Length());
1277 tag[0] -=
'a' -
'A';
1278 tag.Prepend(
"TDoc");
1281 TClass* clDirective = TClass::GetClass(tag, kFALSE);
1283 if (gDebug > 0 && !clDirective)
1284 Warning(
"IsDirective",
"Unknown THtml directive %s in line %d!", word.Data(), fLineNo);
1301 Bool_t TDocParser::IsName(UChar_t c)
1303 Bool_t ret = kFALSE;
1305 if (isalnum(c) || c ==
'_' || c ==
'~')
1324 Bool_t TDocParser::IsWord(UChar_t c)
1326 Bool_t ret = kFALSE;
1328 if (isalpha(c) || c ==
'_' || c ==
'~')
1343 TMethod* TDocParser::LocateMethodInCurrentLine(Ssiz_t &posMethodName, TString& ret,
1344 TString& name, TString& params,
1345 Bool_t& isconst, std::ostream &srcOut,
1346 TString &anchor, std::ifstream& sourceFile,
1347 Bool_t allowPureVirtual)
1349 typedef std::map<std::string , Int_t > MethodCount_t;
1352 if (posMethodName == kNPOS) {
1355 Ssiz_t posBlock = fLineRaw.Index(
'{');
1356 Ssiz_t posQuote = fLineRaw.Index(
'"');
1357 if (posQuote != kNPOS && (posBlock == kNPOS || posQuote < posBlock))
1358 posBlock = posQuote;
1359 if (posBlock == kNPOS)
1360 posBlock = fLineRaw.Length();
1361 for (MethodCount_t::iterator iMethodName = fMethodCounts.begin();
1362 !name.Length() && iMethodName != fMethodCounts.end(); ++iMethodName) {
1363 TString lookFor(iMethodName->first);
1364 posMethodName = fLineRaw.Index(lookFor);
1365 if (posMethodName != kNPOS && posMethodName < posBlock
1366 && (posMethodName == 0 || !IsWord(fLineRaw[posMethodName - 1]))) {
1369 Ssiz_t posMethodEnd = posMethodName + lookFor.Length();
1370 while (isspace((UChar_t)fLineRaw[posMethodEnd])) ++posMethodEnd;
1371 if (fLineRaw[posMethodEnd] ==
'(') {
1372 meth = LocateMethodInCurrentLine(posMethodName, ret, name, params, isconst,
1373 srcOut, anchor, sourceFile, allowPureVirtual);
1382 name = fLineRaw(posMethodName, fLineRaw.Length() - posMethodName);
1385 ret = fLineRaw(0, posMethodName);
1387 while (ret.Length() && (IsName(ret[ret.Length() - 1]) || ret[ret.Length()-1] ==
':'))
1388 ret.Remove(ret.Length() - 1, 1);
1390 Bool_t didSomething = kTRUE;
1391 while (didSomething) {
1392 didSomething = kFALSE;
1393 if (ret.BeginsWith(
"inline ")) {
1394 didSomething = kTRUE;
1397 if (ret.BeginsWith(
"static ")) {
1398 didSomething = kTRUE;
1401 if (ret.BeginsWith(
"virtual ")) {
1402 didSomething = kTRUE;
1410 Ssiz_t posParam = name.First(
'(');
1411 if (posParam == kNPOS ||
1413 ret.Contains(
"{") || ret.Contains(
"}") || ret.Contains(
"(") || ret.Contains(
")")
1414 || ret.Contains(
"=")) {
1421 if (name.BeginsWith(
"operator")) {
1423 Ssiz_t checkOpBracketParam = posParam + 1;
1424 while (isspace((UChar_t)name[checkOpBracketParam]))
1425 ++checkOpBracketParam;
1426 if (name[checkOpBracketParam] ==
')') {
1427 ++checkOpBracketParam;
1428 while (isspace((UChar_t)name[checkOpBracketParam]))
1429 ++checkOpBracketParam;
1430 if (name[checkOpBracketParam] ==
'(')
1431 posParam = checkOpBracketParam;
1435 if (posParam == kNPOS) {
1442 params = name(posParam, name.Length() - posParam);
1443 name.Remove(posParam);
1444 while (name.Length() && isspace((UChar_t)name[name.Length() - 1]))
1445 name.Remove(name.Length() - 1);
1446 if (!name.Length()) {
1453 MethodCount_t::const_iterator iMethodName = fMethodCounts.find(name.Data());
1454 if (iMethodName == fMethodCounts.end() || iMethodName->second <= 0) {
1462 Ssiz_t posParamEnd = 1;
1463 Int_t bracketLevel = 1;
1464 while (bracketLevel) {
1465 const char* paramEnd = strpbrk(params.Data() + posParamEnd,
")(\"'");
1469 if (!anchor.Length()) {
1471 AnchorFromLine(fLineStripped, anchor);
1473 srcOut <<
"<a name=\"" << anchor <<
"\"></a>";
1477 WriteSourceLine(srcOut);
1479 fLineRaw.ReadLine(sourceFile, kFALSE);
1480 if (sourceFile.eof()) {
1481 Error(
"LocateMethodInCurrentLine",
1482 "Cannot find end of signature for function %s!",
1487 fCommentAtBOL = kFALSE;
1490 fLineStripped = fLineRaw;
1491 Strip(fLineStripped);
1493 fLineSource = fLineRaw;
1494 DecorateKeywords(fLineSource);
1496 posParamEnd = params.Length();
1499 posParamEnd = paramEnd - params.Data();
1500 switch (params[posParamEnd]) {
1501 case '(': ++bracketLevel; ++posParamEnd;
break;
1502 case ')': --bracketLevel; ++posParamEnd;
break;
1505 while (params.Length() > posParamEnd && params[posParamEnd] !=
'"') {
1507 if (params[posParamEnd] ==
'\\') ++posParamEnd;
1510 if (params.Length() <= posParamEnd) {
1521 if (params[posParamEnd] ==
'\\') ++posParamEnd;
1530 TString pastParams(params(posParamEnd, params.Length()));
1531 pastParams = pastParams.Strip(TString::kLeading);
1532 isconst = pastParams.BeginsWith(
"const") && !(isalnum(pastParams[5]) || pastParams[5] ==
'_');
1535 Ssiz_t posBlock = params.Index(
'{', posParamEnd);
1536 Ssiz_t posSemicolon = params.Index(
';', posParamEnd);
1537 Ssiz_t posPureVirt = params.Index(
'=', posParamEnd);
1538 if (posSemicolon != kNPOS)
1539 if ((posBlock == kNPOS || (posSemicolon < posBlock)) &&
1540 (posPureVirt == kNPOS || !allowPureVirtual)
1541 && !allowPureVirtual)
1544 if (params.Length())
1545 params.Remove(posParamEnd);
1547 if (!params.Length()) {
1553 posMethodName = posParam + posParamEnd;
1554 if (fCurrentClass) {
1555 TMethod* meth = fCurrentClass->GetMethodAny(name);
1557 fDirectiveCount = 0;
1558 fCurrentMethodTag = name +
"_";
1559 fCurrentMethodTag += fMethodCounts[name.Data()];
1573 void TDocParser::Parse(std::ostream& out)
1575 fClassDocState = kClassDoc_LookingNothingFound;
1577 DeleteDirectiveOutput();
1579 LocateMethodsInSource(out);
1580 LocateMethodsInHeaderInline(out);
1581 LocateMethodsInHeaderClassDecl(out);
1583 if (!fSourceInfo[kInfoLastUpdate].Length()) {
1585 fSourceInfo[kInfoLastUpdate] = date.AsString();
1607 void TDocParser::LocateMethods(std::ostream& out,
const char* filename,
1608 Bool_t lookForSourceInfo ,
1609 Bool_t useDocxxStyle ,
1610 Bool_t allowPureVirtual ,
1611 const char* methodPattern ,
1612 const char* sourceExt )
1614 TString sourceFileName(filename);
1615 fCurrentFile = filename;
1616 if (!sourceFileName.Length()) {
1617 fHtml->GetImplFileName(fCurrentClass, kFALSE, sourceFileName);
1618 Error(
"LocateMethods",
"Can't find source file '%s' for class %s!",
1619 sourceFileName.Data(), fCurrentClass->GetName());
1622 std::ifstream sourceFile(sourceFileName.Data());
1623 if (!sourceFile || !sourceFile.good()) {
1624 Error(
"LocateMethods",
"Can't open file '%s' for reading!", sourceFileName.Data());
1628 TPMERegexp patternRE(methodPattern ? methodPattern :
"");
1630 TString codeOneLiner;
1633 TString methodParam;
1634 Bool_t methodIsConst = kFALSE;
1636 TString docxxComment;
1638 Bool_t wroteMethodNowWaitingForOpenBlock = kFALSE;
1640 std::ofstream srcHtmlOut;
1641 TString srcHtmlOutName;
1642 if (sourceExt && sourceExt[0]) {
1643 static_cast<TClassDocOutput*
>(fDocOutput)->CreateSourceOutputStream(srcHtmlOut, sourceExt, srcHtmlOutName);
1647 srcHtmlOutName = fCurrentClass->GetName();
1648 fDocOutput->NameSpace2FileName(srcHtmlOutName);
1649 gSystem->PrependPathName(
"src", srcHtmlOutName);
1650 srcHtmlOutName +=
".h.html";
1653 fParseContext.clear();
1654 fParseContext.push_back(kCode);
1655 fDocContext = kIgnore;
1658 while (!sourceFile.eof()) {
1659 Bool_t needAnchor = kFALSE;
1663 fLineRaw.ReadLine(sourceFile, kFALSE);
1664 if (sourceFile.eof())
break;
1666 fCommentAtBOL = InContext(kComment);
1669 fLineStripped = fLineRaw;
1670 Strip(fLineStripped);
1672 fLineSource = fLineRaw;
1674 DecorateKeywords(fLineSource);
1676 if (!ProcessComment()) {
1679 if (fDocContext == kDocClass && fClassDocState < kClassDoc_Written) {
1680 TString strippedComment(fComment);
1681 Strip(strippedComment);
1682 if (strippedComment.Length() > 0) {
1683 fLastClassDoc = fComment;
1684 if (fClassDocState == kClassDoc_LookingNothingFound) {
1685 fFirstClassDoc = fComment;
1686 fClassDocState = kClassDoc_LookingHaveSomething;
1689 fDocContext = kIgnore;
1692 Ssiz_t impIdx = fLineStripped.Index(
"ClassImp(");
1693 if (impIdx == 0 && fClassDocState == kClassDoc_LookingHaveSomething) {
1694 TString name(fCurrentClass->GetName());
1696 Ssiz_t posLastScope = kNPOS;
1697 while ((posLastScope = name.Index(
"::")) != kNPOS)
1698 name.Remove(0, posLastScope + 2);
1700 Ssiz_t posName = fLineStripped.Index(name, impIdx);
1701 if (posName != kNPOS) {
1702 Ssiz_t posClosingParen = posName + name.Length();
1703 while (isspace(fLineStripped[posClosingParen])) ++posClosingParen;
1704 if (fLineStripped[posClosingParen] ==
')') {
1705 WriteClassDoc(out, kFALSE);
1706 fDocContext = kIgnore;
1711 if (fLineStripped.Length())
1717 if (methodName.Length() && !wroteMethodNowWaitingForOpenBlock) {
1718 TString savedComment;
1719 if (useDocxxStyle && docxxComment.Length()) {
1720 savedComment = fComment;
1721 fComment = docxxComment;
1723 WriteMethod(out, methodRet, methodName, methodParam, methodIsConst,
1724 gSystem->BaseName(srcHtmlOutName), anchor, codeOneLiner);
1725 docxxComment.Remove(0);
1726 if (savedComment[0]) {
1727 fComment = savedComment;
1731 if (!wroteMethodNowWaitingForOpenBlock) {
1733 Ssiz_t posPattern = kNPOS;
1734 if (methodPattern) {
1735 posPattern = fLineRaw.Index((TPRegexp&)patternRE);
1737 if (posPattern != kNPOS && methodPattern) {
1739 static const char vetoChars[] =
"{\"";
1740 for (
int ich = 0; posPattern != kNPOS && vetoChars[ich]; ++ich) {
1741 Ssiz_t posVeto = fLineRaw.Index(vetoChars[ich]);
1742 if (posVeto != kNPOS && posVeto < posPattern)
1746 if (posPattern != kNPOS || !methodPattern) {
1747 if (methodPattern) {
1748 patternRE.Match(fLineRaw);
1749 posPattern += patternRE[0].Length();
1751 LocateMethodInCurrentLine(posPattern, methodRet, methodName,
1752 methodParam, methodIsConst, srcHtmlOut,
1753 anchor, sourceFile, allowPureVirtual);
1754 if (methodName.Length()) {
1755 fDocContext = kDocFunc;
1756 needAnchor = !anchor.Length();
1758 docxxComment = fComment;
1760 codeOneLiner.Remove(0);
1762 wroteMethodNowWaitingForOpenBlock = fLineRaw.Index(
"{", posPattern) == kNPOS;
1763 wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index(
";", posPattern) == kNPOS;
1764 }
else if (fLineRaw.First(
"{};") != kNPOS)
1771 wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index(
"{") == kNPOS;
1772 wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index(
";") == kNPOS;
1775 if (methodName.Length() && !wroteMethodNowWaitingForOpenBlock) {
1777 if (!codeOneLiner.Length() &&
1778 fLineSource.CountChar(
'{') == 1 &&
1779 fLineSource.CountChar(
'}') == 1) {
1781 codeOneLiner = fLineSource;
1782 codeOneLiner.Remove(0, codeOneLiner.Index(
'{'));
1783 codeOneLiner.Remove(codeOneLiner.Index(
'}') + 1);
1787 else if (!methodName.Length() && !useDocxxStyle)
1790 if (needAnchor || fExtraLinesWithAnchor.find(fLineNo) != fExtraLinesWithAnchor.end()) {
1791 AnchorFromLine(fLineStripped, anchor);
1793 srcHtmlOut <<
"<a name=\"" << anchor <<
"\"></a>";
1799 Ssiz_t posTag = kNPOS;
1800 if (lookForSourceInfo)
1801 for (Int_t si = 0; si < (Int_t) kNumSourceInfos; ++si)
1802 if (!fSourceInfo[si].Length() && (posTag = fLineRaw.Index(fSourceInfoTags[si])) != kNPOS) {
1803 fSourceInfo[si] = fLineRaw(posTag + strlen(fSourceInfoTags[si]), fLineRaw.Length() - posTag);
1804 if (si == kInfoAuthor)
1805 fDocOutput->FixupAuthorSourceInfo(fSourceInfo[kInfoAuthor]);
1812 WriteSourceLine(srcHtmlOut);
1813 else if (needAnchor)
1814 fExtraLinesWithAnchor.insert(fLineNo);
1818 if (methodName.Length()) {
1819 if (useDocxxStyle && docxxComment.Length())
1820 fComment = docxxComment;
1821 WriteMethod(out, methodRet, methodName, methodParam, methodIsConst,
1822 gSystem->BaseName(srcHtmlOutName), anchor, codeOneLiner);
1823 docxxComment.Remove(0);
1827 srcHtmlOut <<
"</pre>" << std::endl;
1829 fDocOutput->WriteLineNumbers(srcHtmlOut, fLineNumber, gSystem->BaseName(fCurrentFile));
1831 srcHtmlOut <<
"</div>" << std::endl;
1833 fDocOutput->WriteHtmlFooter(srcHtmlOut,
"../");
1835 fParseContext.clear();
1836 fParseContext.push_back(kCode);
1837 fDocContext = kIgnore;
1846 void TDocParser::LocateMethodsInSource(std::ostream& out)
1849 Bool_t useDocxxStyle = (fHtml->GetDocStyle() ==
"Doc++");
1851 TString pattern(fCurrentClass->GetName());
1853 Ssiz_t posLastScope = kNPOS;
1854 while ((posLastScope = pattern.Index(
"::")) != kNPOS)
1855 pattern.Remove(0, posLastScope + 2);
1858 TString implFileName;
1859 if (fHtml->GetImplFileName(fCurrentClass, kTRUE, implFileName)) {
1860 LocateMethods(out, implFileName, kFALSE , useDocxxStyle,
1861 kFALSE , pattern,
".cxx.html");
1862 Ssiz_t posGt = pattern.Index(
'>');
1863 if (posGt != kNPOS) {
1865 Ssiz_t posLt = pattern.Index(
'<');
1866 if (posLt != kNPOS && posLt < posGt) {
1867 pattern.Replace(posLt + 1, posGt - posLt - 1,
".*");
1868 LocateMethods(out, implFileName, kFALSE , useDocxxStyle,
1869 kFALSE , pattern,
".cxx.html");
1879 void TDocParser::LocateMethodsInHeaderInline(std::ostream& out)
1882 Bool_t useDocxxStyle = kTRUE;
1884 TString pattern(fCurrentClass->GetName());
1886 Ssiz_t posLastScope = kNPOS;
1887 while ((posLastScope = pattern.Index(
"::")) != kNPOS)
1888 pattern.Remove(0, posLastScope + 1);
1891 TString declFileName;
1892 if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declFileName)) {
1893 LocateMethods(out, declFileName, kTRUE , useDocxxStyle,
1894 kFALSE , pattern, 0);
1895 Ssiz_t posGt = pattern.Index(
'>');
1896 if (posGt != kNPOS) {
1898 Ssiz_t posLt = pattern.Index(
'<');
1899 if (posLt != kNPOS && posLt < posGt) {
1900 pattern.Replace(posLt + 1, posGt - posLt - 1,
".*");
1901 LocateMethods(out, declFileName, kTRUE , useDocxxStyle,
1902 kFALSE , pattern, 0);
1913 void TDocParser::LocateMethodsInHeaderClassDecl(std::ostream& out)
1915 TString declFileName;
1916 if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declFileName))
1917 LocateMethods(out, declFileName, kTRUE, kTRUE ,
1918 kTRUE , 0,
".h.html");
1928 Bool_t TDocParser::ProcessComment()
1931 && !(fLineStripped[0] ==
'/'
1932 && (fLineStripped[1] ==
'/' || fLineStripped[1] ==
'*'))
1933 && !InContext(kComment) && !InContext(kDirective)) {
1942 if (InContext(kDirective) && !fLineComment.Length())
1945 TString commentLine(fLineComment.Strip());
1948 Bool_t mustDealWithCommentAtBOL = fCommentAtBOL;
1949 Ssiz_t posComment = kNPOS;
1951 posComment = commentLine.Index(
"<span class=\"comment\">", 0, TString::kIgnoreCase);
1952 Ssiz_t posSpanEnd = commentLine.Index(
"</span>", posComment == kNPOS?0:posComment, TString::kIgnoreCase);
1953 while ((mustDealWithCommentAtBOL && posSpanEnd != kNPOS) || posComment != kNPOS) {
1954 Int_t spanLevel = 1;
1955 Ssiz_t posSpan = commentLine.Index(
"<span", posComment + 1, TString::kIgnoreCase);
1956 while (spanLevel > 1 || (posSpan != kNPOS && posSpan < posSpanEnd)) {
1958 if (posSpan != kNPOS && posSpan < posSpanEnd) {
1960 posSpan = commentLine.Index(
"<span", posSpan + 1, TString::kIgnoreCase);
1966 posSpanEnd = commentLine.Index(
"</span>", posSpanEnd + 1, TString::kIgnoreCase);
1968 if (posSpanEnd != kNPOS) {
1970 commentLine.Remove(posSpanEnd, 7);
1971 if (posComment != kNPOS)
1972 commentLine.Remove(posComment, 22);
1974 mustDealWithCommentAtBOL = kFALSE;
1978 posComment = commentLine.Index(
"<span class=\"comment\">", posComment, TString::kIgnoreCase);
1981 if (posComment != kNPOS)
1982 commentLine.Remove(posComment, 22);
1985 if (!InContext(kComment) || (InContext(kComment) & kCXXComment)
1986 || (fLineStripped[0] ==
'/' && fLineStripped[1] ==
'*'))
1990 if ((fClassDocState == kClassDoc_LookingNothingFound
1991 || fClassDocState == kClassDoc_LookingHaveSomething)
1992 && !fComment.Length()
1993 && fDocContext == kIgnore && commentLine.Contains(fClassDescrTag)) {
1994 fDocContext = kDocClass;
1997 char start_or_end = 0;
1999 if (commentLine.Length()>1 && commentLine[0] ==
'/'
2000 && (commentLine[1] ==
'/' || commentLine[1] ==
'*')) {
2001 start_or_end = commentLine[1];
2002 commentLine.Remove(0, 2);
2005 if (start_or_end !=
'/' && commentLine.Length()>1
2006 && commentLine[commentLine.Length() - 2] ==
'*'
2007 && commentLine[commentLine.Length() - 1] ==
'/') {
2008 start_or_end = commentLine[commentLine.Length() - 2];
2009 commentLine.Remove(commentLine.Length()-2);
2013 if (start_or_end && commentLine.Length() > 3) {
2014 TString lineAllOneChar(commentLine.Strip());
2016 Ssiz_t len = lineAllOneChar.Length();
2018 Char_t c = lineAllOneChar[len - 1];
2019 if (c == lineAllOneChar[len - 2] && c == lineAllOneChar[len - 3]) {
2020 TString lineAllOneCharStripped = lineAllOneChar.Strip(TString::kTrailing, c);
2021 Strip(lineAllOneCharStripped);
2022 if (!lineAllOneCharStripped.Length()) {
2023 commentLine.Remove(0);
2026 if ((fClassDocState == kClassDoc_LookingNothingFound
2027 || fClassDocState == kClassDoc_LookingHaveSomething)
2028 && !fComment.Length()
2029 && fDocContext == kIgnore && start_or_end==
'/') {
2030 fDocContext = kDocClass;
2038 if (commentLine.Length() > 0 && start_or_end == commentLine[commentLine.Length() - 1])
2040 commentLine = commentLine.Strip(TString::kTrailing, start_or_end);
2042 if (commentLine.Length() > 2 && Context() != kDirective)
2043 while (commentLine.Length() > 2
2044 && !IsWord(commentLine[0])
2045 && commentLine[0] == commentLine[commentLine.Length() - 1])
2046 commentLine = commentLine.Strip(TString::kBoth, commentLine[0]);
2049 while (start_or_end && commentLine[0] == start_or_end)
2050 commentLine.Remove(0, 1);
2052 fComment += commentLine +
"\n";
2060 void TDocParser::RemoveCommentContext(Bool_t cxxcomment)
2062 UInt_t lookFor = kComment;
2063 if (cxxcomment) lookFor |= kCXXComment;
2064 std::list<UInt_t>::iterator iComment = fParseContext.end();
2065 for (std::list<UInt_t>::iterator iContext = fParseContext.begin();
2066 iContext != fParseContext.end(); ++ iContext)
2067 if (*iContext == lookFor) iComment =iContext;
2068 if (iComment != fParseContext.end())
2069 fParseContext.erase(iComment);
2075 Bool_t TDocParser::Strip(TString& str)
2077 Bool_t changed = str[0] ==
' ' || str[0] ==
'\t' || str[0] ==
'\n';
2078 changed |= str.Length()
2079 && (str[str.Length() - 1] ==
' ' || str[str.Length() - 1] ==
'\t'
2080 || str[str.Length() - 1] ==
'\n');
2081 if (!changed)
return kFALSE;
2083 while (str[i] ==
' ' || str[i] ==
'\t' || str[i] ==
'\n')
2086 i = str.Length() - 1;
2087 while (i >= 0 && (str[i] ==
' ' || str[i] ==
'\t' || str[i] ==
'\n'))
2089 str.Remove(i + 1, str.Length());
2096 void TDocParser::WriteClassDoc(std::ostream& out, Bool_t first )
2098 if (fClassDocState == kClassDoc_LookingHaveSomething || fClassDocState == kClassDoc_LookingNothingFound) {
2099 TString& classDoc = first || !fLastClassDoc.Length() ? fFirstClassDoc : fLastClassDoc;
2100 static_cast<TClassDocOutput*
>(fDocOutput)->WriteClassDescription(out, classDoc);
2101 fClassDocState = kClassDoc_Written;
2107 static void RemoveUnneededSpaces(TString& s) {
2110 for (Ssiz_t i = 1; i < s.Length() - 1; ++i) {
2114 if (((isalnum(p) || p ==
'_') && (isalnum(n) || n ==
'_'))
2115 || (p ==
'>' && n ==
'>')) {
2118 while (isspace(s[i])) {
2126 static void ParseParameters(TString& strippedParams, TList& paramArr) {
2131 bool quoted =
false;
2132 Ssiz_t len = strippedParams.Length();
2134 for (Ssiz_t i = 0; i < len; ++i) {
2135 switch (strippedParams[i]) {
2138 case '[': ++nest;
break;
2141 case ']': --nest;
break;
2142 case '=': init =
true;
break;
2143 case '\'': ++i;
if (strippedParams[i] ==
'\\') ++i; ++i;
continue;
2144 case '\\': ++i;
continue;
break;
2145 case '"': quoted = !quoted;
break;
2147 if (!quoted && !nest) {
2148 TString strippedArg(arg.Strip(TString::kBoth));
2149 paramArr.AddLast(
new TObjString(strippedArg));
2157 arg += strippedParams[i];
2160 TString strippedLastArg(arg.Strip(TString::kBoth));
2161 if (strippedLastArg.Length()) {
2162 paramArr.AddLast(
new TObjString(strippedLastArg));
2166 void MatchOverloadSignatures(TCollection* candidates, TList* paramArr)
2171 TIter iCandidate(candidates);
2172 int nparams = paramArr->GetSize();
2173 for (
int iparam = 0; iparam < nparams && candidates->GetSize() > 1; ++iparam) {
2174 TString& srcArg = ((TObjString*)paramArr->At(iparam))->String();
2175 TString noParName(srcArg);
2176 while (noParName.Length()
2177 && (isalnum(noParName[noParName.Length() - 1]) || noParName[noParName.Length() - 1] ==
'_'))
2178 noParName.Remove(noParName.Length() - 1);
2179 noParName = noParName.Strip(TString::kTrailing);
2181 if (noParName.Length()) {
2182 RemoveUnneededSpaces(noParName);
2184 RemoveUnneededSpaces(srcArg);
2189 for (
int comparison = 0; comparison < 5; ++comparison) {
2190 if (comparison == 1 && noParName == srcArg)
2195 TDocMethodWrapper* method = 0;
2196 while ((method = (TDocMethodWrapper*) iCandidate())) {
2197 TMethodArg* methArg = (TMethodArg*) method->GetMethod()->GetListOfMethodArgs()->At(iparam);
2198 TString sMethArg = methArg->GetFullTypeName();
2199 RemoveUnneededSpaces(sMethArg);
2200 bool matches =
false;
2201 switch (comparison) {
2202 case 0: matches = (srcArg == sMethArg);
break;
2203 case 1: matches = (noParName == sMethArg);
break;
2204 case 2: matches = srcArg.Contains(sMethArg) || sMethArg.Contains(srcArg);
break;
2207 suppressed.Add(method);
2210 if (suppressed.GetSize()
2211 && suppressed.GetSize() < candidates->GetSize()) {
2212 candidates->RemoveAll(&suppressed);
2215 if (!suppressed.GetSize()) {
2221 if (candidates->GetSize() > 1) {
2225 TDocMethodWrapper* method = 0;
2226 while ((method = (TDocMethodWrapper*) iCandidate())) {
2227 if (method->TestBit(TDocMethodWrapper::kDocumented)) {
2228 suppressed.AddLast(method);
2231 if (suppressed.GetSize()
2232 && suppressed.GetSize() < candidates->GetSize()) {
2233 candidates->RemoveAll(&suppressed);
2242 void TDocParser::WriteMethod(std::ostream& out, TString& ret,
2243 TString& name, TString& params, Bool_t isconst,
2244 const char* filename, TString& anchor,
2245 TString& codeOneLiner)
2248 if (fClassDocState < kClassDoc_Written)
2251 TString strippedParams(params);
2252 if (strippedParams[0] ==
'(') {
2253 strippedParams.Remove(0, 1);
2254 strippedParams.Remove(strippedParams.Length() - 1);
2255 strippedParams = strippedParams.Strip(TString::kBoth);
2259 paramArr.SetOwner();
2260 ParseParameters(strippedParams, paramArr);
2261 int nparams = paramArr.GetSize();
2265 for (
int access = 0; access < 3; ++access) {
2266 const TList* methList = fMethods[access].GetListForObject(name);
2267 if (!methList)
continue;
2269 TIter nextMethod(methList);
2270 TDocMethodWrapper* method = 0;
2271 while ((method = (TDocMethodWrapper *) nextMethod())) {
2272 if (name == method->GetName()
2273 && isconst == ((method->GetMethod()->Property() & kIsConstMethod) > 0)
2274 && method->GetMethod()->GetListOfMethodArgs()->GetSize() == nparams) {
2275 candidates.Add(method);
2280 if (nparams && candidates.GetSize() > 1) {
2281 MatchOverloadSignatures(&candidates, ¶mArr);
2284 TDocMethodWrapper* guessedMethod = 0;
2285 if (candidates.GetSize() == 1) {
2286 guessedMethod = (TDocMethodWrapper*) candidates.First();
2287 guessedMethod->SetBit(TDocMethodWrapper::kDocumented);
2290 static_cast<TClassDocOutput*
>(fDocOutput)->WriteMethod(out, ret, name, params, filename, anchor,
2291 fComment, codeOneLiner, guessedMethod);
2293 DecrementMethodCount(name);
2300 fDocContext = kIgnore;
2307 void TDocParser::WriteSourceLine(std::ostream& out)
2309 fDocOutput->AdjustSourcePath(fLineSource);
2310 out << fLineSource << std::endl;